graphicsdriver/opengl: Ignore non-existent uniform locations

Shader users should not have to care about the existence of uniform
variables.

Updates #1168
This commit is contained in:
Hajime Hoshi 2020-05-27 11:07:21 +09:00
parent f80719ef9a
commit 1c980a16f5
5 changed files with 68 additions and 31 deletions

View File

@ -71,6 +71,7 @@ type programID uint32
const (
invalidTexture = 0
invalidFramebuffer = (1 << 32) - 1
invalidUniform = -1
)
func getProgramID(p program) programID {
@ -383,31 +384,45 @@ func (c *context) getUniformLocationImpl(p program, location string) uniformLoca
l, free := gl.Strs(location + "\x00")
uniform := uniformLocation(gl.GetUniformLocation(uint32(p), *l))
free()
if uniform == -1 {
panic("opengl: invalid uniform location: " + location)
}
return uniform
}
func (c *context) uniformInt(p program, location string, v int) {
func (c *context) uniformInt(p program, location string, v int) bool {
var r bool
_ = c.t.Call(func() error {
l := int32(c.locationCache.GetUniformLocation(c, p, location))
if l == invalidUniform {
return nil
}
r = true
gl.Uniform1i(l, int32(v))
return nil
})
return r
}
func (c *context) uniformFloat(p program, location string, v float32) {
func (c *context) uniformFloat(p program, location string, v float32) bool {
var r bool
_ = c.t.Call(func() error {
l := int32(c.locationCache.GetUniformLocation(c, p, location))
if l == invalidUniform {
return nil
}
r = true
gl.Uniform1f(l, v)
return nil
})
return r
}
func (c *context) uniformFloats(p program, location string, v []float32) {
func (c *context) uniformFloats(p program, location string, v []float32) bool {
var r bool
_ = c.t.Call(func() error {
l := int32(c.locationCache.GetUniformLocation(c, p, location))
if l == invalidUniform {
return nil
}
r = true
switch len(v) {
case 2:
gl.Uniform2fv(l, 1, (*float32)(gl.Ptr(v)))
@ -420,6 +435,7 @@ func (c *context) uniformFloats(p program, location string, v []float32) {
}
return nil
})
return r
}
func (c *context) vertexAttribPointer(p program, index int, size int, dataType dataType, stride int, offset int) {

View File

@ -67,6 +67,8 @@ func (p program) equal(rhs program) bool {
var InvalidTexture = textureNative(js.Null())
var invalidUniform = uniformLocation(js.Null())
func getProgramID(p program) programID {
return p.id
}
@ -423,24 +425,35 @@ func (c *context) getUniformLocationImpl(p program, location string) uniformLoca
return uniformLocation(gl.Call("getUniformLocation", p.value, location))
}
func (c *context) uniformInt(p program, location string, v int) {
func (c *context) uniformInt(p program, location string, v int) bool {
c.ensureGL()
gl := c.gl
l := c.locationCache.GetUniformLocation(c, p, location)
if l.equal(invalidUniform) {
return false
}
gl.Call("uniform1i", js.Value(l), v)
return true
}
func (c *context) uniformFloat(p program, location string, v float32) {
func (c *context) uniformFloat(p program, location string, v float32) bool {
c.ensureGL()
gl := c.gl
l := c.locationCache.GetUniformLocation(c, p, location)
if l.equal(invalidUniform) {
return false
}
gl.Call("uniform1f", js.Value(l), v)
return true
}
func (c *context) uniformFloats(p program, location string, v []float32) {
func (c *context) uniformFloats(p program, location string, v []float32) bool {
c.ensureGL()
gl := c.gl
l := c.locationCache.GetUniformLocation(c, p, location)
if l.equal(invalidUniform) {
return false
}
switch len(v) {
case 2:
gl.Call("uniform2f", js.Value(l), v[0], v[1])
@ -454,6 +467,7 @@ func (c *context) uniformFloats(p program, location string, v []float32) {
default:
panic(fmt.Sprintf("opengl: invalid uniform floats num: %d", len(v)))
}
return true
}
func (c *context) vertexAttribPointer(p program, index int, size int, dataType dataType, stride int, offset int) {

View File

@ -69,6 +69,7 @@ type programID uint32
var (
invalidTexture = textureNative(mgl.Texture{})
invalidFramebuffer = framebufferNative(mgl.Framebuffer{(1 << 32) - 1})
invalidUniform = uniformLocation(mgl.Uniform{-1})
)
func getProgramID(p program) programID {
@ -286,35 +287,46 @@ func (c *context) deleteProgram(p program) {
func (c *context) getUniformLocationImpl(p program, location string) uniformLocation {
gl := c.gl
u := uniformLocation(gl.GetUniformLocation(mgl.Program(p), location))
if u.Value == -1 {
panic("invalid uniform location: " + location)
}
return u
}
func (c *context) uniformInt(p program, location string, v int) {
func (c *context) uniformInt(p program, location string, v int) bool {
gl := c.gl
gl.Uniform1i(mgl.Uniform(c.locationCache.GetUniformLocation(c, p, location)), v)
l := c.locationCache.GetUniformLocation(c, p, location)
if l == invalidUniform {
return false
}
gl.Uniform1i(mgl.Uniform(l), v)
return true
}
func (c *context) uniformFloat(p program, location string, v float32) {
func (c *context) uniformFloat(p program, location string, v float32) bool {
gl := c.gl
gl.Uniform1f(mgl.Uniform(c.locationCache.GetUniformLocation(c, p, location)), v)
l := c.locationCache.GetUniformLocation(c, p, location)
if l == invalidUniform {
return false
}
gl.Uniform1f(mgl.Uniform(l), v)
return true
}
func (c *context) uniformFloats(p program, location string, v []float32) {
func (c *context) uniformFloats(p program, location string, v []float32) bool {
gl := c.gl
l := mgl.Uniform(c.locationCache.GetUniformLocation(c, p, location))
l := c.locationCache.GetUniformLocation(c, p, location)
if l == invalidUniform {
return false
}
switch len(v) {
case 2:
gl.Uniform2fv(l, v)
gl.Uniform2fv(mgl.Uniform(l), v)
case 4:
gl.Uniform4fv(l, v)
gl.Uniform4fv(mgl.Uniform(l), v)
case 16:
gl.UniformMatrix4fv(l, v)
gl.UniformMatrix4fv(mgl.Uniform(l), v)
default:
panic(fmt.Sprintf("opengl: invalid uniform floats num: %d", len(v)))
}
return true
}
func (c *context) vertexAttribPointer(p program, index int, size int, dataType dataType, stride int, offset int) {

View File

@ -266,6 +266,7 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable) error
if ok && cached == v {
continue
}
// TODO: Remember whether the location is available or not.
g.context.uniformFloat(program, u.name, v)
g.state.lastUniforms[u.name] = v
case []float32:
@ -283,9 +284,6 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable) error
g.state.lastActiveTexture = u.textureIndex
}
g.context.bindTexture(v)
case nil:
// TODO: Rather than using nil for skipping, check the availablity of locations at e.g.,
// uniformFloats and ignore the error for unavailability.
default:
return fmt.Errorf("opengl: unexpected uniform value: %v", u.value)
}

View File

@ -112,18 +112,15 @@ func TestShaderMultipleSources(t *testing.T) {
ir := etesting.ShaderProgramImages(3)
s := NewShader(&ir)
// TODO: Now GLSL's optimization eliminates unused uniform variables by the program. Now nils are given,
// but it is strange to care about optimization from users. We should ignore the error when the location is
// not available.
us := []interface{}{
[]float32{1, 1},
srcs[0],
srcs[1],
nil, // []float32{1, 1},
nil, // []float32{0, 0, 1, 1},
[]float32{1, 1},
[]float32{0, 0, 1, 1},
srcs[2],
nil, // []float32{1, 1},
nil, // []float32{0, 0, 1, 1},
[]float32{1, 1},
[]float32{0, 0, 1, 1},
}
dst.DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero, s, us)