internal/graphicsdriver/opengl: Optimization: Avoid interface conversion

This commit is contained in:
Hajime Hoshi 2021-10-29 21:35:40 +09:00
parent 71b2b439f4
commit 3c1f8da7f8
2 changed files with 41 additions and 36 deletions

View File

@ -172,12 +172,12 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
dw, dh := destination.framebufferSize() dw, dh := destination.framebufferSize()
uniformVars = append(uniformVars, uniformVariable{ uniformVars = append(uniformVars, uniformVariable{
name: "viewport_size", name: "viewport_size",
value: []float32{float32(dw), float32(dh)}, valueSlice: []float32{float32(dw), float32(dh)},
typ: shaderir.Type{Main: shaderir.Vec2}, typ: shaderir.Type{Main: shaderir.Vec2},
}, uniformVariable{ }, uniformVariable{
name: "source_region", name: "source_region",
value: []float32{ valueSlice: []float32{
srcRegion.X, srcRegion.X,
srcRegion.Y, srcRegion.Y,
srcRegion.X + srcRegion.Width, srcRegion.X + srcRegion.Width,
@ -192,22 +192,22 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
var esTranslate [4]float32 var esTranslate [4]float32
colorM.Elements(&esBody, &esTranslate) colorM.Elements(&esBody, &esTranslate)
uniformVars = append(uniformVars, uniformVariable{ uniformVars = append(uniformVars, uniformVariable{
name: "color_matrix_body", name: "color_matrix_body",
value: esBody[:], valueSlice: esBody[:],
typ: shaderir.Type{Main: shaderir.Mat4}, typ: shaderir.Type{Main: shaderir.Mat4},
}, uniformVariable{ }, uniformVariable{
name: "color_matrix_translation", name: "color_matrix_translation",
value: esTranslate[:], valueSlice: esTranslate[:],
typ: shaderir.Type{Main: shaderir.Vec4}, typ: shaderir.Type{Main: shaderir.Vec4},
}) })
} }
if filter != driver.FilterNearest { if filter != driver.FilterNearest {
sw, sh := g.images[srcIDs[0]].framebufferSize() sw, sh := g.images[srcIDs[0]].framebufferSize()
uniformVars = append(uniformVars, uniformVariable{ uniformVars = append(uniformVars, uniformVariable{
name: "source_size", name: "source_size",
value: []float32{float32(sw), float32(sh)}, valueSlice: []float32{float32(sw), float32(sh)},
typ: shaderir.Type{Main: shaderir.Vec2}, typ: shaderir.Type{Main: shaderir.Vec2},
}) })
} }
@ -228,7 +228,7 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
const idx = graphics.DestinationTextureSizeUniformVariableIndex const idx = graphics.DestinationTextureSizeUniformVariableIndex
w, h := destination.framebufferSize() w, h := destination.framebufferSize()
uniformVars[idx].name = fmt.Sprintf("U%d", idx) uniformVars[idx].name = fmt.Sprintf("U%d", idx)
uniformVars[idx].value = []float32{float32(w), float32(h)} uniformVars[idx].valueSlice = []float32{float32(w), float32(h)}
uniformVars[idx].typ = shader.ir.Uniforms[idx] uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
{ {
@ -243,7 +243,7 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
} }
const idx = graphics.TextureSizesUniformVariableIndex const idx = graphics.TextureSizesUniformVariableIndex
uniformVars[idx].name = fmt.Sprintf("U%d", idx) uniformVars[idx].name = fmt.Sprintf("U%d", idx)
uniformVars[idx].value = sizes uniformVars[idx].valueSlice = sizes
uniformVars[idx].typ = shader.ir.Uniforms[idx] uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
dw, dh := destination.framebufferSize() dw, dh := destination.framebufferSize()
@ -251,14 +251,14 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
origin := []float32{float32(dstRegion.X) / float32(dw), float32(dstRegion.Y) / float32(dh)} origin := []float32{float32(dstRegion.X) / float32(dw), float32(dstRegion.Y) / float32(dh)}
const idx = graphics.TextureDestinationRegionOriginUniformVariableIndex const idx = graphics.TextureDestinationRegionOriginUniformVariableIndex
uniformVars[idx].name = fmt.Sprintf("U%d", idx) uniformVars[idx].name = fmt.Sprintf("U%d", idx)
uniformVars[idx].value = origin uniformVars[idx].valueSlice = origin
uniformVars[idx].typ = shader.ir.Uniforms[idx] uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
{ {
size := []float32{float32(dstRegion.Width) / float32(dw), float32(dstRegion.Height) / float32(dh)} size := []float32{float32(dstRegion.Width) / float32(dw), float32(dstRegion.Height) / float32(dh)}
const idx = graphics.TextureDestinationRegionSizeUniformVariableIndex const idx = graphics.TextureDestinationRegionSizeUniformVariableIndex
uniformVars[idx].name = fmt.Sprintf("U%d", idx) uniformVars[idx].name = fmt.Sprintf("U%d", idx)
uniformVars[idx].value = size uniformVars[idx].valueSlice = size
uniformVars[idx].typ = shader.ir.Uniforms[idx] uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
{ {
@ -269,28 +269,35 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
} }
const idx = graphics.TextureSourceOffsetsUniformVariableIndex const idx = graphics.TextureSourceOffsetsUniformVariableIndex
uniformVars[idx].name = fmt.Sprintf("U%d", idx) uniformVars[idx].name = fmt.Sprintf("U%d", idx)
uniformVars[idx].value = voffsets uniformVars[idx].valueSlice = voffsets
uniformVars[idx].typ = shader.ir.Uniforms[idx] uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
{ {
origin := []float32{float32(srcRegion.X), float32(srcRegion.Y)} origin := []float32{float32(srcRegion.X), float32(srcRegion.Y)}
const idx = graphics.TextureSourceRegionOriginUniformVariableIndex const idx = graphics.TextureSourceRegionOriginUniformVariableIndex
uniformVars[idx].name = fmt.Sprintf("U%d", idx) uniformVars[idx].name = fmt.Sprintf("U%d", idx)
uniformVars[idx].value = origin uniformVars[idx].valueSlice = origin
uniformVars[idx].typ = shader.ir.Uniforms[idx] uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
{ {
size := []float32{float32(srcRegion.Width), float32(srcRegion.Height)} size := []float32{float32(srcRegion.Width), float32(srcRegion.Height)}
const idx = graphics.TextureSourceRegionSizeUniformVariableIndex const idx = graphics.TextureSourceRegionSizeUniformVariableIndex
uniformVars[idx].name = fmt.Sprintf("U%d", idx) uniformVars[idx].name = fmt.Sprintf("U%d", idx)
uniformVars[idx].value = size uniformVars[idx].valueSlice = size
uniformVars[idx].typ = shader.ir.Uniforms[idx] uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
for i, v := range uniforms { for i, v := range uniforms {
const offset = graphics.PreservedUniformVariablesNum const offset = graphics.PreservedUniformVariablesNum
uniformVars[i+offset].name = fmt.Sprintf("U%d", i+offset) uniformVars[i+offset].name = fmt.Sprintf("U%d", i+offset)
uniformVars[i+offset].value = v switch v := v.(type) {
case float32:
uniformVars[i+offset].value = v
case []float32:
uniformVars[i+offset].valueSlice = v
default:
return fmt.Errorf("opengl: unexpected uniform value: %v (type: %T)", v, v)
}
uniformVars[i+offset].typ = shader.ir.Uniforms[i+offset] uniformVars[i+offset].typ = shader.ir.Uniforms[i+offset]
} }
} }

View File

@ -239,9 +239,10 @@ func areSameFloat32Array(a, b []float32) bool {
} }
type uniformVariable struct { type uniformVariable struct {
name string name string
value interface{} value float32
typ shaderir.Type valueSlice []float32
typ shaderir.Type
} }
type textureVariable struct { type textureVariable struct {
@ -268,32 +269,29 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
} }
for _, u := range uniforms { for _, u := range uniforms {
switch v := u.value.(type) { if len(u.valueSlice) == 0 {
case float32:
if got, expected := (&shaderir.Type{Main: shaderir.Float}), &u.typ; !got.Equal(expected) { if got, expected := (&shaderir.Type{Main: shaderir.Float}), &u.typ; !got.Equal(expected) {
return fmt.Errorf("opengl: uniform variable %s type doesn't match: expected %s but %s", u.name, expected.String(), got.String()) return fmt.Errorf("opengl: uniform variable %s type doesn't match: expected %s but %s", u.name, expected.String(), got.String())
} }
cached, ok := g.state.lastUniforms[u.name].(float32) cached, ok := g.state.lastUniforms[u.name].(float32)
if ok && cached == v { if ok && cached == u.value {
continue continue
} }
// TODO: Remember whether the location is available or not. // TODO: Remember whether the location is available or not.
g.context.uniformFloat(program, u.name, v) g.context.uniformFloat(program, u.name, u.value)
g.state.lastUniforms[u.name] = v g.state.lastUniforms[u.name] = u.value
case []float32: } else {
if got, expected := len(v), u.typ.FloatNum(); got != expected { if got, expected := len(u.valueSlice), 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) 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].([]float32) cached, ok := g.state.lastUniforms[u.name].([]float32)
if ok && areSameFloat32Array(cached, v) { if ok && areSameFloat32Array(cached, u.valueSlice) {
continue continue
} }
g.context.uniformFloats(program, u.name, v, u.typ) g.context.uniformFloats(program, u.name, u.valueSlice, u.typ)
g.state.lastUniforms[u.name] = v g.state.lastUniforms[u.name] = u.valueSlice
default:
return fmt.Errorf("opengl: unexpected uniform value: %v (type: %T)", u.value, u.value)
} }
} }