graphicsdriver/opengl: Use glBindAttribLocation instead of glGetAttribLocation

Attribute variables are often optimized out and it is really hard
to prevent this.

Instead of implicit indices of attribute variables, use explicit
indices by glBindAttribLocation.

Bug: #816
This commit is contained in:
Hajime Hoshi 2019-02-16 14:03:21 +09:00
parent 7ff99d3965
commit 09ca873c41
6 changed files with 55 additions and 80 deletions

View File

@ -311,7 +311,7 @@ func (c *context) deleteShader(s shader) {
})
}
func (c *context) newProgram(shaders []shader) (program, error) {
func (c *context) newProgram(shaders []shader, attributes []string) (program, error) {
var pr program
if err := mainthread.Run(func() error {
p := gl.CreateProgram()
@ -322,6 +322,13 @@ func (c *context) newProgram(shaders []shader) (program, error) {
for _, shader := range shaders {
gl.AttachShader(p, uint32(shader))
}
for i, name := range attributes {
l, free := gl.Strs(name + "\x00")
gl.BindAttribLocation(p, uint32(i), *l)
free()
}
gl.LinkProgram(p)
var v int32
gl.GetProgramiv(p, gl.LINK_STATUS, &v)
@ -396,36 +403,23 @@ func (c *context) uniformFloats(p program, location string, v []float32) {
})
}
func (c *context) getAttribLocationImpl(p program, location string) attribLocation {
l, free := gl.Strs(location + "\x00")
attrib := attribLocation(gl.GetAttribLocation(uint32(p), *l))
free()
if attrib == -1 {
panic("opengl: invalid attrib location: " + location)
}
return attrib
}
func (c *context) vertexAttribPointer(p program, location string, size int, dataType dataType, stride int, offset int) {
func (c *context) vertexAttribPointer(p program, index int, size int, dataType dataType, stride int, offset int) {
_ = mainthread.Run(func() error {
l := c.locationCache.GetAttribLocation(c, p, location)
gl.VertexAttribPointer(uint32(l), int32(size), uint32(dataType), false, int32(stride), gl.PtrOffset(offset))
gl.VertexAttribPointer(uint32(index), int32(size), uint32(dataType), false, int32(stride), gl.PtrOffset(offset))
return nil
})
}
func (c *context) enableVertexAttribArray(p program, location string) {
func (c *context) enableVertexAttribArray(p program, index int) {
_ = mainthread.Run(func() error {
l := c.locationCache.GetAttribLocation(c, p, location)
gl.EnableVertexAttribArray(uint32(l))
gl.EnableVertexAttribArray(uint32(index))
return nil
})
}
func (c *context) disableVertexAttribArray(p program, location string) {
func (c *context) disableVertexAttribArray(p program, index int) {
_ = mainthread.Run(func() error {
l := c.locationCache.GetAttribLocation(c, p, location)
gl.DisableVertexAttribArray(uint32(l))
gl.DisableVertexAttribArray(uint32(index))
return nil
})
}

View File

@ -293,7 +293,7 @@ func (c *context) deleteShader(s shader) {
gl.Call("deleteShader", js.Value(s))
}
func (c *context) newProgram(shaders []shader) (program, error) {
func (c *context) newProgram(shaders []shader, attributes []string) (program, error) {
c.ensureGL()
gl := c.gl
v := gl.Call("createProgram")
@ -304,6 +304,11 @@ func (c *context) newProgram(shaders []shader) (program, error) {
for _, shader := range shaders {
gl.Call("attachShader", v, js.Value(shader))
}
for i, name := range attributes {
gl.Call("bindAttribLocation", v, i, name)
}
gl.Call("linkProgram", v)
if !gl.Call("getProgramParameter", v, linkStatus).Bool() {
return program{}, errors.New("opengl: program error")
@ -374,31 +379,22 @@ func (c *context) uniformFloats(p program, location string, v []float32) {
}
}
func (c *context) getAttribLocationImpl(p program, location string) attribLocation {
func (c *context) vertexAttribPointer(p program, index int, size int, dataType dataType, stride int, offset int) {
c.ensureGL()
gl := c.gl
return attribLocation(gl.Call("getAttribLocation", p.value, location).Int())
gl.Call("vertexAttribPointer", index, size, int(dataType), false, stride, offset)
}
func (c *context) vertexAttribPointer(p program, location string, size int, dataType dataType, stride int, offset int) {
func (c *context) enableVertexAttribArray(p program, index int) {
c.ensureGL()
gl := c.gl
l := c.locationCache.GetAttribLocation(c, p, location)
gl.Call("vertexAttribPointer", int(l), size, int(dataType), false, stride, offset)
gl.Call("enableVertexAttribArray", index)
}
func (c *context) enableVertexAttribArray(p program, location string) {
func (c *context) disableVertexAttribArray(p program, index int) {
c.ensureGL()
gl := c.gl
l := c.locationCache.GetAttribLocation(c, p, location)
gl.Call("enableVertexAttribArray", int(l))
}
func (c *context) disableVertexAttribArray(p program, location string) {
c.ensureGL()
gl := c.gl
l := c.locationCache.GetAttribLocation(c, p, location)
gl.Call("disableVertexAttribArray", int(l))
gl.Call("disableVertexAttribArray", index)
}
func (c *context) newArrayBuffer(size int) buffer {

View File

@ -243,7 +243,7 @@ func (c *context) deleteShader(s shader) {
gl.DeleteShader(mgl.Shader(s))
}
func (c *context) newProgram(shaders []shader) (program, error) {
func (c *context) newProgram(shaders []shader, attributes []string) (program, error) {
gl := c.gl
p := gl.CreateProgram()
if p.Value == 0 {
@ -253,6 +253,11 @@ func (c *context) newProgram(shaders []shader) (program, error) {
for _, shader := range shaders {
gl.AttachShader(p, mgl.Shader(shader))
}
for i, name := range attributes {
gl.BindAttribLocation(p, mgl.Attrib{uint(i)}, name)
}
gl.LinkProgram(p)
v := gl.GetProgrami(p, mgl.LINK_STATUS)
if v == mgl.FALSE {
@ -308,31 +313,19 @@ func (c *context) uniformFloats(p program, location string, v []float32) {
}
}
func (c *context) getAttribLocationImpl(p program, location string) attribLocation {
func (c *context) vertexAttribPointer(p program, index int, size int, dataType dataType, stride int, offset int) {
gl := c.gl
a := attribLocation(gl.GetAttribLocation(mgl.Program(p), location))
if a.Value == ^uint(0) {
panic("invalid attrib location: " + location)
}
return a
gl.VertexAttribPointer(mgl.Attrib{uint(index)}, size, mgl.Enum(dataType), false, stride, offset)
}
func (c *context) vertexAttribPointer(p program, location string, size int, dataType dataType, stride int, offset int) {
func (c *context) enableVertexAttribArray(p program, index int) {
gl := c.gl
l := c.locationCache.GetAttribLocation(c, p, location)
gl.VertexAttribPointer(mgl.Attrib(l), size, mgl.Enum(dataType), false, stride, offset)
gl.EnableVertexAttribArray(mgl.Attrib{uint(index)})
}
func (c *context) enableVertexAttribArray(p program, location string) {
func (c *context) disableVertexAttribArray(p program, index int) {
gl := c.gl
l := c.locationCache.GetAttribLocation(c, p, location)
gl.EnableVertexAttribArray(mgl.Attrib(l))
}
func (c *context) disableVertexAttribArray(p program, location string) {
gl := c.gl
l := c.locationCache.GetAttribLocation(c, p, location)
gl.DisableVertexAttribArray(mgl.Attrib(l))
gl.DisableVertexAttribArray(mgl.Attrib{uint(index)})
}
func (c *context) newArrayBuffer(size int) buffer {

View File

@ -18,13 +18,11 @@ package opengl
type locationCache struct {
uniformLocationCache map[programID]map[string]uniformLocation
attribLocationCache map[programID]map[string]attribLocation
}
func newLocationCache() *locationCache {
return &locationCache{
uniformLocationCache: map[programID]map[string]uniformLocation{},
attribLocationCache: map[programID]map[string]attribLocation{},
}
}
@ -40,16 +38,3 @@ func (c *locationCache) GetUniformLocation(context *context, p program, location
}
return l
}
func (c *locationCache) GetAttribLocation(context *context, p program, location string) attribLocation {
id := getProgramID(p)
if _, ok := c.attribLocationCache[id]; !ok {
c.attribLocationCache[id] = map[string]attribLocation{}
}
l, ok := c.attribLocationCache[id][location]
if !ok {
l = context.getAttribLocationImpl(p, location)
c.attribLocationCache[id][location] = l
}
return l
}

View File

@ -38,6 +38,14 @@ type arrayBufferLayout struct {
total int
}
func (a *arrayBufferLayout) names() []string {
ns := make([]string, len(a.parts))
for i, p := range a.parts {
ns[i] = p.name
}
return ns
}
// totalBytes returns the size in bytes for one element of the array buffer.
func (a *arrayBufferLayout) totalBytes() int {
if a.total != 0 {
@ -58,13 +66,13 @@ func (a *arrayBufferLayout) newArrayBuffer(context *context) buffer {
// enable binds the array buffer the given program to use the array buffer.
func (a *arrayBufferLayout) enable(context *context, program program) {
for _, p := range a.parts {
context.enableVertexAttribArray(program, p.name)
for i := range a.parts {
context.enableVertexAttribArray(program, i)
}
total := a.totalBytes()
offset := 0
for _, p := range a.parts {
context.vertexAttribPointer(program, p.name, p.num, float, total, offset)
for i, p := range a.parts {
context.vertexAttribPointer(program, i, p.num, float, total, offset)
offset += float.SizeInBytes() * p.num
}
}
@ -72,8 +80,8 @@ func (a *arrayBufferLayout) enable(context *context, program program) {
// disable stops using the array buffer.
func (a *arrayBufferLayout) disable(context *context, program program) {
// TODO: Disabling should be done in reversed order?
for _, p := range a.parts {
context.disableVertexAttribArray(program, p.name)
for i := range a.parts {
context.disableVertexAttribArray(program, i)
}
}
@ -210,10 +218,12 @@ func (s *openGLState) reset(context *context) error {
program, err := context.newProgram([]shader{
shaderVertexModelviewNative,
shaderFragmentColorMatrixNative,
})
}, theArrayBufferLayout.names())
if err != nil {
return err
}
s.programs[programKey{
filter: f,
address: a,

View File

@ -234,9 +234,6 @@ void main(void) {
highp vec2 p0 = pos - texel_size / 2.0 / scale;
highp vec2 p1 = pos + texel_size / 2.0 / scale;
// Prevent this variable from being optimized out.
p0 += varying_tex_region.xy - varying_tex_region.xy;
p1 = adjustTexel(p0, p1);
vec4 c0 = texture2D(texture, p0);