internal/graphicsdriver/opengl: record last uniform variables and reset them before swapping buffers

This is basically a revert of 6b4c696b31.
This change resets the last uniform variables before swapping
buffers.

Updates #2517
This commit is contained in:
Hajime Hoshi 2023-01-03 03:04:41 +09:00
parent aa00293fea
commit edf35b02cb
2 changed files with 39 additions and 1 deletions

View File

@ -265,6 +265,11 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
g.context.ctx.Disable(gl.STENCIL_TEST)
}
// The last uniforms must be reset after swapping the buffer (#2517).
if destination.screen {
g.state.resetLastUniforms()
}
return nil
}

View File

@ -124,6 +124,7 @@ type openGLState struct {
elementArrayBuffer buffer
lastProgram program
lastUniforms map[string][]uint32
lastActiveTexture int
}
@ -135,6 +136,9 @@ func (s *openGLState) reset(context *context) error {
s.lastProgram = 0
context.ctx.UseProgram(0)
for key := range s.lastUniforms {
delete(s.lastUniforms, key)
}
// On browsers (at least Chrome), buffers are already detached from the context
// and must not be deleted by DeleteBuffer.
@ -157,6 +161,25 @@ func (s *openGLState) reset(context *context) error {
return nil
}
func (s *openGLState) resetLastUniforms() {
for k := range s.lastUniforms {
delete(s.lastUniforms, k)
}
}
// areSameUint32Array returns a boolean indicating if a and b are deeply equal.
func areSameUint32Array(a, b []uint32) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
type uniformVariable struct {
name string
value []uint32
@ -191,6 +214,9 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
}
g.state.lastProgram = program
for k := range g.state.lastUniforms {
delete(g.state.lastUniforms, k)
}
g.state.lastActiveTexture = 0
g.context.ctx.ActiveTexture(gl.TEXTURE0)
}
@ -206,8 +232,15 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
return fmt.Errorf("opengl: length of a uniform variables %s (%s) doesn't match: expected %d but %d", u.name, typ.String(), expected, got)
}
// Set the uniform variables, even though they are the same as the last time (#2517).
cached, ok := g.state.lastUniforms[u.name]
if ok && areSameUint32Array(cached, u.value) {
continue
}
g.context.uniforms(program, u.name, u.value, u.typ)
if g.state.lastUniforms == nil {
g.state.lastUniforms = map[string][]uint32{}
}
g.state.lastUniforms[u.name] = u.value
}
var idx int