mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 19:28:57 +01:00
parent
031f8376e9
commit
337f44c916
@ -29,13 +29,41 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/internal/shaderir/metal"
|
"github.com/hajimehoshi/ebiten/internal/shaderir/metal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func normalize(str string) string {
|
func glslNormalize(str string) string {
|
||||||
if strings.HasPrefix(str, glsl.FragmentPrelude) {
|
if strings.HasPrefix(str, glsl.FragmentPrelude) {
|
||||||
str = str[len(glsl.FragmentPrelude):]
|
str = str[len(glsl.FragmentPrelude):]
|
||||||
}
|
}
|
||||||
return strings.TrimSpace(str)
|
return strings.TrimSpace(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func metalNormalize(str string) string {
|
||||||
|
if strings.HasPrefix(str, metal.Prelude) {
|
||||||
|
str = str[len(metal.Prelude):]
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func compare(t *testing.T, title, got, want string) {
|
||||||
|
var msg string
|
||||||
|
gotlines := strings.Split(got, "\n")
|
||||||
|
wantlines := strings.Split(want, "\n")
|
||||||
|
for i := range gotlines {
|
||||||
|
if len(wantlines) <= i {
|
||||||
|
msg = fmt.Sprintf(`lines %d:
|
||||||
|
got: %s
|
||||||
|
want: (out of range)`, i+1, gotlines[i])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if gotlines[i] != wantlines[i] {
|
||||||
|
msg = fmt.Sprintf(`lines %d:
|
||||||
|
got: %s
|
||||||
|
want: %s`, i+1, gotlines[i], wantlines[i])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Errorf("%s: got: %v, want: %v\n\n%s", title, got, want, msg)
|
||||||
|
}
|
||||||
|
|
||||||
func TestCompile(t *testing.T) {
|
func TestCompile(t *testing.T) {
|
||||||
if runtime.GOOS == "js" {
|
if runtime.GOOS == "js" {
|
||||||
t.Skip("file open might not be implemented in this environment")
|
t.Skip("file open might not be implemented in this environment")
|
||||||
@ -47,10 +75,11 @@ func TestCompile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type testcase struct {
|
type testcase struct {
|
||||||
Name string
|
Name string
|
||||||
Src []byte
|
Src []byte
|
||||||
VS []byte
|
VS []byte
|
||||||
FS []byte
|
FS []byte
|
||||||
|
Metal []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
fnames := map[string]struct{}{}
|
fnames := map[string]struct{}{}
|
||||||
@ -100,6 +129,15 @@ func TestCompile(t *testing.T) {
|
|||||||
t.Fatalf("no expected file for %s", name)
|
t.Fatalf("no expected file for %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
metaln := name + ".expected.metal"
|
||||||
|
if _, ok := fnames[metaln]; ok {
|
||||||
|
metal, err := ioutil.ReadFile(filepath.Join("testdata", metaln))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
tc.Metal = metal
|
||||||
|
}
|
||||||
|
|
||||||
tests = append(tests, tc)
|
tests = append(tests, tc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,30 +154,22 @@ func TestCompile(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GLSL
|
||||||
vs, fs := glsl.Compile(s)
|
vs, fs := glsl.Compile(s)
|
||||||
if got, want := normalize(vs), normalize(string(tc.VS)); got != want {
|
if got, want := glslNormalize(vs), glslNormalize(string(tc.VS)); got != want {
|
||||||
var msg string
|
compare(t, "GLSL Vertex", got, want)
|
||||||
gotlines := strings.Split(got, "\n")
|
|
||||||
wantlines := strings.Split(want, "\n")
|
|
||||||
for i := range gotlines {
|
|
||||||
if len(wantlines) <= i {
|
|
||||||
msg = fmt.Sprintf(`lines %d:
|
|
||||||
got: %s
|
|
||||||
want: (out of range)`, i+1, gotlines[i])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if gotlines[i] != wantlines[i] {
|
|
||||||
msg = fmt.Sprintf(`lines %d:
|
|
||||||
got: %s
|
|
||||||
want: %s`, i+1, gotlines[i], wantlines[i])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t.Errorf("got: %v, want: %v\n\n%s", got, want, msg)
|
|
||||||
}
|
}
|
||||||
if tc.FS != nil {
|
if tc.FS != nil {
|
||||||
if got, want := normalize(fs), normalize(string(tc.FS)); got != want {
|
if got, want := glslNormalize(fs), glslNormalize(string(tc.FS)); got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
compare(t, "GLSL Fragment", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.Metal != nil {
|
||||||
|
m := metal.Compile(s, "Vertex", "Fragment")
|
||||||
|
if got, want := metalNormalize(m), metalNormalize(string(tc.Metal)); got != want {
|
||||||
|
compare(t, "Metal", got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
internal/shader/testdata/array2.expected.metal
vendored
Normal file
12
internal/shader/testdata/array2.expected.metal
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
void F0(thread array<float2, 3>& l0);
|
||||||
|
|
||||||
|
void F0(thread array<float2, 3>& l0) {
|
||||||
|
array<float2, 2> l1 = {};
|
||||||
|
array<float2, 3> l2 = {};
|
||||||
|
{
|
||||||
|
array<float2, 2> l2 = {};
|
||||||
|
l2 = l1;
|
||||||
|
}
|
||||||
|
l0 = l2;
|
||||||
|
return;
|
||||||
|
}
|
24
internal/shader/testdata/vertex.expected.metal
vendored
Normal file
24
internal/shader/testdata/vertex.expected.metal
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
struct Attributes {
|
||||||
|
packed_float2 M0;
|
||||||
|
packed_float2 M1;
|
||||||
|
packed_float4 M2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Varyings {
|
||||||
|
float4 Position [[position]];
|
||||||
|
float2 M0;
|
||||||
|
float4 M1;
|
||||||
|
};
|
||||||
|
|
||||||
|
vertex Varyings Vertex(
|
||||||
|
uint vid [[vertex_id]],
|
||||||
|
const device Attributes* attributes [[buffer(0)]],
|
||||||
|
constant float2& U0 [[buffer(1)]]) {
|
||||||
|
Varyings varyings = {};
|
||||||
|
float4x4 l0 = float4x4(0);
|
||||||
|
l0 = float4x4((2.0) / ((U0).x), 0.0, 0.0, 0.0, 0.0, (2.0) / ((U0).y), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0);
|
||||||
|
varyings.Position = (l0) * (float4(attributes[vid].M0, 0.0, 1.0));
|
||||||
|
varyings.M0 = attributes[vid].M1;
|
||||||
|
varyings.M1 = attributes[vid].M2;
|
||||||
|
return varyings;
|
||||||
|
}
|
32
internal/shader/testdata/vertex_fragment.expected.metal
vendored
Normal file
32
internal/shader/testdata/vertex_fragment.expected.metal
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
struct Attributes {
|
||||||
|
packed_float2 M0;
|
||||||
|
packed_float2 M1;
|
||||||
|
packed_float4 M2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Varyings {
|
||||||
|
float4 Position [[position]];
|
||||||
|
float2 M0;
|
||||||
|
float4 M1;
|
||||||
|
};
|
||||||
|
|
||||||
|
vertex Varyings Vertex(
|
||||||
|
uint vid [[vertex_id]],
|
||||||
|
const device Attributes* attributes [[buffer(0)]],
|
||||||
|
constant float2& U0 [[buffer(1)]]) {
|
||||||
|
Varyings varyings = {};
|
||||||
|
float4x4 l0 = float4x4(0);
|
||||||
|
l0 = float4x4((2.0) / ((U0).x), 0.0, 0.0, 0.0, 0.0, (2.0) / ((U0).y), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0);
|
||||||
|
varyings.Position = (l0) * (float4(attributes[vid].M0, 0.0, 1.0));
|
||||||
|
varyings.M0 = attributes[vid].M1;
|
||||||
|
varyings.M1 = attributes[vid].M2;
|
||||||
|
return varyings;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment float4 Fragment(
|
||||||
|
Varyings varyings [[stage_in]],
|
||||||
|
constant float2& U0 [[buffer(1)]]) {
|
||||||
|
float4 out = float4(0);
|
||||||
|
out = float4((varyings.Position).x, (varyings.M0).y, (varyings.M1).z, 1.0);
|
||||||
|
return out;
|
||||||
|
}
|
@ -48,20 +48,20 @@ func (c *compileContext) structName(p *shaderir.Program, t *shaderir.Type) strin
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Prelude = `#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
constexpr sampler texture_sampler{filter::nearest};`
|
||||||
|
|
||||||
func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
|
func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
|
||||||
c := &compileContext{
|
c := &compileContext{
|
||||||
structNames: map[string]string{},
|
structNames: map[string]string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
var lines []string
|
var lines []string
|
||||||
lines = append(lines,
|
lines = append(lines, strings.Split(Prelude, "\n")...)
|
||||||
"#include <metal_stdlib>",
|
lines = append(lines, "", "{{.Structs}}")
|
||||||
"",
|
|
||||||
"using namespace metal;",
|
|
||||||
"",
|
|
||||||
"{{.Structs}}",
|
|
||||||
"",
|
|
||||||
"constexpr sampler texture_sampler{filter::nearest};")
|
|
||||||
|
|
||||||
if len(p.Attributes) > 0 {
|
if len(p.Attributes) > 0 {
|
||||||
lines = append(lines, "")
|
lines = append(lines, "")
|
||||||
|
Loading…
Reference in New Issue
Block a user