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"
|
||||
)
|
||||
|
||||
func normalize(str string) string {
|
||||
func glslNormalize(str string) string {
|
||||
if strings.HasPrefix(str, glsl.FragmentPrelude) {
|
||||
str = str[len(glsl.FragmentPrelude):]
|
||||
}
|
||||
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) {
|
||||
if runtime.GOOS == "js" {
|
||||
t.Skip("file open might not be implemented in this environment")
|
||||
@ -47,10 +75,11 @@ func TestCompile(t *testing.T) {
|
||||
}
|
||||
|
||||
type testcase struct {
|
||||
Name string
|
||||
Src []byte
|
||||
VS []byte
|
||||
FS []byte
|
||||
Name string
|
||||
Src []byte
|
||||
VS []byte
|
||||
FS []byte
|
||||
Metal []byte
|
||||
}
|
||||
|
||||
fnames := map[string]struct{}{}
|
||||
@ -100,6 +129,15 @@ func TestCompile(t *testing.T) {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -116,30 +154,22 @@ func TestCompile(t *testing.T) {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
// GLSL
|
||||
vs, fs := glsl.Compile(s)
|
||||
if got, want := normalize(vs), normalize(string(tc.VS)); got != want {
|
||||
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("got: %v, want: %v\n\n%s", got, want, msg)
|
||||
if got, want := glslNormalize(vs), glslNormalize(string(tc.VS)); got != want {
|
||||
compare(t, "GLSL Vertex", got, want)
|
||||
}
|
||||
if tc.FS != nil {
|
||||
if got, want := normalize(fs), normalize(string(tc.FS)); got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
if got, want := glslNormalize(fs), glslNormalize(string(tc.FS)); 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
|
||||
}
|
||||
|
||||
const Prelude = `#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
constexpr sampler texture_sampler{filter::nearest};`
|
||||
|
||||
func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
|
||||
c := &compileContext{
|
||||
structNames: map[string]string{},
|
||||
}
|
||||
|
||||
var lines []string
|
||||
lines = append(lines,
|
||||
"#include <metal_stdlib>",
|
||||
"",
|
||||
"using namespace metal;",
|
||||
"",
|
||||
"{{.Structs}}",
|
||||
"",
|
||||
"constexpr sampler texture_sampler{filter::nearest};")
|
||||
lines = append(lines, strings.Split(Prelude, "\n")...)
|
||||
lines = append(lines, "", "{{.Structs}}")
|
||||
|
||||
if len(p.Attributes) > 0 {
|
||||
lines = append(lines, "")
|
||||
|
Loading…
Reference in New Issue
Block a user