From 03e3f0f5f7a5b8401bd2a6e7f09b98a41ed9a74c Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Thu, 31 May 2018 00:53:02 +0900 Subject: [PATCH] graphics: Call glBufferSubData for element array buffer every frame This is a preparation for more flexible drawing commands. --- internal/graphics/command.go | 19 ++++++++++- internal/graphics/program.go | 13 +------- internal/opengl/context_desktop.go | 16 ++++++--- internal/opengl/context_js.go | 14 +++++--- internal/opengl/context_mobile.go | 52 ++++++++++++++++-------------- 5 files changed, 67 insertions(+), 47 deletions(-) diff --git a/internal/graphics/command.go b/internal/graphics/command.go index 523cb9227..af3dfe94c 100644 --- a/internal/graphics/command.go +++ b/internal/graphics/command.go @@ -47,11 +47,27 @@ type commandQueue struct { // nvertices must <= len(vertices). // vertices is never shrunk since re-extending a vertices buffer is heavy. nvertices int + + indices []uint16 } // theCommandQueue is the command queue for the current process. var theCommandQueue = &commandQueue{} +func init() { + q := theCommandQueue + // Initialize indices for drawImageCommand. + q.indices = make([]uint16, 6*maxQuads) + for i := uint16(0); i < maxQuads; i++ { + q.indices[6*i+0] = 4*i + 0 + q.indices[6*i+1] = 4*i + 1 + q.indices[6*i+2] = 4*i + 2 + q.indices[6*i+3] = 4*i + 1 + q.indices[6*i+4] = 4*i + 2 + q.indices[6*i+5] = 4*i + 3 + } +} + // appendVertices appends vertices to the queue. func (q *commandQueue) appendVertices(vertices []float32) { if len(q.vertices) < q.nvertices+len(vertices) { @@ -140,7 +156,8 @@ func (q *commandQueue) Flush() error { // Note that the vertices passed to BufferSubData is not under GC management // in opengl package due to unsafe-way. // See BufferSubData in context_mobile.go. - opengl.GetContext().BufferSubData(opengl.ArrayBuffer, q.vertices[lastN:n]) + opengl.GetContext().ElementArrayBufferSubData(q.indices) + opengl.GetContext().ArrayBufferSubData(q.vertices[lastN:n]) } // NOTE: WebGL doesn't seem to have gl.MAX_ELEMENTS_VERTICES or // gl.MAX_ELEMENTS_INDICES so far. diff --git a/internal/graphics/program.go b/internal/graphics/program.go index 8eb941dba..7e6e73439 100644 --- a/internal/graphics/program.go +++ b/internal/graphics/program.go @@ -120,8 +120,6 @@ type openGLState struct { lastColorMatrixTranslation []float32 lastSourceWidth int lastSourceHeight int - - indices []uint16 } var ( @@ -229,19 +227,10 @@ func (s *openGLState) reset() error { s.arrayBuffer = theArrayBufferLayout.newArrayBuffer() - s.indices = make([]uint16, 6*maxQuads) - for i := uint16(0); i < maxQuads; i++ { - s.indices[6*i+0] = 4*i + 0 - s.indices[6*i+1] = 4*i + 1 - s.indices[6*i+2] = 4*i + 2 - s.indices[6*i+3] = 4*i + 1 - s.indices[6*i+4] = 4*i + 2 - s.indices[6*i+5] = 4*i + 3 - } // Note that the indices passed to NewElementArrayBuffer is not under GC management // in opengl package due to unsafe-way. // See NewElementArrayBuffer in context_mobile.go. - s.elementArrayBuffer = opengl.GetContext().NewElementArrayBuffer(s.indices) + s.elementArrayBuffer = opengl.GetContext().NewElementArrayBuffer(indicesNum * 2) return nil } diff --git a/internal/opengl/context_desktop.go b/internal/opengl/context_desktop.go index 3a84aadce..065a77003 100644 --- a/internal/opengl/context_desktop.go +++ b/internal/opengl/context_desktop.go @@ -58,7 +58,6 @@ func init() { ArrayBuffer = gl.ARRAY_BUFFER ElementArrayBuffer = gl.ELEMENT_ARRAY_BUFFER DynamicDraw = gl.DYNAMIC_DRAW - StaticDraw = gl.STATIC_DRAW Triangles = gl.TRIANGLES Lines = gl.LINES Short = gl.SHORT @@ -452,13 +451,13 @@ func (c *Context) NewArrayBuffer(size int) Buffer { return buffer } -func (c *Context) NewElementArrayBuffer(indices []uint16) Buffer { +func (c *Context) NewElementArrayBuffer(size int) Buffer { var buffer Buffer _ = c.runOnContextThread(func() error { var b uint32 gl.GenBuffers(1, &b) gl.BindBuffer(uint32(ElementArrayBuffer), b) - gl.BufferData(uint32(ElementArrayBuffer), 2*len(indices), gl.Ptr(indices), uint32(StaticDraw)) + gl.BufferData(uint32(ElementArrayBuffer), size, nil, uint32(DynamicDraw)) buffer = Buffer(b) return nil }) @@ -472,9 +471,16 @@ func (c *Context) BindBuffer(bufferType BufferType, b Buffer) { }) } -func (c *Context) BufferSubData(bufferType BufferType, data []float32) { +func (c *Context) ArrayBufferSubData(data []float32) { _ = c.runOnContextThread(func() error { - gl.BufferSubData(uint32(bufferType), 0, len(data)*4, gl.Ptr(data)) + gl.BufferSubData(uint32(ArrayBuffer), 0, len(data)*4, gl.Ptr(data)) + return nil + }) +} + +func (c *Context) ElementArrayBufferSubData(data []uint16) { + _ = c.runOnContextThread(func() error { + gl.BufferSubData(uint32(ElementArrayBuffer), 0, len(data)*2, gl.Ptr(data)) return nil }) } diff --git a/internal/opengl/context_js.go b/internal/opengl/context_js.go index c8bc7c416..20feeaab7 100644 --- a/internal/opengl/context_js.go +++ b/internal/opengl/context_js.go @@ -55,7 +55,6 @@ func init() { ArrayBuffer = BufferType(c.Get("ARRAY_BUFFER").Int()) ElementArrayBuffer = BufferType(c.Get("ELEMENT_ARRAY_BUFFER").Int()) DynamicDraw = BufferUsage(c.Get("DYNAMIC_DRAW").Int()) - StaticDraw = BufferUsage(c.Get("STATIC_DRAW").Int()) Triangles = Mode(c.Get("TRIANGLES").Int()) Lines = Mode(c.Get("LINES").Int()) Short = DataType(c.Get("SHORT").Int()) @@ -358,11 +357,11 @@ func (c *Context) NewArrayBuffer(size int) Buffer { return b } -func (c *Context) NewElementArrayBuffer(indices []uint16) Buffer { +func (c *Context) NewElementArrayBuffer(size int) Buffer { gl := c.gl b := gl.Call("createBuffer") gl.Call("bindBuffer", int(ElementArrayBuffer), b) - gl.Call("bufferData", int(ElementArrayBuffer), indices, int(StaticDraw)) + gl.Call("bufferData", int(ElementArrayBuffer), size, int(DynamicDraw)) return b } @@ -371,9 +370,14 @@ func (c *Context) BindBuffer(bufferType BufferType, b Buffer) { gl.Call("bindBuffer", int(bufferType), b) } -func (c *Context) BufferSubData(bufferType BufferType, data []float32) { +func (c *Context) ArrayBufferSubData(data []float32) { gl := c.gl - gl.Call("bufferSubData", int(bufferType), 0, data) + gl.Call("bufferSubData", int(ArrayBuffer), 0, data) +} + +func (c *Context) ElementArrayBufferSubData(data []uint16) { + gl := c.gl + gl.Call("bufferSubData", int(ElementArrayBuffer), 0, data) } func (c *Context) DeleteBuffer(b Buffer) { diff --git a/internal/opengl/context_mobile.go b/internal/opengl/context_mobile.go index afa8209a7..3d6c18be6 100644 --- a/internal/opengl/context_mobile.go +++ b/internal/opengl/context_mobile.go @@ -57,7 +57,6 @@ func init() { ArrayBuffer = mgl.ARRAY_BUFFER ElementArrayBuffer = mgl.ELEMENT_ARRAY_BUFFER DynamicDraw = mgl.DYNAMIC_DRAW - StaticDraw = mgl.STATIC_DRAW Triangles = mgl.TRIANGLES Lines = mgl.LINES Short = mgl.SHORT @@ -353,6 +352,27 @@ func (c *Context) DisableVertexAttribArray(p Program, location string) { gl.DisableVertexAttribArray(mgl.Attrib(l)) } +func (c *Context) NewArrayBuffer(size int) Buffer { + gl := c.gl + b := gl.CreateBuffer() + gl.BindBuffer(mgl.Enum(ArrayBuffer), b) + gl.BufferInit(mgl.Enum(ArrayBuffer), size, mgl.Enum(DynamicDraw)) + return Buffer(b) +} + +func (c *Context) NewElementArrayBuffer(size int) Buffer { + gl := c.gl + b := gl.CreateBuffer() + gl.BindBuffer(mgl.Enum(ElementArrayBuffer), b) + gl.BufferInit(mgl.Enum(ElementArrayBuffer), size, mgl.Enum(DynamicDraw)) + return Buffer(b) +} + +func (c *Context) BindBuffer(bufferType BufferType, b Buffer) { + gl := c.gl + gl.BindBuffer(mgl.Enum(bufferType), mgl.Buffer(b)) +} + func uint16ToBytes(v []uint16) []byte { u16h := (*reflect.SliceHeader)(unsafe.Pointer(&v)) @@ -364,27 +384,6 @@ func uint16ToBytes(v []uint16) []byte { return b } -func (c *Context) NewArrayBuffer(size int) Buffer { - gl := c.gl - b := gl.CreateBuffer() - gl.BindBuffer(mgl.Enum(ArrayBuffer), b) - gl.BufferInit(mgl.Enum(ArrayBuffer), size, mgl.Enum(DynamicDraw)) - return Buffer(b) -} - -func (c *Context) NewElementArrayBuffer(indices []uint16) Buffer { - gl := c.gl - b := gl.CreateBuffer() - gl.BindBuffer(mgl.Enum(ElementArrayBuffer), b) - gl.BufferData(mgl.Enum(ElementArrayBuffer), uint16ToBytes(indices), mgl.Enum(StaticDraw)) - return Buffer(b) -} - -func (c *Context) BindBuffer(bufferType BufferType, b Buffer) { - gl := c.gl - gl.BindBuffer(mgl.Enum(bufferType), mgl.Buffer(b)) -} - func float32ToBytes(v []float32) []byte { f32h := (*reflect.SliceHeader)(unsafe.Pointer(&v)) @@ -396,9 +395,14 @@ func float32ToBytes(v []float32) []byte { return b } -func (c *Context) BufferSubData(bufferType BufferType, data []float32) { +func (c *Context) ArrayBufferSubData(data []float32) { gl := c.gl - gl.BufferSubData(mgl.Enum(bufferType), 0, float32ToBytes(data)) + gl.BufferSubData(mgl.Enum(ArrayBuffer), 0, float32ToBytes(data)) +} + +func (c *Context) ElementArrayBufferSubData(data []uint16) { + gl := c.gl + gl.BufferSubData(mgl.Enum(ElementArrayBuffer), 0, uint16ToBytes(data)) } func (c *Context) DeleteBuffer(b Buffer) {