mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
graphics: Improve speed by merging vertices arrays into one
This commit is contained in:
parent
a744285b51
commit
333b0956ff
@ -32,11 +32,25 @@ type command interface {
|
|||||||
|
|
||||||
type commandQueue struct {
|
type commandQueue struct {
|
||||||
commands []command
|
commands []command
|
||||||
|
vertices []float32
|
||||||
|
verticesNum int
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
var theCommandQueue = &commandQueue{
|
var theCommandQueue = &commandQueue{
|
||||||
commands: []command{},
|
commands: []command{},
|
||||||
|
vertices: []float32{},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *commandQueue) AppendVertices(vertices []float32) {
|
||||||
|
q.m.Lock()
|
||||||
|
defer q.m.Unlock()
|
||||||
|
if len(q.vertices) < q.verticesNum+len(vertices) {
|
||||||
|
n := q.verticesNum + len(vertices) - len(q.vertices)
|
||||||
|
q.vertices = append(q.vertices, make([]float32, n)...)
|
||||||
|
}
|
||||||
|
copy(q.vertices[q.verticesNum:q.verticesNum+len(vertices)], vertices)
|
||||||
|
q.verticesNum += len(vertices)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *commandQueue) Enqueue(command command) {
|
func (q *commandQueue) Enqueue(command command) {
|
||||||
@ -46,7 +60,7 @@ func (q *commandQueue) Enqueue(command command) {
|
|||||||
if c1, ok := q.commands[len(q.commands)-1].(*drawImageCommand); ok {
|
if c1, ok := q.commands[len(q.commands)-1].(*drawImageCommand); ok {
|
||||||
if c2, ok := command.(*drawImageCommand); ok {
|
if c2, ok := command.(*drawImageCommand); ok {
|
||||||
if c1.isMergeable(c2) {
|
if c1.isMergeable(c2) {
|
||||||
c1.vertices = append(c1.vertices, c2.vertices...)
|
c1.verticesNum += c2.verticesNum
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,27 +105,21 @@ func (q *commandQueue) Flush(context *opengl.Context) error {
|
|||||||
defer q.m.Unlock()
|
defer q.m.Unlock()
|
||||||
// glViewport must be called at least at every frame on iOS.
|
// glViewport must be called at least at every frame on iOS.
|
||||||
context.ResetViewportSize()
|
context.ResetViewportSize()
|
||||||
for _, g := range q.commandGroups() {
|
|
||||||
n := 0
|
n := 0
|
||||||
|
lastN := 0
|
||||||
|
for _, g := range q.commandGroups() {
|
||||||
for _, c := range g {
|
for _, c := range g {
|
||||||
switch c := c.(type) {
|
switch c := c.(type) {
|
||||||
case *drawImageCommand:
|
case *drawImageCommand:
|
||||||
n += len(c.vertices)
|
n += c.verticesNum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vertices := make([]float32, 0, n)
|
if 0 < n-lastN {
|
||||||
for _, c := range g {
|
context.BufferSubData(opengl.ArrayBuffer, q.vertices[lastN:n])
|
||||||
switch c := c.(type) {
|
|
||||||
case *drawImageCommand:
|
|
||||||
vertices = append(vertices, c.vertices...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if 0 < len(vertices) {
|
|
||||||
context.BufferSubData(opengl.ArrayBuffer, vertices)
|
|
||||||
}
|
}
|
||||||
// NOTE: WebGL doesn't seem to have Check gl.MAX_ELEMENTS_VERTICES or gl.MAX_ELEMENTS_INDICES so far.
|
// 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.
|
// Let's use them to compare to len(quads) in the future.
|
||||||
if maxQuads < len(vertices)*opengl.Float.SizeInBytes()/QuadVertexSizeInBytes() {
|
if maxQuads < (n-lastN)*opengl.Float.SizeInBytes()/QuadVertexSizeInBytes() {
|
||||||
return fmt.Errorf("len(quads) must be equal to or less than %d", maxQuads)
|
return fmt.Errorf("len(quads) must be equal to or less than %d", maxQuads)
|
||||||
}
|
}
|
||||||
numc := len(g)
|
numc := len(g)
|
||||||
@ -121,7 +129,7 @@ func (q *commandQueue) Flush(context *opengl.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if c, ok := c.(*drawImageCommand); ok {
|
if c, ok := c.(*drawImageCommand); ok {
|
||||||
n := len(c.vertices) * opengl.Float.SizeInBytes() / QuadVertexSizeInBytes()
|
n := c.verticesNum * opengl.Float.SizeInBytes() / QuadVertexSizeInBytes()
|
||||||
indexOffsetInBytes += 6 * n * 2
|
indexOffsetInBytes += 6 * n * 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,8 +137,10 @@ func (q *commandQueue) Flush(context *opengl.Context) error {
|
|||||||
// Call glFlush to prevent black flicking (especially on Android (#226) and iOS).
|
// Call glFlush to prevent black flicking (especially on Android (#226) and iOS).
|
||||||
context.Flush()
|
context.Flush()
|
||||||
}
|
}
|
||||||
|
lastN = n
|
||||||
}
|
}
|
||||||
q.commands = []command{}
|
q.commands = []command{}
|
||||||
|
q.verticesNum = 0
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +173,7 @@ func (c *fillCommand) Exec(context *opengl.Context, indexOffsetInBytes int) erro
|
|||||||
type drawImageCommand struct {
|
type drawImageCommand struct {
|
||||||
dst *Image
|
dst *Image
|
||||||
src *Image
|
src *Image
|
||||||
vertices []float32
|
verticesNum int
|
||||||
color affine.ColorM
|
color affine.ColorM
|
||||||
mode opengl.CompositeMode
|
mode opengl.CompositeMode
|
||||||
}
|
}
|
||||||
@ -209,8 +219,9 @@ func (c *drawImageCommand) split(quadsNum int) [2]*drawImageCommand {
|
|||||||
c1 := *c
|
c1 := *c
|
||||||
c2 := *c
|
c2 := *c
|
||||||
s := opengl.Float.SizeInBytes()
|
s := opengl.Float.SizeInBytes()
|
||||||
c1.vertices = c.vertices[:quadsNum*QuadVertexSizeInBytes()/s]
|
n := quadsNum * QuadVertexSizeInBytes() / s
|
||||||
c2.vertices = c.vertices[quadsNum*QuadVertexSizeInBytes()/s:]
|
c1.verticesNum = n
|
||||||
|
c2.verticesNum -= n
|
||||||
return [2]*drawImageCommand{&c1, &c2}
|
return [2]*drawImageCommand{&c1, &c2}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +242,7 @@ func (c *drawImageCommand) isMergeable(other *drawImageCommand) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *drawImageCommand) quadsNum() int {
|
func (c *drawImageCommand) quadsNum() int {
|
||||||
return len(c.vertices) * opengl.Float.SizeInBytes() / QuadVertexSizeInBytes()
|
return c.verticesNum * opengl.Float.SizeInBytes() / QuadVertexSizeInBytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
type replacePixelsCommand struct {
|
type replacePixelsCommand struct {
|
||||||
|
@ -147,10 +147,11 @@ func (i *Image) DrawImage(src *Image, vertices []float32, clr affine.ColorM, mod
|
|||||||
c := &drawImageCommand{
|
c := &drawImageCommand{
|
||||||
dst: i,
|
dst: i,
|
||||||
src: src,
|
src: src,
|
||||||
vertices: vertices,
|
verticesNum: len(vertices),
|
||||||
color: clr,
|
color: clr,
|
||||||
mode: mode,
|
mode: mode,
|
||||||
}
|
}
|
||||||
|
theCommandQueue.AppendVertices(vertices)
|
||||||
theCommandQueue.Enqueue(c)
|
theCommandQueue.Enqueue(c)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user