Compare commits

...

3 Commits

Author SHA1 Message Date
Hajime Hoshi
7d3007a43e internal/graphicsdriver/metal: bug fix: compilation failure 2024-12-07 23:15:13 +09:00
Hajime Hoshi
103b3fe11e internal/graphicsdriver/playstation5: add ebitengine_ProjectionMatrixUniformDwordIndex
This is a necessary information to treat the projection matrix correctly.

This change also updates the header file to avoid duplicated symbols
for constant variables.
2024-12-07 23:04:52 +09:00
Hajime Hoshi
beac278c59 internal/grahics, internal/shadeir: use the term Dword instead of Uint32
This change also renames DWord to Dword.
2024-12-07 22:26:09 +09:00
17 changed files with 104 additions and 86 deletions

View File

@ -29,13 +29,20 @@ const (
ProjectionMatrixUniformVariableIndex = 6 ProjectionMatrixUniformVariableIndex = 6
PreservedUniformUint32Count = 2 + // the destination texture size PreservedUniformDwordCount = 2 + // the destination texture size
2*ShaderSrcImageCount + // the source texture sizes array 2*ShaderSrcImageCount + // the source texture sizes array
2 + // the destination image region origin 2 + // the destination image region origin
2 + // the destination image region size 2 + // the destination image region size
2*ShaderSrcImageCount + // the source image region origins array 2*ShaderSrcImageCount + // the source image region origins array
2*ShaderSrcImageCount + // the source image region sizes array 2*ShaderSrcImageCount + // the source image region sizes array
16 // the projection matrix 16 // the projection matrix
ProjectionMatrixUniformDwordIndex = 2 +
2*ShaderSrcImageCount +
2 +
2 +
2*ShaderSrcImageCount +
2*ShaderSrcImageCount
) )
const ( const (

View File

@ -23,7 +23,7 @@ import (
) )
func BenchmarkPrependPreservedUniforms(b *testing.B) { func BenchmarkPrependPreservedUniforms(b *testing.B) {
var uniforms [graphics.PreservedUniformUint32Count]uint32 var uniforms [graphics.PreservedUniformDwordCount]uint32
dst := graphicscommand.NewImage(16, 16, false, "") dst := graphicscommand.NewImage(16, 16, false, "")
src := graphicscommand.NewImage(16, 16, false, "") src := graphicscommand.NewImage(16, 16, false, "")
dr := image.Rect(0, 0, 16, 16) dr := image.Rect(0, 0, 16, 16)

View File

@ -347,15 +347,15 @@ func imageRectangleToRectangleF32(r image.Rectangle) rectangleF32 {
func (q *commandQueue) prependPreservedUniforms(uniforms []uint32, shader *Shader, dst *Image, srcs [graphics.ShaderSrcImageCount]*Image, dstRegion image.Rectangle, srcRegions [graphics.ShaderSrcImageCount]image.Rectangle) []uint32 { func (q *commandQueue) prependPreservedUniforms(uniforms []uint32, shader *Shader, dst *Image, srcs [graphics.ShaderSrcImageCount]*Image, dstRegion image.Rectangle, srcRegions [graphics.ShaderSrcImageCount]image.Rectangle) []uint32 {
origUniforms := uniforms origUniforms := uniforms
uniforms = q.uint32sBuffer.alloc(len(origUniforms) + graphics.PreservedUniformUint32Count) uniforms = q.uint32sBuffer.alloc(len(origUniforms) + graphics.PreservedUniformDwordCount)
copy(uniforms[graphics.PreservedUniformUint32Count:], origUniforms) copy(uniforms[graphics.PreservedUniformDwordCount:], origUniforms)
return prependPreservedUniforms(uniforms, shader, dst, srcs, dstRegion, srcRegions) return prependPreservedUniforms(uniforms, shader, dst, srcs, dstRegion, srcRegions)
} }
func prependPreservedUniforms(uniforms []uint32, shader *Shader, dst *Image, srcs [graphics.ShaderSrcImageCount]*Image, dstRegion image.Rectangle, srcRegions [graphics.ShaderSrcImageCount]image.Rectangle) []uint32 { func prependPreservedUniforms(uniforms []uint32, shader *Shader, dst *Image, srcs [graphics.ShaderSrcImageCount]*Image, dstRegion image.Rectangle, srcRegions [graphics.ShaderSrcImageCount]image.Rectangle) []uint32 {
// Set the destination texture size. // Set the destination texture size.
// Hard-code indices for BCE optimization. // Hard-code indices for BCE optimization.
_ = uniforms[graphics.PreservedUniformUint32Count-1] _ = uniforms[graphics.PreservedUniformDwordCount-1]
dw, dh := dst.InternalSize() dw, dh := dst.InternalSize()
uniforms[0] = math.Float32bits(float32(dw)) uniforms[0] = math.Float32bits(float32(dw))
@ -468,8 +468,8 @@ func prependPreservedUniforms(uniforms []uint32, shader *Shader, dst *Image, src
return uniforms return uniforms
} }
// Confirm the concrete value of graphics.PreservedUniformUint32Count. // Confirm the concrete value of graphics.PreservedUniformDwordCount.
var _ [0]struct{} = [graphics.PreservedUniformUint32Count - 46]struct{}{} var _ [0]struct{} = [graphics.PreservedUniformDwordCount - 46]struct{}{}
type commandQueuePool struct { type commandQueuePool struct {
cache []*commandQueue cache []*commandQueue

View File

@ -513,7 +513,7 @@ func (g *graphics11) NewShader(program *shaderir.Program) (graphicsdriver.Shader
graphics: g, graphics: g,
id: g.genNextShaderID(), id: g.genNextShaderID(),
uniformTypes: program.Uniforms, uniformTypes: program.Uniforms,
uniformOffsets: hlsl.UniformVariableOffsetsInDWords(program), uniformOffsets: hlsl.UniformVariableOffsetsInDwords(program),
vertexShaderBlob: vsh, vertexShaderBlob: vsh,
pixelShaderBlob: psh, pixelShaderBlob: psh,
} }

View File

@ -1073,7 +1073,7 @@ func (g *graphics12) NewShader(program *shaderir.Program) (graphicsdriver.Shader
graphics: g, graphics: g,
id: g.genNextShaderID(), id: g.genNextShaderID(),
uniformTypes: program.Uniforms, uniformTypes: program.Uniforms,
uniformOffsets: hlsl.UniformVariableOffsetsInDWords(program), uniformOffsets: hlsl.UniformVariableOffsetsInDwords(program),
vertexShader: vsh, vertexShader: vsh,
pixelShader: psh, pixelShader: psh,
} }

View File

@ -209,7 +209,7 @@ func adjustUniforms(uniformTypes []shaderir.Type, uniformOffsets []int, uniforms
fs = append(fs, make([]uint32, uniformOffsets[i]-len(fs))...) fs = append(fs, make([]uint32, uniformOffsets[i]-len(fs))...)
} }
n := typ.Uint32Count() n := typ.DwordCount()
switch typ.Main { switch typ.Main {
case shaderir.Float: case shaderir.Float:
fs = append(fs, uniforms[idx:idx+1]...) fs = append(fs, uniforms[idx:idx+1]...)

View File

@ -882,7 +882,7 @@ func adjustUniformVariablesLayout(uniformTypes []shaderir.Type, uniforms []uint3
var idx int var idx int
for i, typ := range uniformTypes { for i, typ := range uniformTypes {
n := typ.Uint32Count() n := typ.DwordCount()
switch typ.Main { switch typ.Main {
case shaderir.Float, shaderir.Int: case shaderir.Float, shaderir.Int:
values = append(values, uniforms[idx:idx+n]...) values = append(values, uniforms[idx:idx+n]...)

View File

@ -224,7 +224,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
var idx int var idx int
for i, typ := range shader.ir.Uniforms { for i, typ := range shader.ir.Uniforms {
n := typ.Uint32Count() n := typ.DwordCount()
g.uniformVars[i].name = g.uniformVariableName(i) g.uniformVars[i].name = g.uniformVariableName(i)
g.uniformVars[i].value = uniforms[idx : idx+n] g.uniformVars[i].value = uniforms[idx : idx+n]
g.uniformVars[i].typ = typ g.uniformVars[i].typ = typ

View File

@ -292,7 +292,7 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
if u.value == nil { if u.value == nil {
continue continue
} }
if got, expected := len(u.value), u.typ.Uint32Count(); got != expected { if got, expected := len(u.value), u.typ.DwordCount(); got != expected {
// Copy a shaderir.Type value once. Do not pass u.typ directly to fmt.Errorf arguments, or // Copy a shaderir.Type value once. Do not pass u.typ directly to fmt.Errorf arguments, or
// the value u would be allocated on heap. // the value u would be allocated on heap.
typ := u.typ typ := u.typ

View File

@ -30,6 +30,11 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/shaderir" "github.com/hajimehoshi/ebiten/v2/internal/shaderir"
) )
//export ebitengine_ProjectionMatrixUniformDwordIndex
func ebitengine_ProjectionMatrixUniformDwordIndex() C.int {
return C.int(graphics.ProjectionMatrixUniformDwordIndex)
}
type playstation5Error struct { type playstation5Error struct {
name string name string
code int code int

View File

@ -25,6 +25,8 @@
extern "C" { extern "C" {
#endif #endif
int ebitengine_ProjectionMatrixUniformDwordIndex();
typedef struct ebitengine_Error { typedef struct ebitengine_Error {
const char *message; const char *message;
int code; int code;
@ -52,23 +54,27 @@ typedef struct ebitengine_DstRegion {
// kBlendFactor* and kBlendOperation* must be synced with // kBlendFactor* and kBlendOperation* must be synced with
// internal/graphicsdriver/blend.go. // internal/graphicsdriver/blend.go.
const uint8_t kBlendFactorZero = 0; enum {
const uint8_t kBlendFactorOne = 1; kBlendFactorZero = 0,
const uint8_t kBlendFactorSourceColor = 2; kBlendFactorOne = 1,
const uint8_t kBlendFactorOneMinusSourceColor = 3; kBlendFactorSourceColor = 2,
const uint8_t kBlendFactorSourceAlpha = 4; kBlendFactorOneMinusSourceColor = 3,
const uint8_t kBlendFactorOneMinusSourceAlpha = 5; kBlendFactorSourceAlpha = 4,
const uint8_t kBlendFactorDestinationColor = 6; kBlendFactorOneMinusSourceAlpha = 5,
const uint8_t kBlendFactorOneMinusDestinationColor = 7; kBlendFactorDestinationColor = 6,
const uint8_t kBlendFactorDestinationAlpha = 8; kBlendFactorOneMinusDestinationColor = 7,
const uint8_t kBlendFactorOneMinusDestinationAlpha = 9; kBlendFactorDestinationAlpha = 8,
const uint8_t kBlendFactorSourceAlphaSaturated = 10; kBlendFactorOneMinusDestinationAlpha = 9,
kBlendFactorSourceAlphaSaturated = 10,
};
const uint8_t kBlendOperationAdd = 0; enum {
const uint8_t kBlendOperationSubtract = 1; kBlendOperationAdd = 0,
const uint8_t kBlendOperationReverseSubtract = 2; kBlendOperationSubtract = 1,
const uint8_t kBlendOperationMin = 3; kBlendOperationReverseSubtract = 2,
const uint8_t kBlendOperationMax = 4; kBlendOperationMin = 3,
kBlendOperationMax = 4,
};
typedef struct ebitengine_Blend { typedef struct ebitengine_Blend {
uint8_t factor_src_rgb; uint8_t factor_src_rgb;

View File

@ -27,7 +27,7 @@ func BenchmarkFilter(b *testing.B) {
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
uniforms := make([]uint32, graphics.PreservedUniformUint32Count) uniforms := make([]uint32, graphics.PreservedUniformDwordCount)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
s.FilterUniformVariables(uniforms) s.FilterUniformVariables(uniforms)
} }

View File

@ -81,7 +81,7 @@ float4x4 float4x4FromScalar(float x) {
}` }`
func Compile(p *shaderir.Program) (vertexShader, pixelShader, prelude string) { func Compile(p *shaderir.Program) (vertexShader, pixelShader, prelude string) {
offsets := UniformVariableOffsetsInDWords(p) offsets := UniformVariableOffsetsInDwords(p)
c := &compileContext{ c := &compileContext{
unit: p.Unit, unit: p.Unit,
@ -119,8 +119,8 @@ func Compile(p *shaderir.Program) (vertexShader, pixelShader, prelude string) {
lines = append(lines, "cbuffer Uniforms : register(b0) {") lines = append(lines, "cbuffer Uniforms : register(b0) {")
for i, t := range p.Uniforms { for i, t := range p.Uniforms {
// packingoffset is not mandatory, but this is useful to ensure the correct offset is used. // packingoffset is not mandatory, but this is useful to ensure the correct offset is used.
offset := fmt.Sprintf("c%d", offsets[i]/UniformVariableBoundaryInDWords) offset := fmt.Sprintf("c%d", offsets[i]/UniformVariableBoundaryInDwords)
switch offsets[i] % UniformVariableBoundaryInDWords { switch offsets[i] % UniformVariableBoundaryInDwords {
case 1: case 1:
offset += ".y" offset += ".y"
case 2: case 2:

View File

@ -20,10 +20,10 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/shaderir" "github.com/hajimehoshi/ebiten/v2/internal/shaderir"
) )
const UniformVariableBoundaryInDWords = 4 const UniformVariableBoundaryInDwords = 4
// UniformVariableOffsetsInDWords returns the offsets of the uniform variables in DWROD units in the HLSL layout. // UniformVariableOffsetsInDwords returns the offsets of the uniform variables in DWROD units in the HLSL layout.
func UniformVariableOffsetsInDWords(program *shaderir.Program) []int { func UniformVariableOffsetsInDwords(program *shaderir.Program) []int {
// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
// https://github.com/microsoft/DirectXShaderCompiler/wiki/Buffer-Packing // https://github.com/microsoft/DirectXShaderCompiler/wiki/Buffer-Packing
@ -31,59 +31,59 @@ func UniformVariableOffsetsInDWords(program *shaderir.Program) []int {
if x == 0 { if x == 0 {
return 0 return 0
} }
return ((x-1)/UniformVariableBoundaryInDWords + 1) * UniformVariableBoundaryInDWords return ((x-1)/UniformVariableBoundaryInDwords + 1) * UniformVariableBoundaryInDwords
} }
var offsetsInDWords []int var offsetsInDwords []int
var headInDWords int var headInDwords int
// TODO: Reorder the variables with packoffset. // TODO: Reorder the variables with packoffset.
// See https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-variable-packoffset // See https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-variable-packoffset
for _, u := range program.Uniforms { for _, u := range program.Uniforms {
switch u.Main { switch u.Main {
case shaderir.Float: case shaderir.Float:
offsetsInDWords = append(offsetsInDWords, headInDWords) offsetsInDwords = append(offsetsInDwords, headInDwords)
headInDWords += 1 headInDwords += 1
case shaderir.Int: case shaderir.Int:
offsetsInDWords = append(offsetsInDWords, headInDWords) offsetsInDwords = append(offsetsInDwords, headInDwords)
headInDWords += 1 headInDwords += 1
case shaderir.Vec2, shaderir.IVec2: case shaderir.Vec2, shaderir.IVec2:
if headInDWords%UniformVariableBoundaryInDWords >= 3 { if headInDwords%UniformVariableBoundaryInDwords >= 3 {
headInDWords = align(headInDWords) headInDwords = align(headInDwords)
} }
offsetsInDWords = append(offsetsInDWords, headInDWords) offsetsInDwords = append(offsetsInDwords, headInDwords)
headInDWords += 2 headInDwords += 2
case shaderir.Vec3, shaderir.IVec3: case shaderir.Vec3, shaderir.IVec3:
if headInDWords%UniformVariableBoundaryInDWords >= 2 { if headInDwords%UniformVariableBoundaryInDwords >= 2 {
headInDWords = align(headInDWords) headInDwords = align(headInDwords)
} }
offsetsInDWords = append(offsetsInDWords, headInDWords) offsetsInDwords = append(offsetsInDwords, headInDwords)
headInDWords += 3 headInDwords += 3
case shaderir.Vec4, shaderir.IVec4: case shaderir.Vec4, shaderir.IVec4:
if headInDWords%UniformVariableBoundaryInDWords >= 1 { if headInDwords%UniformVariableBoundaryInDwords >= 1 {
headInDWords = align(headInDWords) headInDwords = align(headInDwords)
} }
offsetsInDWords = append(offsetsInDWords, headInDWords) offsetsInDwords = append(offsetsInDwords, headInDwords)
headInDWords += 4 headInDwords += 4
case shaderir.Mat2: case shaderir.Mat2:
// For matrices, each column is aligned to the boundary. // For matrices, each column is aligned to the boundary.
headInDWords = align(headInDWords) headInDwords = align(headInDwords)
offsetsInDWords = append(offsetsInDWords, headInDWords) offsetsInDwords = append(offsetsInDwords, headInDwords)
headInDWords += 6 headInDwords += 6
case shaderir.Mat3: case shaderir.Mat3:
headInDWords = align(headInDWords) headInDwords = align(headInDwords)
offsetsInDWords = append(offsetsInDWords, headInDWords) offsetsInDwords = append(offsetsInDwords, headInDwords)
headInDWords += 11 headInDwords += 11
case shaderir.Mat4: case shaderir.Mat4:
headInDWords = align(headInDWords) headInDwords = align(headInDwords)
offsetsInDWords = append(offsetsInDWords, headInDWords) offsetsInDwords = append(offsetsInDwords, headInDwords)
headInDWords += 16 headInDwords += 16
case shaderir.Array: case shaderir.Array:
// Each array is 16-byte aligned. // Each array is 16-byte aligned.
// TODO: What if the array has 2 or more dimensions? // TODO: What if the array has 2 or more dimensions?
headInDWords = align(headInDWords) headInDwords = align(headInDwords)
offsetsInDWords = append(offsetsInDWords, headInDWords) offsetsInDwords = append(offsetsInDwords, headInDwords)
n := u.Sub[0].Uint32Count() n := u.Sub[0].DwordCount()
switch u.Sub[0].Main { switch u.Sub[0].Main {
case shaderir.Mat2: case shaderir.Mat2:
n = 6 n = 6
@ -92,9 +92,9 @@ func UniformVariableOffsetsInDWords(program *shaderir.Program) []int {
case shaderir.Mat4: case shaderir.Mat4:
n = 16 n = 16
} }
headInDWords += (u.Length - 1) * align(n) headInDwords += (u.Length - 1) * align(n)
// The last element is not with a padding. // The last element is not with a padding.
headInDWords += n headInDwords += n
case shaderir.Struct: case shaderir.Struct:
// TODO: Implement this // TODO: Implement this
panic("hlsl: offset for a struct is not implemented yet") panic("hlsl: offset for a struct is not implemented yet")
@ -103,5 +103,5 @@ func UniformVariableOffsetsInDWords(program *shaderir.Program) []int {
} }
} }
return offsetsInDWords return offsetsInDwords
} }

View File

@ -493,7 +493,7 @@ func (p *Program) FilterUniformVariables(uniforms []uint32) {
p.uniformFactors = make([]uint32, len(uniforms)) p.uniformFactors = make([]uint32, len(uniforms))
var idx int var idx int
for i, typ := range p.Uniforms { for i, typ := range p.Uniforms {
c := typ.Uint32Count() c := typ.DwordCount()
if reachableUniforms[i] { if reachableUniforms[i] {
for i := idx; i < idx+c; i++ { for i := idx; i < idx+c; i++ {
p.uniformFactors[i] = 1 p.uniformFactors[i] = 1

View File

@ -87,7 +87,7 @@ func (t Type) String() string {
} }
} }
func (t Type) Uint32Count() int { func (t Type) DwordCount() int {
switch t.Main { switch t.Main {
case Int: case Int:
return 1 return 1
@ -112,7 +112,7 @@ func (t Type) Uint32Count() int {
case Mat4: case Mat4:
return 16 return 16
case Array: case Array:
return t.Length * t.Sub[0].Uint32Count() return t.Length * t.Sub[0].DwordCount()
default: // TODO: Parse a struct correctly default: // TODO: Parse a struct correctly
return -1 return -1
} }

View File

@ -29,7 +29,7 @@ type Shader struct {
uniformNames []string uniformNames []string
uniformTypes []shaderir.Type uniformTypes []shaderir.Type
uniformUint32Count int uniformDwordCount int
} }
func NewShader(ir *shaderir.Program, name string) *Shader { func NewShader(ir *shaderir.Program, name string) *Shader {
@ -45,20 +45,20 @@ func (s *Shader) Deallocate() {
} }
func (s *Shader) AppendUniforms(dst []uint32, uniforms map[string]any) []uint32 { func (s *Shader) AppendUniforms(dst []uint32, uniforms map[string]any) []uint32 {
if s.uniformUint32Count == 0 { if s.uniformDwordCount == 0 {
for _, typ := range s.uniformTypes { for _, typ := range s.uniformTypes {
s.uniformUint32Count += typ.Uint32Count() s.uniformDwordCount += typ.DwordCount()
} }
} }
origLen := len(dst) origLen := len(dst)
if cap(dst)-len(dst) >= s.uniformUint32Count { if cap(dst)-len(dst) >= s.uniformDwordCount {
dst = dst[:len(dst)+s.uniformUint32Count] dst = dst[:len(dst)+s.uniformDwordCount]
for i := origLen; i < len(dst); i++ { for i := origLen; i < len(dst); i++ {
dst[i] = 0 dst[i] = 0
} }
} else { } else {
dst = append(dst, make([]uint32, s.uniformUint32Count)...) dst = append(dst, make([]uint32, s.uniformDwordCount)...)
} }
idx := origLen idx := origLen
@ -71,23 +71,23 @@ func (s *Shader) AppendUniforms(dst []uint32, uniforms map[string]any) []uint32
t := v.Type() t := v.Type()
switch t.Kind() { switch t.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if typ.Uint32Count() != 1 { if typ.DwordCount() != 1 {
panic(fmt.Sprintf("ui: unexpected uniform value for %s (%s)", name, typ.String())) panic(fmt.Sprintf("ui: unexpected uniform value for %s (%s)", name, typ.String()))
} }
dst[idx] = uint32(v.Int()) dst[idx] = uint32(v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
if typ.Uint32Count() != 1 { if typ.DwordCount() != 1 {
panic(fmt.Sprintf("ui: unexpected uniform value for %s (%s)", name, typ.String())) panic(fmt.Sprintf("ui: unexpected uniform value for %s (%s)", name, typ.String()))
} }
dst[idx] = uint32(v.Uint()) dst[idx] = uint32(v.Uint())
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
if typ.Uint32Count() != 1 { if typ.DwordCount() != 1 {
panic(fmt.Sprintf("ui: unexpected uniform value for %s (%s)", name, typ.String())) panic(fmt.Sprintf("ui: unexpected uniform value for %s (%s)", name, typ.String()))
} }
dst[idx] = math.Float32bits(float32(v.Float())) dst[idx] = math.Float32bits(float32(v.Float()))
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
l := v.Len() l := v.Len()
if typ.Uint32Count() != l { if typ.DwordCount() != l {
panic(fmt.Sprintf("ui: unexpected uniform value for %s (%s)", name, typ.String())) panic(fmt.Sprintf("ui: unexpected uniform value for %s (%s)", name, typ.String()))
} }
switch t.Elem().Kind() { switch t.Elem().Kind() {
@ -111,7 +111,7 @@ func (s *Shader) AppendUniforms(dst []uint32, uniforms map[string]any) []uint32
} }
} }
idx += typ.Uint32Count() idx += typ.DwordCount()
} }
return dst return dst