mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
internal/graphicsdriver/opengl: Optimization: Avoid the empty interface
This commit is contained in:
parent
60f2c7ace6
commit
1f82bb297c
@ -196,16 +196,20 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
|
|||||||
|
|
||||||
dw, dh := destination.framebufferSize()
|
dw, dh := destination.framebufferSize()
|
||||||
g.uniformVars = append(g.uniformVars, uniformVariable{
|
g.uniformVars = append(g.uniformVars, uniformVariable{
|
||||||
name: "viewport_size",
|
name: "viewport_size",
|
||||||
valueSlice: []float32{float32(dw), float32(dh)},
|
value: uniformVariableValue{
|
||||||
typ: shaderir.Type{Main: shaderir.Vec2},
|
f32s: []float32{float32(dw), float32(dh)},
|
||||||
|
},
|
||||||
|
typ: shaderir.Type{Main: shaderir.Vec2},
|
||||||
}, uniformVariable{
|
}, uniformVariable{
|
||||||
name: "source_region",
|
name: "source_region",
|
||||||
valueSlice: []float32{
|
value: uniformVariableValue{
|
||||||
srcRegion.X,
|
f32s: []float32{
|
||||||
srcRegion.Y,
|
srcRegion.X,
|
||||||
srcRegion.X + srcRegion.Width,
|
srcRegion.Y,
|
||||||
srcRegion.Y + srcRegion.Height,
|
srcRegion.X + srcRegion.Width,
|
||||||
|
srcRegion.Y + srcRegion.Height,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
typ: shaderir.Type{Main: shaderir.Vec4},
|
typ: shaderir.Type{Main: shaderir.Vec4},
|
||||||
})
|
})
|
||||||
@ -216,31 +220,39 @@ 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)
|
||||||
g.uniformVars = append(g.uniformVars, uniformVariable{
|
g.uniformVars = append(g.uniformVars, uniformVariable{
|
||||||
name: "color_matrix_body",
|
name: "color_matrix_body",
|
||||||
valueSlice: esBody[:],
|
value: uniformVariableValue{
|
||||||
typ: shaderir.Type{Main: shaderir.Mat4},
|
f32s: esBody[:],
|
||||||
|
},
|
||||||
|
typ: shaderir.Type{Main: shaderir.Mat4},
|
||||||
}, uniformVariable{
|
}, uniformVariable{
|
||||||
name: "color_matrix_translation",
|
name: "color_matrix_translation",
|
||||||
valueSlice: esTranslate[:],
|
value: uniformVariableValue{
|
||||||
typ: shaderir.Type{Main: shaderir.Vec4},
|
f32s: esTranslate[:],
|
||||||
|
},
|
||||||
|
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()
|
||||||
g.uniformVars = append(g.uniformVars, uniformVariable{
|
g.uniformVars = append(g.uniformVars, uniformVariable{
|
||||||
name: "source_size",
|
name: "source_size",
|
||||||
valueSlice: []float32{float32(sw), float32(sh)},
|
value: uniformVariableValue{
|
||||||
typ: shaderir.Type{Main: shaderir.Vec2},
|
f32s: []float32{float32(sw), float32(sh)},
|
||||||
|
},
|
||||||
|
typ: shaderir.Type{Main: shaderir.Vec2},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if filter == driver.FilterScreen {
|
if filter == driver.FilterScreen {
|
||||||
scale := float32(destination.width) / float32(g.images[srcIDs[0]].width)
|
scale := float32(destination.width) / float32(g.images[srcIDs[0]].width)
|
||||||
g.uniformVars = append(g.uniformVars, uniformVariable{
|
g.uniformVars = append(g.uniformVars, uniformVariable{
|
||||||
name: "scale",
|
name: "scale",
|
||||||
value: scale,
|
value: uniformVariableValue{
|
||||||
typ: shaderir.Type{Main: shaderir.Float},
|
f32: scale,
|
||||||
|
},
|
||||||
|
typ: shaderir.Type{Main: shaderir.Float},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -258,7 +270,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()
|
||||||
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
||||||
g.uniformVars[idx].valueSlice = []float32{float32(w), float32(h)}
|
g.uniformVars[idx].value.f32s = []float32{float32(w), float32(h)}
|
||||||
g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
|
g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -273,7 +285,7 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
|
|||||||
}
|
}
|
||||||
const idx = graphics.TextureSizesUniformVariableIndex
|
const idx = graphics.TextureSizesUniformVariableIndex
|
||||||
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
||||||
g.uniformVars[idx].valueSlice = sizes
|
g.uniformVars[idx].value.f32s = sizes
|
||||||
g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
|
g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
|
||||||
}
|
}
|
||||||
dw, dh := destination.framebufferSize()
|
dw, dh := destination.framebufferSize()
|
||||||
@ -281,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)}
|
origin := []float32{float32(dstRegion.X) / float32(dw), float32(dstRegion.Y) / float32(dh)}
|
||||||
const idx = graphics.TextureDestinationRegionOriginUniformVariableIndex
|
const idx = graphics.TextureDestinationRegionOriginUniformVariableIndex
|
||||||
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
||||||
g.uniformVars[idx].valueSlice = origin
|
g.uniformVars[idx].value.f32s = origin
|
||||||
g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
|
g.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
|
||||||
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
||||||
g.uniformVars[idx].valueSlice = size
|
g.uniformVars[idx].value.f32s = size
|
||||||
g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
|
g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -299,21 +311,21 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
|
|||||||
}
|
}
|
||||||
const idx = graphics.TextureSourceOffsetsUniformVariableIndex
|
const idx = graphics.TextureSourceOffsetsUniformVariableIndex
|
||||||
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
||||||
g.uniformVars[idx].valueSlice = voffsets
|
g.uniformVars[idx].value.f32s = voffsets
|
||||||
g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
|
g.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
|
||||||
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
||||||
g.uniformVars[idx].valueSlice = origin
|
g.uniformVars[idx].value.f32s = origin
|
||||||
g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
|
g.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
|
||||||
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
g.uniformVars[idx].name = g.uniformVariableName(idx)
|
||||||
g.uniformVars[idx].valueSlice = size
|
g.uniformVars[idx].value.f32s = size
|
||||||
g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
|
g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,9 +334,9 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
|
|||||||
g.uniformVars[i+offset].name = fmt.Sprintf("U%d", i+offset)
|
g.uniformVars[i+offset].name = fmt.Sprintf("U%d", i+offset)
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case float32:
|
case float32:
|
||||||
g.uniformVars[i+offset].value = v
|
g.uniformVars[i+offset].value.f32 = v
|
||||||
case []float32:
|
case []float32:
|
||||||
g.uniformVars[i+offset].valueSlice = v
|
g.uniformVars[i+offset].value.f32s = v
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("opengl: unexpected uniform value: %v (type: %T)", v, v)
|
return fmt.Errorf("opengl: unexpected uniform value: %v (type: %T)", v, v)
|
||||||
}
|
}
|
||||||
|
@ -120,6 +120,11 @@ type programKey struct {
|
|||||||
address driver.Address
|
address driver.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type uniformVariableValue struct {
|
||||||
|
f32 float32
|
||||||
|
f32s []float32
|
||||||
|
}
|
||||||
|
|
||||||
// openGLState is a state for
|
// openGLState is a state for
|
||||||
type openGLState struct {
|
type openGLState struct {
|
||||||
// arrayBuffer is OpenGL's array buffer (vertices data).
|
// arrayBuffer is OpenGL's array buffer (vertices data).
|
||||||
@ -132,7 +137,7 @@ type openGLState struct {
|
|||||||
programs map[programKey]program
|
programs map[programKey]program
|
||||||
|
|
||||||
lastProgram program
|
lastProgram program
|
||||||
lastUniforms map[string]interface{}
|
lastUniforms map[string]uniformVariableValue
|
||||||
lastActiveTexture int
|
lastActiveTexture int
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +154,9 @@ func (s *openGLState) reset(context *context) error {
|
|||||||
|
|
||||||
s.lastProgram = zeroProgram
|
s.lastProgram = zeroProgram
|
||||||
context.useProgram(zeroProgram)
|
context.useProgram(zeroProgram)
|
||||||
s.lastUniforms = map[string]interface{}{}
|
for key := range s.lastUniforms {
|
||||||
|
delete(s.lastUniforms, key)
|
||||||
|
}
|
||||||
|
|
||||||
// When context lost happens, deleting programs or buffers is not necessary.
|
// When context lost happens, deleting programs or buffers is not necessary.
|
||||||
// However, it is not assumed that reset is called only when context lost happens.
|
// However, it is not assumed that reset is called only when context lost happens.
|
||||||
@ -239,10 +246,9 @@ func areSameFloat32Array(a, b []float32) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type uniformVariable struct {
|
type uniformVariable struct {
|
||||||
name string
|
name string
|
||||||
value float32
|
value uniformVariableValue
|
||||||
valueSlice []float32
|
typ shaderir.Type
|
||||||
typ shaderir.Type
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type textureVariable struct {
|
type textureVariable struct {
|
||||||
@ -269,31 +275,41 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, u := range uniforms {
|
for _, u := range uniforms {
|
||||||
if len(u.valueSlice) == 0 {
|
if len(u.value.f32s) == 0 {
|
||||||
if u.typ.Main != shaderir.Float {
|
if u.typ.Main != shaderir.Float {
|
||||||
expected := &shaderir.Type{Main: shaderir.Float}
|
expected := &shaderir.Type{Main: shaderir.Float}
|
||||||
got := &u.typ
|
got := &u.typ
|
||||||
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]
|
||||||
if ok && cached == u.value {
|
if ok && cached.f32 == u.value.f32 {
|
||||||
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, u.value)
|
g.context.uniformFloat(program, u.name, u.value.f32)
|
||||||
g.state.lastUniforms[u.name] = u.value
|
if g.state.lastUniforms == nil {
|
||||||
|
g.state.lastUniforms = map[string]uniformVariableValue{}
|
||||||
|
}
|
||||||
|
g.state.lastUniforms[u.name] = uniformVariableValue{
|
||||||
|
f32: u.value.f32,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if got, expected := len(u.valueSlice), u.typ.FloatNum(); got != expected {
|
if got, expected := len(u.value.f32s), 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]
|
||||||
if ok && areSameFloat32Array(cached, u.valueSlice) {
|
if ok && areSameFloat32Array(cached.f32s, u.value.f32s) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
g.context.uniformFloats(program, u.name, u.valueSlice, u.typ)
|
g.context.uniformFloats(program, u.name, u.value.f32s, u.typ)
|
||||||
g.state.lastUniforms[u.name] = u.valueSlice
|
if g.state.lastUniforms == nil {
|
||||||
|
g.state.lastUniforms = map[string]uniformVariableValue{}
|
||||||
|
}
|
||||||
|
g.state.lastUniforms[u.name] = uniformVariableValue{
|
||||||
|
f32s: u.value.f32s,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user