diff --git a/internal/atlas/image.go b/internal/atlas/image.go index 9c1a07742..b16f1d500 100644 --- a/internal/atlas/image.go +++ b/internal/atlas/image.go @@ -407,13 +407,13 @@ func (i *Image) processSrc(src *Image) { // 5: Color G // 6: Color B // 7: Color Y -func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, evenOdd bool) { +func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []driver.Uniform, evenOdd bool) { backendsM.Lock() defer backendsM.Unlock() i.drawTriangles(srcs, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, subimageOffsets, shader, uniforms, evenOdd, false) } -func (i *Image) drawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, evenOdd bool, keepOnAtlas bool) { +func (i *Image) drawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []driver.Uniform, evenOdd bool, keepOnAtlas bool) { if i.disposed { panic("atlas: the drawing target image must not be disposed (DrawTriangles)") } diff --git a/internal/buffered/image.go b/internal/buffered/image.go index 84bd99ceb..bfe409915 100644 --- a/internal/buffered/image.go +++ b/internal/buffered/image.go @@ -202,7 +202,7 @@ func (i *Image) replacePendingPixels(pix []byte, x, y, width, height int) { // DrawTriangles draws the src image with the given vertices. // // Copying vertices and indices is the caller's responsibility. -func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, evenOdd bool) { +func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []driver.Uniform, evenOdd bool) { for _, src := range srcs { if i == src { panic("buffered: Image.DrawTriangles: source images must be different from the receiver") diff --git a/internal/driver/graphics.go b/internal/driver/graphics.go index 6c1e989b9..6d771f1a0 100644 --- a/internal/driver/graphics.go +++ b/internal/driver/graphics.go @@ -39,6 +39,11 @@ type ColorM interface { Elements(body *[16]float32, translate *[4]float32) } +type Uniform struct { + Float32 float32 + Float32s []float32 +} + type Graphics interface { Begin() End() @@ -64,7 +69,7 @@ type Graphics interface { // // * float32 // * []float32 - DrawTriangles(dst ImageID, srcs [graphics.ShaderImageNum]ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader ShaderID, indexLen int, indexOffset int, mode CompositeMode, colorM ColorM, filter Filter, address Address, dstRegion, srcRegion Region, uniforms []interface{}, evenOdd bool) error + DrawTriangles(dst ImageID, srcs [graphics.ShaderImageNum]ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader ShaderID, indexLen int, indexOffset int, mode CompositeMode, colorM ColorM, filter Filter, address Address, dstRegion, srcRegion Region, uniforms []Uniform, evenOdd bool) error } // GraphicsNotReady represents that the graphics driver is not ready for recovering from the context lost. diff --git a/internal/graphicscommand/command.go b/internal/graphicscommand/command.go index 572898803..1f7118702 100644 --- a/internal/graphicscommand/command.go +++ b/internal/graphicscommand/command.go @@ -145,7 +145,7 @@ func (q *commandQueue) appendIndices(indices []uint16, offset uint16) { } // EnqueueDrawTrianglesCommand enqueues a drawing-image command. -func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, color affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}, evenOdd bool) { +func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, color affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []driver.Uniform, evenOdd bool) { if len(indices) > graphics.IndicesNum { panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesNum but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesNum: %d", len(indices), graphics.IndicesNum)) } @@ -363,7 +363,7 @@ type drawTrianglesCommand struct { dstRegion driver.Region srcRegion driver.Region shader *Shader - uniforms []interface{} + uniforms []driver.Uniform evenOdd bool } diff --git a/internal/graphicscommand/image.go b/internal/graphicscommand/image.go index 0ed1db834..24529c22f 100644 --- a/internal/graphicscommand/image.go +++ b/internal/graphicscommand/image.go @@ -141,7 +141,7 @@ func (i *Image) InternalSize() (int, int) { // // If the source image is not specified, i.e., src is nil and there is no image in the uniform variables, the // elements for the source image are not used. -func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, clr affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}, evenOdd bool) { +func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, clr affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []driver.Uniform, evenOdd bool) { if shader == nil { // Fast path for rendering without a shader (#1355). img := srcs[0] diff --git a/internal/graphicsdriver/metal/graphics.go b/internal/graphicsdriver/metal/graphics.go index af1eb64a6..535d6d60b 100644 --- a/internal/graphicsdriver/metal/graphics.go +++ b/internal/graphicsdriver/metal/graphics.go @@ -775,7 +775,7 @@ func (g *Graphics) flushRenderCommandEncoderIfNeeded() { g.lastDst = nil } -func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion driver.Region, srcs [graphics.ShaderImageNum]*Image, indexLen int, indexOffset int, uniforms []interface{}, stencilMode stencilMode) error { +func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion driver.Region, srcs [graphics.ShaderImageNum]*Image, indexLen int, indexOffset int, uniforms []driver.Uniform, stencilMode stencilMode) error { // When prepareing a stencil buffer, flush the current render command encoder // to make sure the stencil buffer is cleared when loading. // TODO: What about clearing the stencil buffer by vertices? @@ -840,15 +840,14 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion drive g.rce.SetVertexBuffer(g.vb, 0, 0) for i, u := range uniforms { - switch u := u.(type) { - case float32: - g.rce.SetVertexBytes(unsafe.Pointer(&u), unsafe.Sizeof(u), i+1) - g.rce.SetFragmentBytes(unsafe.Pointer(&u), unsafe.Sizeof(u), i+1) - case []float32: - g.rce.SetVertexBytes(unsafe.Pointer(&u[0]), unsafe.Sizeof(u[0])*uintptr(len(u)), i+1) - g.rce.SetFragmentBytes(unsafe.Pointer(&u[0]), unsafe.Sizeof(u[0])*uintptr(len(u)), i+1) - default: - return fmt.Errorf("metal: unexpected uniform value: %[1]v (type: %[1]T)", u) + if len(u.Float32s) == 0 { + v := u.Float32 + g.rce.SetVertexBytes(unsafe.Pointer(&v), unsafe.Sizeof(v), i+1) + g.rce.SetFragmentBytes(unsafe.Pointer(&v), unsafe.Sizeof(v), i+1) + } else { + v := u.Float32s + g.rce.SetVertexBytes(unsafe.Pointer(&v[0]), unsafe.Sizeof(v[0])*uintptr(len(v)), i+1) + g.rce.SetFragmentBytes(unsafe.Pointer(&v[0]), unsafe.Sizeof(v[0])*uintptr(len(v)), i+1) } } @@ -867,7 +866,7 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion drive return nil } -func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shaderID driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, colorM driver.ColorM, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, uniforms []interface{}, evenOdd bool) error { +func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shaderID driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, colorM driver.ColorM, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, uniforms []driver.Uniform, evenOdd bool) error { dst := g.images[dstID] if dst.screen { @@ -880,7 +879,7 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm } rpss := map[stencilMode]mtl.RenderPipelineState{} - var uniformVars []interface{} + var uniformVars []driver.Uniform if shaderID == driver.InvalidShaderID { if dst.screen && filter == driver.FilterScreen { rpss[noStencil] = g.screenRPS @@ -915,17 +914,29 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm if filter == driver.FilterScreen { scale = float32(dst.width) / float32(srcs[0].width) } - uniformVars = []interface{}{ - []float32{float32(w), float32(h)}, - sourceSize, - esBody[:], - esTranslate[:], - scale, - []float32{ - srcRegion.X, - srcRegion.Y, - srcRegion.X + srcRegion.Width, - srcRegion.Y + srcRegion.Height, + uniformVars = []driver.Uniform{ + { + Float32s: []float32{float32(w), float32(h)}, + }, + { + Float32s: sourceSize, + }, + { + Float32s: esBody[:], + }, + { + Float32s: esTranslate[:], + }, + { + Float32: scale, + }, + { + Float32s: []float32{ + srcRegion.X, + srcRegion.Y, + srcRegion.X + srcRegion.Width, + srcRegion.Y + srcRegion.Height, + }, }, } } else { @@ -941,11 +952,13 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm } } - uniformVars = make([]interface{}, graphics.PreservedUniformVariablesNum+len(uniforms)) + uniformVars = make([]driver.Uniform, graphics.PreservedUniformVariablesNum+len(uniforms)) // Set the destination texture size. dw, dh := dst.internalSize() - uniformVars[graphics.DestinationTextureSizeUniformVariableIndex] = []float32{float32(dw), float32(dh)} + uniformVars[graphics.DestinationTextureSizeUniformVariableIndex] = driver.Uniform{ + Float32s: []float32{float32(dw), float32(dh)}, + } // Set the source texture sizes. usizes := make([]float32, 2*len(srcs)) @@ -956,15 +969,21 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm usizes[2*i+1] = float32(h) } } - uniformVars[graphics.TextureSizesUniformVariableIndex] = usizes + uniformVars[graphics.TextureSizesUniformVariableIndex] = driver.Uniform{ + Float32s: usizes, + } // Set the destination region's origin. udorigin := []float32{float32(dstRegion.X) / float32(dw), float32(dstRegion.Y) / float32(dh)} - uniformVars[graphics.TextureDestinationRegionOriginUniformVariableIndex] = udorigin + uniformVars[graphics.TextureDestinationRegionOriginUniformVariableIndex] = driver.Uniform{ + Float32s: udorigin, + } // Set the destination region's size. udsize := []float32{float32(dstRegion.Width) / float32(dw), float32(dstRegion.Height) / float32(dh)} - uniformVars[graphics.TextureDestinationRegionSizeUniformVariableIndex] = udsize + uniformVars[graphics.TextureDestinationRegionSizeUniformVariableIndex] = driver.Uniform{ + Float32s: udsize, + } // Set the source offsets. uoffsets := make([]float32, 2*len(offsets)) @@ -972,15 +991,21 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm uoffsets[2*i] = offset[0] uoffsets[2*i+1] = offset[1] } - uniformVars[graphics.TextureSourceOffsetsUniformVariableIndex] = uoffsets + uniformVars[graphics.TextureSourceOffsetsUniformVariableIndex] = driver.Uniform{ + Float32s: uoffsets, + } // Set the source region's origin of texture0. usorigin := []float32{float32(srcRegion.X), float32(srcRegion.Y)} - uniformVars[graphics.TextureSourceRegionOriginUniformVariableIndex] = usorigin + uniformVars[graphics.TextureSourceRegionOriginUniformVariableIndex] = driver.Uniform{ + Float32s: usorigin, + } // Set the source region's size of texture0. ussize := []float32{float32(srcRegion.Width), float32(srcRegion.Height)} - uniformVars[graphics.TextureSourceRegionSizeUniformVariableIndex] = ussize + uniformVars[graphics.TextureSourceRegionSizeUniformVariableIndex] = driver.Uniform{ + Float32s: ussize, + } // Set the additional uniform variables. for i, v := range uniforms { diff --git a/internal/graphicsdriver/opengl/graphics.go b/internal/graphicsdriver/opengl/graphics.go index e5105f874..bb9ccc396 100644 --- a/internal/graphicsdriver/opengl/graphics.go +++ b/internal/graphicsdriver/opengl/graphics.go @@ -170,7 +170,7 @@ func (g *Graphics) uniformVariableName(idx int) string { return name } -func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shaderID driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, colorM driver.ColorM, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, uniforms []interface{}, evenOdd bool) error { +func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shaderID driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, colorM driver.ColorM, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, uniforms []driver.Uniform, evenOdd bool) error { destination := g.images[dstID] g.drawCalled = true @@ -197,14 +197,14 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm dw, dh := destination.framebufferSize() g.uniformVars = append(g.uniformVars, uniformVariable{ name: "viewport_size", - value: uniformVariableValue{ - f32s: []float32{float32(dw), float32(dh)}, + value: driver.Uniform{ + Float32s: []float32{float32(dw), float32(dh)}, }, typ: shaderir.Type{Main: shaderir.Vec2}, }, uniformVariable{ name: "source_region", - value: uniformVariableValue{ - f32s: []float32{ + value: driver.Uniform{ + Float32s: []float32{ srcRegion.X, srcRegion.Y, srcRegion.X + srcRegion.Width, @@ -221,14 +221,14 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm colorM.Elements(&esBody, &esTranslate) g.uniformVars = append(g.uniformVars, uniformVariable{ name: "color_matrix_body", - value: uniformVariableValue{ - f32s: esBody[:], + value: driver.Uniform{ + Float32s: esBody[:], }, typ: shaderir.Type{Main: shaderir.Mat4}, }, uniformVariable{ name: "color_matrix_translation", - value: uniformVariableValue{ - f32s: esTranslate[:], + value: driver.Uniform{ + Float32s: esTranslate[:], }, typ: shaderir.Type{Main: shaderir.Vec4}, }) @@ -238,8 +238,8 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm sw, sh := g.images[srcIDs[0]].framebufferSize() g.uniformVars = append(g.uniformVars, uniformVariable{ name: "source_size", - value: uniformVariableValue{ - f32s: []float32{float32(sw), float32(sh)}, + value: driver.Uniform{ + Float32s: []float32{float32(sw), float32(sh)}, }, typ: shaderir.Type{Main: shaderir.Vec2}, }) @@ -249,8 +249,8 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm scale := float32(destination.width) / float32(g.images[srcIDs[0]].width) g.uniformVars = append(g.uniformVars, uniformVariable{ name: "scale", - value: uniformVariableValue{ - f32: scale, + value: driver.Uniform{ + Float32: scale, }, typ: shaderir.Type{Main: shaderir.Float}, }) @@ -270,7 +270,7 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm const idx = graphics.DestinationTextureSizeUniformVariableIndex w, h := destination.framebufferSize() g.uniformVars[idx].name = g.uniformVariableName(idx) - g.uniformVars[idx].value.f32s = []float32{float32(w), float32(h)} + g.uniformVars[idx].value.Float32s = []float32{float32(w), float32(h)} g.uniformVars[idx].typ = shader.ir.Uniforms[idx] } { @@ -285,7 +285,7 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm } const idx = graphics.TextureSizesUniformVariableIndex g.uniformVars[idx].name = g.uniformVariableName(idx) - g.uniformVars[idx].value.f32s = sizes + g.uniformVars[idx].value.Float32s = sizes g.uniformVars[idx].typ = shader.ir.Uniforms[idx] } dw, dh := destination.framebufferSize() @@ -293,14 +293,14 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm origin := []float32{float32(dstRegion.X) / float32(dw), float32(dstRegion.Y) / float32(dh)} const idx = graphics.TextureDestinationRegionOriginUniformVariableIndex g.uniformVars[idx].name = g.uniformVariableName(idx) - g.uniformVars[idx].value.f32s = origin + g.uniformVars[idx].value.Float32s = origin g.uniformVars[idx].typ = shader.ir.Uniforms[idx] } { size := []float32{float32(dstRegion.Width) / float32(dw), float32(dstRegion.Height) / float32(dh)} const idx = graphics.TextureDestinationRegionSizeUniformVariableIndex g.uniformVars[idx].name = g.uniformVariableName(idx) - g.uniformVars[idx].value.f32s = size + g.uniformVars[idx].value.Float32s = size g.uniformVars[idx].typ = shader.ir.Uniforms[idx] } { @@ -311,35 +311,28 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm } const idx = graphics.TextureSourceOffsetsUniformVariableIndex g.uniformVars[idx].name = g.uniformVariableName(idx) - g.uniformVars[idx].value.f32s = voffsets + g.uniformVars[idx].value.Float32s = voffsets g.uniformVars[idx].typ = shader.ir.Uniforms[idx] } { origin := []float32{float32(srcRegion.X), float32(srcRegion.Y)} const idx = graphics.TextureSourceRegionOriginUniformVariableIndex g.uniformVars[idx].name = g.uniformVariableName(idx) - g.uniformVars[idx].value.f32s = origin + g.uniformVars[idx].value.Float32s = origin g.uniformVars[idx].typ = shader.ir.Uniforms[idx] } { size := []float32{float32(srcRegion.Width), float32(srcRegion.Height)} const idx = graphics.TextureSourceRegionSizeUniformVariableIndex g.uniformVars[idx].name = g.uniformVariableName(idx) - g.uniformVars[idx].value.f32s = size + g.uniformVars[idx].value.Float32s = size g.uniformVars[idx].typ = shader.ir.Uniforms[idx] } for i, v := range uniforms { const offset = graphics.PreservedUniformVariablesNum g.uniformVars[i+offset].name = fmt.Sprintf("U%d", i+offset) - switch v := v.(type) { - case float32: - g.uniformVars[i+offset].value.f32 = v - case []float32: - g.uniformVars[i+offset].value.f32s = v - default: - return fmt.Errorf("opengl: unexpected uniform value: %v (type: %T)", v, v) - } + g.uniformVars[i+offset].value = v g.uniformVars[i+offset].typ = shader.ir.Uniforms[i+offset] } } diff --git a/internal/graphicsdriver/opengl/program.go b/internal/graphicsdriver/opengl/program.go index d213d3f7f..f1777d52c 100644 --- a/internal/graphicsdriver/opengl/program.go +++ b/internal/graphicsdriver/opengl/program.go @@ -120,11 +120,6 @@ type programKey struct { address driver.Address } -type uniformVariableValue struct { - f32 float32 - f32s []float32 -} - // openGLState is a state for type openGLState struct { // arrayBuffer is OpenGL's array buffer (vertices data). @@ -137,7 +132,7 @@ type openGLState struct { programs map[programKey]program lastProgram program - lastUniforms map[string]uniformVariableValue + lastUniforms map[string]driver.Uniform lastActiveTexture int } @@ -247,7 +242,7 @@ func areSameFloat32Array(a, b []float32) bool { type uniformVariable struct { name string - value uniformVariableValue + value driver.Uniform typ shaderir.Type } @@ -275,7 +270,7 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu } for _, u := range uniforms { - if len(u.value.f32s) == 0 { + if len(u.value.Float32s) == 0 { if u.typ.Main != shaderir.Float { expected := &shaderir.Type{Main: shaderir.Float} got := &u.typ @@ -283,33 +278,29 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu } cached, ok := g.state.lastUniforms[u.name] - if ok && cached.f32 == u.value.f32 { + if ok && cached.Float32 == u.value.Float32 { continue } // TODO: Remember whether the location is available or not. - g.context.uniformFloat(program, u.name, u.value.f32) + g.context.uniformFloat(program, u.name, u.value.Float32) if g.state.lastUniforms == nil { - g.state.lastUniforms = map[string]uniformVariableValue{} - } - g.state.lastUniforms[u.name] = uniformVariableValue{ - f32: u.value.f32, + g.state.lastUniforms = map[string]driver.Uniform{} } + g.state.lastUniforms[u.name] = u.value } else { - if got, expected := len(u.value.f32s), u.typ.FloatNum(); got != expected { + if got, expected := len(u.value.Float32s), u.typ.FloatNum(); got != expected { return fmt.Errorf("opengl: length of a uniform variables %s (%s) doesn't match: expected %d but %d", u.name, u.typ.String(), expected, got) } cached, ok := g.state.lastUniforms[u.name] - if ok && areSameFloat32Array(cached.f32s, u.value.f32s) { + if ok && areSameFloat32Array(cached.Float32s, u.value.Float32s) { continue } - g.context.uniformFloats(program, u.name, u.value.f32s, u.typ) + g.context.uniformFloats(program, u.name, u.value.Float32s, u.typ) if g.state.lastUniforms == nil { - g.state.lastUniforms = map[string]uniformVariableValue{} - } - g.state.lastUniforms[u.name] = uniformVariableValue{ - f32s: u.value.f32s, + g.state.lastUniforms = map[string]driver.Uniform{} } + g.state.lastUniforms[u.name] = u.value } } diff --git a/internal/mipmap/mipmap.go b/internal/mipmap/mipmap.go index 4b58bcdbc..f58b8ed1c 100644 --- a/internal/mipmap/mipmap.go +++ b/internal/mipmap/mipmap.go @@ -83,7 +83,7 @@ func (m *Mipmap) Pixels(x, y, width, height int) ([]byte, error) { return m.orig.Pixels(x, y, width, height) } -func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, evenOdd bool, canSkipMipmap bool) { +func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []driver.Uniform, evenOdd bool, canSkipMipmap bool) { if len(indices) == 0 { return } diff --git a/internal/restorable/image.go b/internal/restorable/image.go index 148c04397..c4c02d0d1 100644 --- a/internal/restorable/image.go +++ b/internal/restorable/image.go @@ -76,7 +76,7 @@ type drawTrianglesHistoryItem struct { dstRegion driver.Region srcRegion driver.Region shader *Shader - uniforms []interface{} + uniforms []driver.Uniform evenOdd bool } @@ -365,7 +365,7 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) { // 5: Color G // 6: Color B // 7: Color Y -func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}, evenOdd bool) { +func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []driver.Uniform, evenOdd bool) { if i.priority { panic("restorable: DrawTriangles cannot be called on a priority image") } @@ -410,7 +410,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [gra } // appendDrawTrianglesHistory appends a draw-image history item to the image. -func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}, evenOdd bool) { +func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []driver.Uniform, evenOdd bool) { if i.stale || i.volatile || i.screen { return } diff --git a/shader.go b/shader.go index dd470a06b..97aee88ab 100644 --- a/shader.go +++ b/shader.go @@ -21,6 +21,7 @@ import ( "go/token" "strings" + "github.com/hajimehoshi/ebiten/v2/internal/driver" "github.com/hajimehoshi/ebiten/v2/internal/graphics" "github.com/hajimehoshi/ebiten/v2/internal/mipmap" "github.com/hajimehoshi/ebiten/v2/internal/shader" @@ -172,7 +173,7 @@ func (s *Shader) Dispose() { s.shader = nil } -func (s *Shader) convertUniforms(uniforms map[string]interface{}) []interface{} { +func (s *Shader) convertUniforms(uniforms map[string]interface{}) []driver.Uniform { type index struct { resultIndex int shaderUniformIndex int @@ -191,20 +192,26 @@ func (s *Shader) convertUniforms(uniforms map[string]interface{}) []interface{} idx++ } - us := make([]interface{}, len(names)) + us := make([]driver.Uniform, len(names)) for name, idx := range names { if v, ok := uniforms[name]; ok { - // TODO: Check the uniform variable types? - us[idx.resultIndex] = v + switch v := v.(type) { + case float32: + us[idx.resultIndex] = driver.Uniform{ + Float32: v, + } + case []float32: + us[idx.resultIndex] = driver.Uniform{ + Float32s: v, + } + default: + panic(fmt.Sprintf("ebiten: unexpected uniform value type: %s, %T", name, v)) + } continue } t := s.uniformTypes[idx.shaderUniformIndex] - v := zeroUniformValue(t) - if v == nil { - panic(fmt.Sprintf("ebiten: unexpected uniform variable type: %s", t.String())) - } - us[idx.resultIndex] = v + us[idx.resultIndex] = zeroUniformValue(name, t) } // TODO: Panic if uniforms include an invalid name @@ -212,24 +219,17 @@ func (s *Shader) convertUniforms(uniforms map[string]interface{}) []interface{} return us } -func zeroUniformValue(t shaderir.Type) interface{} { +func zeroUniformValue(name string, t shaderir.Type) driver.Uniform { switch t.Main { - case shaderir.Bool: - return false - case shaderir.Int: - return 0 case shaderir.Float: - return float32(0) + return driver.Uniform{ + Float32: 0, + } case shaderir.Array: - switch t.Sub[0].Main { - case shaderir.Bool: - return make([]bool, t.Length) - case shaderir.Int: - return make([]int, t.Length) - default: - return make([]float32, t.FloatNum()) + return driver.Uniform{ + Float32s: make([]float32, t.FloatNum()), } default: - return make([]float32, t.FloatNum()) + panic(fmt.Sprintf("ebiten: unexpected uniform variable type: %s, %s", name, t.String())) } }