mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
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:
parent
7ff99d3965
commit
09ca873c41
@ -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
|
var pr program
|
||||||
if err := mainthread.Run(func() error {
|
if err := mainthread.Run(func() error {
|
||||||
p := gl.CreateProgram()
|
p := gl.CreateProgram()
|
||||||
@ -322,6 +322,13 @@ func (c *context) newProgram(shaders []shader) (program, error) {
|
|||||||
for _, shader := range shaders {
|
for _, shader := range shaders {
|
||||||
gl.AttachShader(p, uint32(shader))
|
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)
|
gl.LinkProgram(p)
|
||||||
var v int32
|
var v int32
|
||||||
gl.GetProgramiv(p, gl.LINK_STATUS, &v)
|
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 {
|
func (c *context) vertexAttribPointer(p program, index int, size int, dataType dataType, stride int, offset int) {
|
||||||
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) {
|
|
||||||
_ = mainthread.Run(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
gl.VertexAttribPointer(uint32(index), int32(size), uint32(dataType), false, int32(stride), gl.PtrOffset(offset))
|
||||||
gl.VertexAttribPointer(uint32(l), int32(size), uint32(dataType), false, int32(stride), gl.PtrOffset(offset))
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) enableVertexAttribArray(p program, location string) {
|
func (c *context) enableVertexAttribArray(p program, index int) {
|
||||||
_ = mainthread.Run(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
gl.EnableVertexAttribArray(uint32(index))
|
||||||
gl.EnableVertexAttribArray(uint32(l))
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) disableVertexAttribArray(p program, location string) {
|
func (c *context) disableVertexAttribArray(p program, index int) {
|
||||||
_ = mainthread.Run(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
gl.DisableVertexAttribArray(uint32(index))
|
||||||
gl.DisableVertexAttribArray(uint32(l))
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -293,7 +293,7 @@ func (c *context) deleteShader(s shader) {
|
|||||||
gl.Call("deleteShader", js.Value(s))
|
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()
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
v := gl.Call("createProgram")
|
v := gl.Call("createProgram")
|
||||||
@ -304,6 +304,11 @@ func (c *context) newProgram(shaders []shader) (program, error) {
|
|||||||
for _, shader := range shaders {
|
for _, shader := range shaders {
|
||||||
gl.Call("attachShader", v, js.Value(shader))
|
gl.Call("attachShader", v, js.Value(shader))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i, name := range attributes {
|
||||||
|
gl.Call("bindAttribLocation", v, i, name)
|
||||||
|
}
|
||||||
|
|
||||||
gl.Call("linkProgram", v)
|
gl.Call("linkProgram", v)
|
||||||
if !gl.Call("getProgramParameter", v, linkStatus).Bool() {
|
if !gl.Call("getProgramParameter", v, linkStatus).Bool() {
|
||||||
return program{}, errors.New("opengl: program error")
|
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()
|
c.ensureGL()
|
||||||
gl := c.gl
|
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()
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
gl.Call("enableVertexAttribArray", index)
|
||||||
gl.Call("vertexAttribPointer", int(l), size, int(dataType), false, stride, offset)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) enableVertexAttribArray(p program, location string) {
|
func (c *context) disableVertexAttribArray(p program, index int) {
|
||||||
c.ensureGL()
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
gl.Call("disableVertexAttribArray", index)
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) newArrayBuffer(size int) buffer {
|
func (c *context) newArrayBuffer(size int) buffer {
|
||||||
|
@ -243,7 +243,7 @@ func (c *context) deleteShader(s shader) {
|
|||||||
gl.DeleteShader(mgl.Shader(s))
|
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
|
gl := c.gl
|
||||||
p := gl.CreateProgram()
|
p := gl.CreateProgram()
|
||||||
if p.Value == 0 {
|
if p.Value == 0 {
|
||||||
@ -253,6 +253,11 @@ func (c *context) newProgram(shaders []shader) (program, error) {
|
|||||||
for _, shader := range shaders {
|
for _, shader := range shaders {
|
||||||
gl.AttachShader(p, mgl.Shader(shader))
|
gl.AttachShader(p, mgl.Shader(shader))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i, name := range attributes {
|
||||||
|
gl.BindAttribLocation(p, mgl.Attrib{uint(i)}, name)
|
||||||
|
}
|
||||||
|
|
||||||
gl.LinkProgram(p)
|
gl.LinkProgram(p)
|
||||||
v := gl.GetProgrami(p, mgl.LINK_STATUS)
|
v := gl.GetProgrami(p, mgl.LINK_STATUS)
|
||||||
if v == mgl.FALSE {
|
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
|
gl := c.gl
|
||||||
a := attribLocation(gl.GetAttribLocation(mgl.Program(p), location))
|
gl.VertexAttribPointer(mgl.Attrib{uint(index)}, size, mgl.Enum(dataType), false, stride, offset)
|
||||||
if a.Value == ^uint(0) {
|
|
||||||
panic("invalid attrib location: " + location)
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
gl := c.gl
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
gl.EnableVertexAttribArray(mgl.Attrib{uint(index)})
|
||||||
gl.VertexAttribPointer(mgl.Attrib(l), size, mgl.Enum(dataType), false, stride, offset)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) enableVertexAttribArray(p program, location string) {
|
func (c *context) disableVertexAttribArray(p program, index int) {
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
gl.DisableVertexAttribArray(mgl.Attrib{uint(index)})
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) newArrayBuffer(size int) buffer {
|
func (c *context) newArrayBuffer(size int) buffer {
|
||||||
|
@ -18,13 +18,11 @@ package opengl
|
|||||||
|
|
||||||
type locationCache struct {
|
type locationCache struct {
|
||||||
uniformLocationCache map[programID]map[string]uniformLocation
|
uniformLocationCache map[programID]map[string]uniformLocation
|
||||||
attribLocationCache map[programID]map[string]attribLocation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLocationCache() *locationCache {
|
func newLocationCache() *locationCache {
|
||||||
return &locationCache{
|
return &locationCache{
|
||||||
uniformLocationCache: map[programID]map[string]uniformLocation{},
|
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
|
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
|
|
||||||
}
|
|
||||||
|
@ -38,6 +38,14 @@ type arrayBufferLayout struct {
|
|||||||
total int
|
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.
|
// totalBytes returns the size in bytes for one element of the array buffer.
|
||||||
func (a *arrayBufferLayout) totalBytes() int {
|
func (a *arrayBufferLayout) totalBytes() int {
|
||||||
if a.total != 0 {
|
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.
|
// enable binds the array buffer the given program to use the array buffer.
|
||||||
func (a *arrayBufferLayout) enable(context *context, program program) {
|
func (a *arrayBufferLayout) enable(context *context, program program) {
|
||||||
for _, p := range a.parts {
|
for i := range a.parts {
|
||||||
context.enableVertexAttribArray(program, p.name)
|
context.enableVertexAttribArray(program, i)
|
||||||
}
|
}
|
||||||
total := a.totalBytes()
|
total := a.totalBytes()
|
||||||
offset := 0
|
offset := 0
|
||||||
for _, p := range a.parts {
|
for i, p := range a.parts {
|
||||||
context.vertexAttribPointer(program, p.name, p.num, float, total, offset)
|
context.vertexAttribPointer(program, i, p.num, float, total, offset)
|
||||||
offset += float.SizeInBytes() * p.num
|
offset += float.SizeInBytes() * p.num
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,8 +80,8 @@ func (a *arrayBufferLayout) enable(context *context, program program) {
|
|||||||
// disable stops using the array buffer.
|
// disable stops using the array buffer.
|
||||||
func (a *arrayBufferLayout) disable(context *context, program program) {
|
func (a *arrayBufferLayout) disable(context *context, program program) {
|
||||||
// TODO: Disabling should be done in reversed order?
|
// TODO: Disabling should be done in reversed order?
|
||||||
for _, p := range a.parts {
|
for i := range a.parts {
|
||||||
context.disableVertexAttribArray(program, p.name)
|
context.disableVertexAttribArray(program, i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,10 +218,12 @@ func (s *openGLState) reset(context *context) error {
|
|||||||
program, err := context.newProgram([]shader{
|
program, err := context.newProgram([]shader{
|
||||||
shaderVertexModelviewNative,
|
shaderVertexModelviewNative,
|
||||||
shaderFragmentColorMatrixNative,
|
shaderFragmentColorMatrixNative,
|
||||||
})
|
}, theArrayBufferLayout.names())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.programs[programKey{
|
s.programs[programKey{
|
||||||
filter: f,
|
filter: f,
|
||||||
address: a,
|
address: a,
|
||||||
|
@ -234,9 +234,6 @@ void main(void) {
|
|||||||
highp vec2 p0 = pos - texel_size / 2.0 / scale;
|
highp vec2 p0 = pos - texel_size / 2.0 / scale;
|
||||||
highp vec2 p1 = 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);
|
p1 = adjustTexel(p0, p1);
|
||||||
|
|
||||||
vec4 c0 = texture2D(texture, p0);
|
vec4 c0 = texture2D(texture, p0);
|
||||||
|
Loading…
Reference in New Issue
Block a user