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. // It is because old Xcode (8 or older?) does not accept @available syntax.
// #cgo CFLAGS: -Wno-unguarded-availability-new // #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 // #cgo LDFLAGS: -framework QuartzCore -framework Foundation -framework CoreGraphics
// //
// #include "ca_darwin.h" // #include "ca_darwin.h"

View File

@ -29,7 +29,7 @@ import (
) )
// #cgo CFLAGS: -x objective-c // #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 // #cgo LDFLAGS: -framework Foundation
// //
// #import <Foundation/Foundation.h> // #import <Foundation/Foundation.h>
@ -56,9 +56,9 @@ const source = `#include <metal_stdlib>
using namespace metal; using namespace metal;
struct VertexIn { struct VertexIn {
packed_float2 position; float2 position;
packed_float2 tex; float2 tex;
packed_float4 color; float4 color;
}; };
struct VertexOut { 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 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. // This package is in very early stages of development.
// The API will change when opportunities for improvement are discovered; it is not yet frozen. // The API will change when opportunities for improvement are discovered; it is not yet frozen.
@ -28,7 +28,7 @@ import (
"unsafe" "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 // #cgo LDFLAGS: -framework Metal -framework CoreGraphics -framework Foundation
// //
// #include "mtl_darwin.h" // #include "mtl_darwin.h"

View File

@ -48,15 +48,11 @@ void *Device_MakeCommandQueue(void *device) {
struct Library Device_MakeLibrary(void *device, const char *source, struct Library Device_MakeLibrary(void *device, const char *source,
size_t sourceLength) { size_t sourceLength) {
NSError *error; 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 id<MTLLibrary> library = [(id<MTLDevice>)device
newLibraryWithSource:[[NSString alloc] initWithBytes:source newLibraryWithSource:[[NSString alloc] initWithBytes:source
length:sourceLength length:sourceLength
encoding:NSUTF8StringEncoding] encoding:NSUTF8StringEncoding]
options:options options:NULL
error:&error]; error:&error];
struct Library l; struct Library l;

View File

@ -25,7 +25,7 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal/ca" "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" // #include "ns_darwin.h"
import "C" import "C"

View File

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

View File

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

View File

@ -72,7 +72,7 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
lines = append(lines, "") lines = append(lines, "")
lines = append(lines, "struct Attributes {") lines = append(lines, "struct Attributes {")
for i, a := range p.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, "};") 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, "struct Varyings {")
lines = append(lines, "\tfloat4 Position [[position]];") lines = append(lines, "\tfloat4 Position [[position]];")
for i, v := range p.Varyings { 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, "};") lines = append(lines, "};")
} }
@ -108,7 +108,7 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
"\tconst device Attributes* attributes [[buffer(0)]]") "\tconst device Attributes* attributes [[buffer(0)]]")
for i, u := range p.Uniforms { for i, u := range p.Uniforms {
lines[len(lines)-1] += "," 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++ { for i := 0; i < p.TextureNum; i++ {
lines[len(lines)-1] += "," lines[len(lines)-1] += ","
@ -130,7 +130,7 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
"\tVaryings varyings [[stage_in]]") "\tVaryings varyings [[stage_in]]")
for i, u := range p.Uniforms { for i, u := range p.Uniforms {
lines[len(lines)-1] += "," 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++ { for i := 0; i < p.TextureNum; i++ {
lines[len(lines)-1] += "," lines[len(lines)-1] += ","
@ -153,7 +153,7 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
for i, t := range c.structTypes { for i, t := range c.structTypes {
stlines = append(stlines, fmt.Sprintf("struct S%d {", i)) stlines = append(stlines, fmt.Sprintf("struct S%d {", i))
for j, st := range t.Sub { 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, "};") stlines = append(stlines, "};")
} }
@ -169,18 +169,18 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
return ls 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 { switch t.Main {
case shaderir.None: case shaderir.None:
return "void" return "void"
case shaderir.Struct: case shaderir.Struct:
return c.structName(p, t) return c.structName(p, t)
default: 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 { switch t.Main {
case shaderir.None: case shaderir.None:
return "?(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) return fmt.Sprintf("%s %s", s, varname)
default: default:
t := typeString(t, packed, ref) t := typeString(t, ref)
return fmt.Sprintf("%s %s", t, varname) 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: case shaderir.Int:
return "0" return "0"
case shaderir.Float, shaderir.Vec2, shaderir.Vec3, shaderir.Vec4, shaderir.Mat2, shaderir.Mat3, shaderir.Mat4: 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: default:
t := c.typ(p, t, false, false) t := c.typ(p, t)
panic(fmt.Sprintf("?(unexpected type: %s)", 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. // Uniform variables and texture variables. In Metal, non-const global variables are not available.
for i, u := range p.Uniforms { 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++ { for i := 0; i < p.TextureNum; i++ {
args = append(args, fmt.Sprintf("texture2d<float> T%d", 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 var idx int
for _, t := range f.InParams { 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++ idx++
} }
for _, t := range f.OutParams { 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++ idx++
} }
argsstr := "void" argsstr := "void"
@ -241,7 +241,7 @@ func (c *compileContext) function(p *shaderir.Program, f *shaderir.Func, prototy
argsstr = strings.Join(args, ", ") 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) sig := fmt.Sprintf("%s F%d(%s)", t, f.Index, argsstr)
var lines []string var lines []string
@ -323,7 +323,7 @@ func (c *compileContext) initVariable(p *shaderir.Program, topBlock, block *shad
var lines []string var lines []string
if decl { 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 { } else {
lines = append(lines, fmt.Sprintf("%s%s = %s;", idt, name, c.varInit(p, &t))) 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 t := s.ForVarType
init := constantToNumberLiteral(ct, s.ForInit) init := constantToNumberLiteral(ct, s.ForInit)
end := constantToNumberLiteral(ct, s.ForEnd) 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, 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, c.block(p, topBlock, s.Blocks[0], level+1)...)
lines = append(lines, fmt.Sprintf("%s}", idt)) 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) 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 { switch t.Main {
case shaderir.Array: 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) t := fmt.Sprintf("array<%s, %d>", st, t.Length)
if ref { if ref {
t += "&" t += "&"
@ -76,7 +76,7 @@ func typeString(t *shaderir.Type, packed bool, ref bool) string {
case shaderir.Struct: case shaderir.Struct:
panic("msl: a struct is not implemented") panic("msl: a struct is not implemented")
default: default:
t := basicTypeString(t.Main, packed) t := basicTypeString(t.Main)
if ref { if ref {
t += "&" 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 { switch t {
case shaderir.None: case shaderir.None:
return "?(none)" return "?(none)"
@ -95,19 +95,10 @@ func basicTypeString(t shaderir.BasicType, packed bool) string {
case shaderir.Float: case shaderir.Float:
return "float" return "float"
case shaderir.Vec2: case shaderir.Vec2:
if packed {
return "packed_float2"
}
return "float2" return "float2"
case shaderir.Vec3: case shaderir.Vec3:
if packed {
return "packed_float3"
}
return "float3" return "float3"
case shaderir.Vec4: case shaderir.Vec4:
if packed {
return "packed_float4"
}
return "float4" return "float4"
case shaderir.Mat2: case shaderir.Mat2:
return "float2x2" return "float2x2"