mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 13:07: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
|
package graphics
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"image/color"
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
@ -27,6 +29,7 @@ type command interface {
|
|||||||
|
|
||||||
type commandQueue struct {
|
type commandQueue struct {
|
||||||
commands []command
|
commands []command
|
||||||
|
indexOffsetInBytes int
|
||||||
}
|
}
|
||||||
|
|
||||||
var theCommandQueue = &commandQueue{
|
var theCommandQueue = &commandQueue{
|
||||||
@ -38,7 +41,18 @@ func (q *commandQueue) Enqueue(command command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (q *commandQueue) Flush(context *opengl.Context) error {
|
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 {
|
for _, c := range q.commands {
|
||||||
if err := c.Exec(context); err != nil {
|
if err := c.Exec(context); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -79,8 +93,34 @@ func (c *drawImageCommand) Exec(context *opengl.Context) error {
|
|||||||
if err := c.dst.setAsViewport(context); err != nil {
|
if err := c.dst.setAsViewport(context); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p := c.dst.projectionMatrix()
|
context.BlendFunc(c.mode)
|
||||||
return drawTexture(context, c.src.native, p, c.vertices, c.geo, c.color, 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 {
|
type replacePixelsCommand struct {
|
||||||
|
@ -14,13 +14,6 @@
|
|||||||
|
|
||||||
package graphics
|
package graphics
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
|
||||||
)
|
|
||||||
|
|
||||||
func glMatrix(m *[4][4]float64) []float32 {
|
func glMatrix(m *[4][4]float64) []float32 {
|
||||||
return []float32{
|
return []float32{
|
||||||
float32(m[0][0]), float32(m[1][0]), float32(m[2][0]), float32(m[3][0]),
|
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 {
|
type Matrix interface {
|
||||||
Element(i, j int) float64
|
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 {
|
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
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -356,7 +356,7 @@ func (c *Context) DeleteBuffer(b Buffer) {
|
|||||||
gl.DeleteBuffer(b.Object)
|
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 := 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))
|
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 := 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