graphicsdriver/opengl: Add type checks of uniform variables

This commit is contained in:
Hajime Hoshi 2020-07-30 11:27:36 +09:00
parent c352e69689
commit da5642cd0e
3 changed files with 43 additions and 0 deletions

View File

@ -179,6 +179,7 @@ func (g *Graphics) Draw(dst, src driver.ImageID, indexLen int, indexOffset int,
uniforms = append(uniforms, uniformVariable{
name: "viewport_size",
value: []float32{float32(vw), float32(vh)},
typ: shaderir.Type{Main: shaderir.Vec2},
}, uniformVariable{
name: "source_region",
value: []float32{
@ -187,6 +188,7 @@ func (g *Graphics) Draw(dst, src driver.ImageID, indexLen int, indexOffset int,
sourceRegion.X + sourceRegion.Width,
sourceRegion.Y + sourceRegion.Height,
},
typ: shaderir.Type{Main: shaderir.Vec4},
})
if colorM != nil {
@ -195,9 +197,11 @@ func (g *Graphics) Draw(dst, src driver.ImageID, indexLen int, indexOffset int,
uniforms = append(uniforms, uniformVariable{
name: "color_matrix_body",
value: esBody,
typ: shaderir.Type{Main: shaderir.Mat4},
}, uniformVariable{
name: "color_matrix_translation",
value: esTranslate,
typ: shaderir.Type{Main: shaderir.Vec4},
})
}
@ -208,6 +212,7 @@ func (g *Graphics) Draw(dst, src driver.ImageID, indexLen int, indexOffset int,
uniforms = append(uniforms, uniformVariable{
name: "source_size",
value: []float32{float32(sw), float32(sh)},
typ: shaderir.Type{Main: shaderir.Vec2},
})
}
@ -216,6 +221,7 @@ func (g *Graphics) Draw(dst, src driver.ImageID, indexLen int, indexOffset int,
uniforms = append(uniforms, uniformVariable{
name: "scale",
value: scale,
typ: shaderir.Type{Main: shaderir.Float},
})
}
@ -303,6 +309,7 @@ func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]
vh := graphics.InternalImageSize(d.height)
us[0].name = "U0"
us[0].value = []float32{float32(vw), float32(vh)}
us[0].typ = s.ir.Uniforms[0]
for i, src := range srcs {
img := g.images[src]
@ -313,6 +320,7 @@ func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]
const offset = 1
us[i+offset].name = fmt.Sprintf("U%d", i+offset)
us[i+offset].value = []float32{float32(w), float32(h)}
us[i+offset].typ = s.ir.Uniforms[i+offset]
}
for i, o := range offsets {
@ -320,12 +328,14 @@ func (g *Graphics) DrawShader(dst driver.ImageID, srcs [graphics.ShaderImageNum]
o := o
us[i+offset].name = fmt.Sprintf("U%d", i+offset)
us[i+offset].value = o[:]
us[i+offset].typ = s.ir.Uniforms[i+offset]
}
for i, v := range uniforms {
const offset = graphics.PreservedUniformVariablesNum
us[i+offset].name = fmt.Sprintf("U%d", i+offset)
us[i+offset].value = v
us[i+offset].typ = s.ir.Uniforms[i+offset]
}
var ts [graphics.ShaderImageNum]textureVariable

View File

@ -19,6 +19,7 @@ import (
"github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/graphics"
"github.com/hajimehoshi/ebiten/internal/shaderir"
"github.com/hajimehoshi/ebiten/internal/web"
)
@ -237,6 +238,7 @@ func areSameFloat32Array(a, b []float32) bool {
type uniformVariable struct {
name string
value interface{}
typ shaderir.Type
}
type textureVariable struct {
@ -265,6 +267,10 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
case nil:
// Do nothing.
case float32:
if got, expected := (&shaderir.Type{Main: shaderir.Float}), &u.typ; !got.Equal(expected) {
return fmt.Errorf("opengl: uniform variable type doesn't match: expected %s but %s", expected.String(), got.String())
}
cached, ok := g.state.lastUniforms[u.name].(float32)
if ok && cached == v {
continue
@ -273,6 +279,10 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
g.context.uniformFloat(program, u.name, v)
g.state.lastUniforms[u.name] = v
case []float32:
if got, expected := u.typ.FloatNum(), len(v); got != expected {
return fmt.Errorf("opengl: length of a uniform variables doesn't match: expected %d but %d", expected, got)
}
cached, ok := g.state.lastUniforms[u.name].([]float32)
if ok && areSameFloat32Array(cached, v) {
continue

View File

@ -96,6 +96,29 @@ func (t *Type) Glsl() string {
}
}
func (t *Type) FloatNum() int {
switch t.Main {
case Float:
return 1
case Vec2:
return 2
case Vec3:
return 3
case Vec4:
return 4
case Mat2:
return 4
case Mat3:
return 9
case Mat4:
return 16
case Array:
return t.Length * t.Sub[0].FloatNum()
default: // TODO: Parse a struct correctly
return -1
}
}
type BasicType int
const (