diff --git a/internal/graphics/vertex.go b/internal/graphics/vertex.go index 20a6fd3fd..f8d5c114b 100644 --- a/internal/graphics/vertex.go +++ b/internal/graphics/vertex.go @@ -48,7 +48,7 @@ const ( ) const ( - IndicesCount = (1 << 16) / 3 * 3 // Adjust num for triangles. + IndicesCount = (1 << 16) / 3 * 3 // Adjust num for triangles. TODO: Remove this (#2460). VertexFloatCount = 8 ) diff --git a/internal/graphicsdriver/opengl/program.go b/internal/graphicsdriver/opengl/program.go index 69f19adc2..55fe5ed31 100644 --- a/internal/graphicsdriver/opengl/program.go +++ b/internal/graphicsdriver/opengl/program.go @@ -113,22 +113,50 @@ type openGLState struct { // arrayBuffer is OpenGL's array buffer (vertices data). arrayBuffer buffer + arrayBufferSizeInBytes int + // elementArrayBuffer is OpenGL's element array buffer (indices data). elementArrayBuffer buffer + elementArrayBufferSizeInBytes int + lastProgram program lastUniforms map[string][]uint32 lastActiveTexture int } -func (s *openGLState) setVertices(context *context, vertices []float32, indices []uint16) { - if s.arrayBuffer == 0 { - s.arrayBuffer = context.newArrayBuffer(graphics.IndicesCount * graphics.VertexFloatCount * floatSizeInBytes) - context.ctx.BindBuffer(gl.ARRAY_BUFFER, uint32(s.arrayBuffer)) +func pow2(x int) int { + p2 := 1 + for p2 < x { + p2 *= 2 } - if s.elementArrayBuffer == 0 { - s.elementArrayBuffer = context.newElementArrayBuffer(graphics.IndicesCount * 2) - context.ctx.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, uint32(s.elementArrayBuffer)) + return p2 +} + +func (s *openGLState) setVertices(context *context, vertices []float32, indices []uint16) { + if size := len(vertices) * 4; s.arrayBufferSizeInBytes < size { + if s.arrayBuffer != 0 { + context.ctx.DeleteBuffer(uint32(s.arrayBuffer)) + } + + newSize := pow2(size) + // newArrayBuffer calls BindBuffer. + s.arrayBuffer = context.newArrayBuffer(newSize) + s.arrayBufferSizeInBytes = newSize + + // Reenable the array buffer layouter explicitly after resetting the array buffer. + theArrayBufferLayout.enable(context) + } + + if size := len(indices) * 2; s.elementArrayBufferSizeInBytes < size { + if s.elementArrayBuffer != 0 { + context.ctx.DeleteBuffer(uint32(s.elementArrayBuffer)) + } + + newSize := pow2(size) + // newElementArrayBuffer calls BindBuffer. + s.elementArrayBuffer = context.newElementArrayBuffer(newSize) + s.elementArrayBufferSizeInBytes = newSize } // Note that the vertices and the indices passed to BufferSubData is not under GC management in the gl package. @@ -184,9 +212,6 @@ func (g *Graphics) textureVariableName(idx int) string { func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textures [graphics.ShaderImageCount]textureVariable) error { if g.state.lastProgram != program { g.context.ctx.UseProgram(uint32(program)) - if g.state.lastProgram == 0 { - theArrayBufferLayout.enable(&g.context) - } g.state.lastProgram = program for k := range g.state.lastUniforms {