internal/graphicsdriver/metal: support macOS 10.12 by removing packed types

From the Metal shading language specification [1] Table 2.2.3, attribute
variables in Ebitengine's vertices don't have to be packed. Then, we can
remove `packed` types.

[1] https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf

Closes #2107
This commit is contained in:
Hajime Hoshi 2022-05-28 22:47:06 +09:00
parent ac922742bf
commit 5c63c4a4aa
9 changed files with 36 additions and 49 deletions

View File

@ -30,7 +30,7 @@ import (
// It is because old Xcode (8 or older?) does not accept @available syntax.
// #cgo CFLAGS: -Wno-unguarded-availability-new
// #cgo !ios CFLAGS: -mmacosx-version-min=10.14
// #cgo !ios CFLAGS: -mmacosx-version-min=10.12
// #cgo LDFLAGS: -framework QuartzCore -framework Foundation -framework CoreGraphics
//
// #include "ca_darwin.h"

View File

@ -29,7 +29,7 @@ import (
)
// #cgo CFLAGS: -x objective-c
// #cgo !ios CFLAGS: -mmacosx-version-min=10.14
// #cgo !ios CFLAGS: -mmacosx-version-min=10.12
// #cgo LDFLAGS: -framework Foundation
//
// #import <Foundation/Foundation.h>
@ -56,9 +56,9 @@ const source = `#include <metal_stdlib>
using namespace metal;
struct VertexIn {
packed_float2 position;
packed_float2 tex;
packed_float4 color;
float2 position;
float2 tex;
float4 color;
};
struct VertexOut {

View File

@ -14,7 +14,7 @@
// Package mtl provides access to Apple's Metal API (https://developer.apple.com/documentation/metal).
//
// Package mtl requires macOS version 10.14 or newer.
// Package mtl requires macOS version 10.12 or newer.
//
// This package is in very early stages of development.
// The API will change when opportunities for improvement are discovered; it is not yet frozen.
@ -28,7 +28,7 @@ import (
"unsafe"
)
// #cgo !ios CFLAGS: -mmacosx-version-min=10.14
// #cgo !ios CFLAGS: -mmacosx-version-min=10.12
// #cgo LDFLAGS: -framework Metal -framework CoreGraphics -framework Foundation
//
// #include "mtl_darwin.h"

View File

@ -48,15 +48,11 @@ void *Device_MakeCommandQueue(void *device) {
struct Library Device_MakeLibrary(void *device, const char *source,
size_t sourceLength) {
NSError *error;
MTLCompileOptions* options = [[MTLCompileOptions alloc] init];
if (@available(macOS 10.14, iOS 12.0, *)) {
options.languageVersion = MTLLanguageVersion2_1;
}
id<MTLLibrary> library = [(id<MTLDevice>)device
newLibraryWithSource:[[NSString alloc] initWithBytes:source
length:sourceLength
encoding:NSUTF8StringEncoding]
options:options
options:NULL
error:&error];
struct Library l;

View File

@ -25,7 +25,7 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal/ca"
)
// #cgo !ios CFLAGS: -mmacosx-version-min=10.14
// #cgo !ios CFLAGS: -mmacosx-version-min=10.12
//
// #include "ns_darwin.h"
import "C"

View File

@ -1,7 +1,7 @@
struct Attributes {
packed_float2 M0;
packed_float2 M1;
packed_float4 M2;
float2 M0;
float2 M1;
float4 M2;
};
struct Varyings {

View File

@ -1,7 +1,7 @@
struct Attributes {
packed_float2 M0;
packed_float2 M1;
packed_float4 M2;
float2 M0;
float2 M1;
float4 M2;
};
struct Varyings {

View File

@ -72,7 +72,7 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
lines = append(lines, "")
lines = append(lines, "struct Attributes {")
for i, a := range p.Attributes {
lines = append(lines, fmt.Sprintf("\t%s;", c.varDecl(p, &a, fmt.Sprintf("M%d", i), true, false)))
lines = append(lines, fmt.Sprintf("\t%s;", c.varDecl(p, &a, fmt.Sprintf("M%d", i), false)))
}
lines = append(lines, "};")
}
@ -82,7 +82,7 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
lines = append(lines, "struct Varyings {")
lines = append(lines, "\tfloat4 Position [[position]];")
for i, v := range p.Varyings {
lines = append(lines, fmt.Sprintf("\t%s;", c.varDecl(p, &v, fmt.Sprintf("M%d", i), false, false)))
lines = append(lines, fmt.Sprintf("\t%s;", c.varDecl(p, &v, fmt.Sprintf("M%d", i), false)))
}
lines = append(lines, "};")
}
@ -108,7 +108,7 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
"\tconst device Attributes* attributes [[buffer(0)]]")
for i, u := range p.Uniforms {
lines[len(lines)-1] += ","
lines = append(lines, fmt.Sprintf("\tconstant %s [[buffer(%d)]]", c.varDecl(p, &u, fmt.Sprintf("U%d", i), false, true), i+1))
lines = append(lines, fmt.Sprintf("\tconstant %s [[buffer(%d)]]", c.varDecl(p, &u, fmt.Sprintf("U%d", i), true), i+1))
}
for i := 0; i < p.TextureNum; i++ {
lines[len(lines)-1] += ","
@ -130,7 +130,7 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
"\tVaryings varyings [[stage_in]]")
for i, u := range p.Uniforms {
lines[len(lines)-1] += ","
lines = append(lines, fmt.Sprintf("\tconstant %s [[buffer(%d)]]", c.varDecl(p, &u, fmt.Sprintf("U%d", i), false, true), i+1))
lines = append(lines, fmt.Sprintf("\tconstant %s [[buffer(%d)]]", c.varDecl(p, &u, fmt.Sprintf("U%d", i), true), i+1))
}
for i := 0; i < p.TextureNum; i++ {
lines[len(lines)-1] += ","
@ -153,7 +153,7 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
for i, t := range c.structTypes {
stlines = append(stlines, fmt.Sprintf("struct S%d {", i))
for j, st := range t.Sub {
stlines = append(stlines, fmt.Sprintf("\t%s;", c.varDecl(p, &st, fmt.Sprintf("M%d", j), false, false)))
stlines = append(stlines, fmt.Sprintf("\t%s;", c.varDecl(p, &st, fmt.Sprintf("M%d", j), false)))
}
stlines = append(stlines, "};")
}
@ -169,18 +169,18 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
return ls
}
func (c *compileContext) typ(p *shaderir.Program, t *shaderir.Type, packed bool, ref bool) string {
func (c *compileContext) typ(p *shaderir.Program, t *shaderir.Type) string {
switch t.Main {
case shaderir.None:
return "void"
case shaderir.Struct:
return c.structName(p, t)
default:
return typeString(t, packed, ref)
return typeString(t, false)
}
}
func (c *compileContext) varDecl(p *shaderir.Program, t *shaderir.Type, varname string, packed bool, ref bool) string {
func (c *compileContext) varDecl(p *shaderir.Program, t *shaderir.Type, varname string, ref bool) string {
switch t.Main {
case shaderir.None:
return "?(none)"
@ -191,7 +191,7 @@ func (c *compileContext) varDecl(p *shaderir.Program, t *shaderir.Type, varname
}
return fmt.Sprintf("%s %s", s, varname)
default:
t := typeString(t, packed, ref)
t := typeString(t, ref)
return fmt.Sprintf("%s %s", t, varname)
}
}
@ -209,9 +209,9 @@ func (c *compileContext) varInit(p *shaderir.Program, t *shaderir.Type) string {
case shaderir.Int:
return "0"
case shaderir.Float, shaderir.Vec2, shaderir.Vec3, shaderir.Vec4, shaderir.Mat2, shaderir.Mat3, shaderir.Mat4:
return fmt.Sprintf("%s(0)", basicTypeString(t.Main, false))
return fmt.Sprintf("%s(0)", basicTypeString(t.Main))
default:
t := c.typ(p, t, false, false)
t := c.typ(p, t)
panic(fmt.Sprintf("?(unexpected type: %s)", t))
}
}
@ -221,7 +221,7 @@ func (c *compileContext) function(p *shaderir.Program, f *shaderir.Func, prototy
// Uniform variables and texture variables. In Metal, non-const global variables are not available.
for i, u := range p.Uniforms {
args = append(args, "constant "+c.varDecl(p, &u, fmt.Sprintf("U%d", i), false, true))
args = append(args, "constant "+c.varDecl(p, &u, fmt.Sprintf("U%d", i), true))
}
for i := 0; i < p.TextureNum; i++ {
args = append(args, fmt.Sprintf("texture2d<float> T%d", i))
@ -229,11 +229,11 @@ func (c *compileContext) function(p *shaderir.Program, f *shaderir.Func, prototy
var idx int
for _, t := range f.InParams {
args = append(args, c.varDecl(p, &t, fmt.Sprintf("l%d", idx), false, false))
args = append(args, c.varDecl(p, &t, fmt.Sprintf("l%d", idx), false))
idx++
}
for _, t := range f.OutParams {
args = append(args, "thread "+c.varDecl(p, &t, fmt.Sprintf("l%d", idx), false, true))
args = append(args, "thread "+c.varDecl(p, &t, fmt.Sprintf("l%d", idx), true))
idx++
}
argsstr := "void"
@ -241,7 +241,7 @@ func (c *compileContext) function(p *shaderir.Program, f *shaderir.Func, prototy
argsstr = strings.Join(args, ", ")
}
t := c.typ(p, &f.Return, false, false)
t := c.typ(p, &f.Return)
sig := fmt.Sprintf("%s F%d(%s)", t, f.Index, argsstr)
var lines []string
@ -323,7 +323,7 @@ func (c *compileContext) initVariable(p *shaderir.Program, topBlock, block *shad
var lines []string
if decl {
lines = append(lines, fmt.Sprintf("%s%s = %s;", idt, c.varDecl(p, &t, name, false, false), c.varInit(p, &t)))
lines = append(lines, fmt.Sprintf("%s%s = %s;", idt, c.varDecl(p, &t, name, false), c.varInit(p, &t)))
} else {
lines = append(lines, fmt.Sprintf("%s%s = %s;", idt, name, c.varInit(p, &t)))
}
@ -477,7 +477,7 @@ func (c *compileContext) block(p *shaderir.Program, topBlock, block *shaderir.Bl
t := s.ForVarType
init := constantToNumberLiteral(ct, s.ForInit)
end := constantToNumberLiteral(ct, s.ForEnd)
ts := typeString(&t, false, false)
ts := typeString(&t, false)
lines = append(lines, fmt.Sprintf("%sfor (%s %s = %s; %s %s %s; %s) {", idt, ts, v, init, v, op, end, delta))
lines = append(lines, c.block(p, topBlock, s.Blocks[0], level+1)...)
lines = append(lines, fmt.Sprintf("%s}", idt))

View File

@ -64,10 +64,10 @@ func opString(op shaderir.Op) string {
return fmt.Sprintf("?(unexpected operator: %d)", op)
}
func typeString(t *shaderir.Type, packed bool, ref bool) string {
func typeString(t *shaderir.Type, ref bool) string {
switch t.Main {
case shaderir.Array:
st := typeString(&t.Sub[0], packed, false)
st := typeString(&t.Sub[0], false)
t := fmt.Sprintf("array<%s, %d>", st, t.Length)
if ref {
t += "&"
@ -76,7 +76,7 @@ func typeString(t *shaderir.Type, packed bool, ref bool) string {
case shaderir.Struct:
panic("msl: a struct is not implemented")
default:
t := basicTypeString(t.Main, packed)
t := basicTypeString(t.Main)
if ref {
t += "&"
}
@ -84,7 +84,7 @@ func typeString(t *shaderir.Type, packed bool, ref bool) string {
}
}
func basicTypeString(t shaderir.BasicType, packed bool) string {
func basicTypeString(t shaderir.BasicType) string {
switch t {
case shaderir.None:
return "?(none)"
@ -95,19 +95,10 @@ func basicTypeString(t shaderir.BasicType, packed bool) string {
case shaderir.Float:
return "float"
case shaderir.Vec2:
if packed {
return "packed_float2"
}
return "float2"
case shaderir.Vec3:
if packed {
return "packed_float3"
}
return "float3"
case shaderir.Vec4:
if packed {
return "packed_float4"
}
return "float4"
case shaderir.Mat2:
return "float2x2"