From 796165492768da892ce897c57b66fbd4c43b640e Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 20 Nov 2022 23:14:09 +0900 Subject: [PATCH] internal/graphicsdriver/metal: bug fix: wrong alignment for vec3 --- .../graphicsdriver/metal/graphics_darwin.go | 13 +++++++ shader_test.go | 36 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/internal/graphicsdriver/metal/graphics_darwin.go b/internal/graphicsdriver/metal/graphics_darwin.go index d2dfaa5e8..9a3e456bc 100644 --- a/internal/graphicsdriver/metal/graphics_darwin.go +++ b/internal/graphicsdriver/metal/graphics_darwin.go @@ -576,6 +576,11 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics. t := g.shaders[shaderID].ir.Uniforms[i] switch t.Main { + case shaderir.Vec3: + // float3x3 requires 16-byte alignment (#2463). + v1 := make([]uint32, 4) + copy(v1[0:3], v[0:3]) + uniformVars[i] = v1 case shaderir.Mat3: // float3x3 requires 16-byte alignment (#2036). v1 := make([]uint32, 12) @@ -585,6 +590,14 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics. uniformVars[i] = v1 case shaderir.Array: switch t.Sub[0].Main { + case shaderir.Vec3: + v1 := make([]uint32, t.Length*4) + for j := 0; j < t.Length; j++ { + offset0 := j * 3 + offset1 := j * 4 + copy(v1[offset1:offset1+3], v[offset0:offset0+3]) + } + uniformVars[i] = v1 case shaderir.Mat3: v1 := make([]uint32, t.Length*12) for j := 0; j < t.Length; j++ { diff --git a/shader_test.go b/shader_test.go index 6050d22f5..452a20d0c 100644 --- a/shader_test.go +++ b/shader_test.go @@ -1406,3 +1406,39 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 { }) } } + +// Issue #2463 +func TestShaderVec3Array(t *testing.T) { + const shader = `package main + +var U [4]vec3 + +func Fragment(position vec4, texCoord vec2, color vec4) vec4 { + return vec4(U[0].x/255.0, U[1].y/255.0, U[2].z/255.0, U[3].x/255.0) +} +` + const w, h = 1, 1 + + dst := ebiten.NewImage(w, h) + defer dst.Dispose() + + s, err := ebiten.NewShader([]byte(shader)) + if err != nil { + t.Fatal(err) + } + defer s.Dispose() + + op := &ebiten.DrawRectShaderOptions{} + op.Uniforms = map[string]any{ + "U": []float32{ + 0x24, 0x3f, 0x6a, + 0x88, 0x85, 0xa3, + 0x08, 0xd3, 0x13, + 0x19, 0x8a, 0x2e, + }, + } + dst.DrawRectShader(w, h, s, op) + if got, want := dst.At(0, 0).(color.RGBA), (color.RGBA{0x24, 0x85, 0x13, 0x19}); !sameColors(got, want, 1) { + t.Errorf("got: %v, want: %v", got, want) + } +}