internal/driver: Optimization: Replace interface{} with driver.Uniform

Converting a value from/to interface{} can create a value in heap
and this is not efficient.
This commit is contained in:
Hajime Hoshi 2021-10-30 02:51:02 +09:00
parent 1f82bb297c
commit 06f4142ca0
11 changed files with 128 additions and 114 deletions

View File

@ -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)")
}

View File

@ -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")

View File

@ -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.

View File

@ -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
}

View File

@ -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]

View File

@ -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 {

View File

@ -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]
}
}

View File

@ -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
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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()))
}
}