mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
graphics: Optimize commands: call glBufferSubData as less times as possible
This commit is contained in:
parent
208b27d5de
commit
3e912ce7f8
@ -15,6 +15,8 @@
|
||||
package graphics
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"image/color"
|
||||
"math"
|
||||
|
||||
@ -26,7 +28,8 @@ type command interface {
|
||||
}
|
||||
|
||||
type commandQueue struct {
|
||||
commands []command
|
||||
commands []command
|
||||
indexOffsetInBytes int
|
||||
}
|
||||
|
||||
var theCommandQueue = &commandQueue{
|
||||
@ -38,7 +41,18 @@ func (q *commandQueue) Enqueue(command command) {
|
||||
}
|
||||
|
||||
func (q *commandQueue) Flush(context *opengl.Context) error {
|
||||
// TODO: Do optimizing before executing
|
||||
q.indexOffsetInBytes = 0
|
||||
vertices := []int16{}
|
||||
for _, c := range q.commands {
|
||||
switch c := c.(type) {
|
||||
case *drawImageCommand:
|
||||
vertices = append(vertices, c.vertices...)
|
||||
}
|
||||
}
|
||||
// TODO: Check if len(vertices) is too big
|
||||
if 0 < len(vertices) {
|
||||
context.BufferSubData(context.ArrayBuffer, vertices)
|
||||
}
|
||||
for _, c := range q.commands {
|
||||
if err := c.Exec(context); err != nil {
|
||||
return err
|
||||
@ -79,8 +93,34 @@ func (c *drawImageCommand) Exec(context *opengl.Context) error {
|
||||
if err := c.dst.setAsViewport(context); err != nil {
|
||||
return err
|
||||
}
|
||||
p := c.dst.projectionMatrix()
|
||||
return drawTexture(context, c.src.native, p, c.vertices, c.geo, c.color, c.mode)
|
||||
context.BlendFunc(c.mode)
|
||||
|
||||
// NOTE: WebGL doesn't seem to have Check gl.MAX_ELEMENTS_VERTICES or gl.MAX_ELEMENTS_INDICES so far.
|
||||
// Let's use them to compare to len(quads) in the future.
|
||||
n := len(c.vertices) / 16
|
||||
if n == 0 {
|
||||
return nil
|
||||
}
|
||||
if MaxQuads < n/16 {
|
||||
return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", MaxQuads))
|
||||
}
|
||||
|
||||
p := programContext{
|
||||
state: &theOpenGLState,
|
||||
program: theOpenGLState.programTexture,
|
||||
context: context,
|
||||
projectionMatrix: glMatrix(c.dst.projectionMatrix()),
|
||||
texture: c.src.native,
|
||||
geoM: c.geo,
|
||||
colorM: c.color,
|
||||
}
|
||||
p.begin()
|
||||
defer p.end()
|
||||
// TODO: We should call glBindBuffer here?
|
||||
// The buffer is already bound at begin() but it is counterintuitive.
|
||||
context.DrawElements(context.Triangles, 6*n, theCommandQueue.indexOffsetInBytes)
|
||||
theCommandQueue.indexOffsetInBytes += 6 * n * 2
|
||||
return nil
|
||||
}
|
||||
|
||||
type replacePixelsCommand struct {
|
||||
|
@ -14,13 +14,6 @@
|
||||
|
||||
package graphics
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
||||
)
|
||||
|
||||
func glMatrix(m *[4][4]float64) []float32 {
|
||||
return []float32{
|
||||
float32(m[0][0]), float32(m[1][0]), float32(m[2][0]), float32(m[3][0]),
|
||||
@ -33,35 +26,3 @@ func glMatrix(m *[4][4]float64) []float32 {
|
||||
type Matrix interface {
|
||||
Element(i, j int) float64
|
||||
}
|
||||
|
||||
func drawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4][4]float64, vertices []int16, geo Matrix, color Matrix, mode opengl.CompositeMode) error {
|
||||
c.BlendFunc(mode)
|
||||
|
||||
// NOTE: WebGL doesn't seem to have Check gl.MAX_ELEMENTS_VERTICES or gl.MAX_ELEMENTS_INDICES so far.
|
||||
// Let's use them to compare to len(quads) in the future.
|
||||
n := len(vertices) / 16
|
||||
if n == 0 {
|
||||
return nil
|
||||
}
|
||||
if MaxQuads < n/16 {
|
||||
return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", MaxQuads))
|
||||
}
|
||||
|
||||
p := programContext{
|
||||
state: &theOpenGLState,
|
||||
program: theOpenGLState.programTexture,
|
||||
context: c,
|
||||
projectionMatrix: glMatrix(projectionMatrix),
|
||||
texture: texture,
|
||||
geoM: geo,
|
||||
colorM: color,
|
||||
}
|
||||
p.begin()
|
||||
defer p.end()
|
||||
// TODO: We should call glBindBuffer here?
|
||||
// The buffer is already bound at begin() but it is counterintuitive.
|
||||
c.BufferSubData(c.ArrayBuffer, vertices)
|
||||
c.DrawElements(c.Triangles, 6*n)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -438,9 +438,9 @@ func (c *Context) DeleteBuffer(b Buffer) {
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Context) DrawElements(mode Mode, len int) {
|
||||
func (c *Context) DrawElements(mode Mode, len int, offsetInBytes int) {
|
||||
c.RunOnContextThread(func() error {
|
||||
gl.DrawElements(uint32(mode), int32(len), gl.UNSIGNED_SHORT, gl.PtrOffset(0))
|
||||
gl.DrawElements(uint32(mode), int32(len), gl.UNSIGNED_SHORT, gl.PtrOffset(offsetInBytes))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ func (c *Context) DeleteBuffer(b Buffer) {
|
||||
gl.DeleteBuffer(b.Object)
|
||||
}
|
||||
|
||||
func (c *Context) DrawElements(mode Mode, len int) {
|
||||
func (c *Context) DrawElements(mode Mode, len int, offsetInBytes int) {
|
||||
gl := c.gl
|
||||
gl.DrawElements(int(mode), len, gl.UNSIGNED_SHORT, 0)
|
||||
gl.DrawElements(int(mode), len, gl.UNSIGNED_SHORT, offsetInBytes)
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ func (c *Context) DeleteBuffer(b Buffer) {
|
||||
gl.DeleteBuffer(mgl.Buffer(b))
|
||||
}
|
||||
|
||||
func (c *Context) DrawElements(mode Mode, len int) {
|
||||
func (c *Context) DrawElements(mode Mode, len int, offsetInBytes int) {
|
||||
gl := c.gl
|
||||
gl.DrawElements(mgl.Enum(mode), len, mgl.UNSIGNED_SHORT, 0)
|
||||
gl.DrawElements(mgl.Enum(mode), len, mgl.UNSIGNED_SHORT, offsetInBytes)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user