mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-27 03:02:49 +01:00
buffered: Do not delay commands if possible
Delaying commands causes memory allocations, which can be heavy especially on browsers. This avoids to use 'defer' for performance.
This commit is contained in:
parent
3291ec51bb
commit
3cf867035d
@ -19,40 +19,26 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
delayedCommandsFlushable bool
|
needsToDelayCommands = true
|
||||||
|
|
||||||
// delayedCommands represents a queue for image operations that are ordered before the game starts
|
// delayedCommands represents a queue for image operations that are ordered before the game starts
|
||||||
// (BeginFrame). Before the game starts, the package shareable doesn't determine the minimum/maximum texture
|
// (BeginFrame). Before the game starts, the package shareable doesn't determine the minimum/maximum texture
|
||||||
// sizes (#879).
|
// sizes (#879).
|
||||||
//
|
|
||||||
// TODO: Flush the commands only when necessary (#921).
|
|
||||||
delayedCommands []func()
|
delayedCommands []func()
|
||||||
delayedCommandsM sync.Mutex
|
delayedCommandsM sync.Mutex
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeDelayedCommandFlushable() {
|
func flushDelayedCommands() {
|
||||||
delayedCommandsM.Lock()
|
|
||||||
delayedCommandsFlushable = true
|
|
||||||
delayedCommandsM.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func enqueueDelayedCommand(f func()) {
|
|
||||||
delayedCommandsM.Lock()
|
|
||||||
delayedCommands = append(delayedCommands, f)
|
|
||||||
delayedCommandsM.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func flushDelayedCommands() bool {
|
|
||||||
delayedCommandsM.Lock()
|
delayedCommandsM.Lock()
|
||||||
defer delayedCommandsM.Unlock()
|
defer delayedCommandsM.Unlock()
|
||||||
|
|
||||||
if !delayedCommandsFlushable {
|
if !needsToDelayCommands {
|
||||||
return false
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range delayedCommands {
|
for _, c := range delayedCommands {
|
||||||
c()
|
c()
|
||||||
}
|
}
|
||||||
delayedCommands = delayedCommands[:0]
|
delayedCommands = delayedCommands[:0]
|
||||||
return true
|
needsToDelayCommands = false
|
||||||
}
|
}
|
||||||
|
@ -30,77 +30,130 @@ func BeginFrame() error {
|
|||||||
if err := shareable.BeginFrame(); err != nil {
|
if err := shareable.BeginFrame(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
makeDelayedCommandFlushable()
|
flushDelayedCommands()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func EndFrame() error {
|
func EndFrame() error {
|
||||||
if !flushDelayedCommands() {
|
|
||||||
panic("buffered: the command queue must be available at EndFrame")
|
|
||||||
}
|
|
||||||
return shareable.EndFrame()
|
return shareable.EndFrame()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewImage(width, height int, volatile bool) *Image {
|
func NewImage(width, height int, volatile bool) *Image {
|
||||||
i := &Image{}
|
i := &Image{}
|
||||||
enqueueDelayedCommand(func() {
|
delayedCommandsM.Lock()
|
||||||
i.img = shareable.NewImage(width, height, volatile)
|
if needsToDelayCommands {
|
||||||
})
|
delayedCommands = append(delayedCommands, func() {
|
||||||
|
i.img = shareable.NewImage(width, height, volatile)
|
||||||
|
})
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
|
|
||||||
|
i.img = shareable.NewImage(width, height, volatile)
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewScreenFramebufferImage(width, height int) *Image {
|
func NewScreenFramebufferImage(width, height int) *Image {
|
||||||
i := &Image{}
|
i := &Image{}
|
||||||
enqueueDelayedCommand(func() {
|
delayedCommandsM.Lock()
|
||||||
i.img = shareable.NewScreenFramebufferImage(width, height)
|
if needsToDelayCommands {
|
||||||
})
|
delayedCommands = append(delayedCommands, func() {
|
||||||
|
i.img = shareable.NewScreenFramebufferImage(width, height)
|
||||||
|
})
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
|
|
||||||
|
i.img = shareable.NewScreenFramebufferImage(width, height)
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) MarkDisposed() {
|
func (i *Image) MarkDisposed() {
|
||||||
enqueueDelayedCommand(func() {
|
delayedCommandsM.Lock()
|
||||||
i.img.MarkDisposed()
|
if needsToDelayCommands {
|
||||||
})
|
delayedCommands = append(delayedCommands, func() {
|
||||||
|
i.img.MarkDisposed()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) At(x, y int) (r, g, b, a byte) {
|
func (i *Image) At(x, y int) (r, g, b, a byte) {
|
||||||
if !flushDelayedCommands() {
|
delayedCommandsM.Lock()
|
||||||
|
defer delayedCommandsM.Unlock()
|
||||||
|
if needsToDelayCommands {
|
||||||
panic("buffered: the command queue is not available yet at At")
|
panic("buffered: the command queue is not available yet at At")
|
||||||
}
|
}
|
||||||
return i.img.At(x, y)
|
return i.img.At(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) Dump(name string) error {
|
func (i *Image) Dump(name string) error {
|
||||||
if !flushDelayedCommands() {
|
delayedCommandsM.Lock()
|
||||||
|
defer delayedCommandsM.Unlock()
|
||||||
|
if needsToDelayCommands {
|
||||||
panic("buffered: the command queue is not available yet at Dump")
|
panic("buffered: the command queue is not available yet at Dump")
|
||||||
}
|
}
|
||||||
return i.img.Dump(name)
|
return i.img.Dump(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) Fill(clr color.RGBA) {
|
func (i *Image) Fill(clr color.RGBA) {
|
||||||
enqueueDelayedCommand(func() {
|
delayedCommandsM.Lock()
|
||||||
i.img.Fill(clr)
|
if needsToDelayCommands {
|
||||||
})
|
delayedCommands = append(delayedCommands, func() {
|
||||||
|
i.img.Fill(clr)
|
||||||
|
})
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
|
|
||||||
|
i.img.Fill(clr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) ClearFramebuffer() {
|
func (i *Image) ClearFramebuffer() {
|
||||||
enqueueDelayedCommand(func() {
|
delayedCommandsM.Lock()
|
||||||
i.img.ClearFramebuffer()
|
if needsToDelayCommands {
|
||||||
})
|
delayedCommands = append(delayedCommands, func() {
|
||||||
|
i.img.ClearFramebuffer()
|
||||||
|
})
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
|
|
||||||
|
i.img.ClearFramebuffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) ReplacePixels(pix []byte) {
|
func (i *Image) ReplacePixels(pix []byte) {
|
||||||
enqueueDelayedCommand(func() {
|
delayedCommandsM.Lock()
|
||||||
i.img.ReplacePixels(pix)
|
if needsToDelayCommands {
|
||||||
})
|
delayedCommands = append(delayedCommands, func() {
|
||||||
|
i.img.ReplacePixels(pix)
|
||||||
|
})
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
|
|
||||||
|
i.img.ReplacePixels(pix)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address) {
|
func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address) {
|
||||||
if i == src {
|
if i == src {
|
||||||
panic("buffered: Image.DrawTriangles: src must be different from the receiver")
|
panic("buffered: Image.DrawTriangles: src must be different from the receiver")
|
||||||
}
|
}
|
||||||
enqueueDelayedCommand(func() {
|
|
||||||
i.img.DrawTriangles(src.img, vertices, indices, colorm, mode, filter, address)
|
delayedCommandsM.Lock()
|
||||||
})
|
if needsToDelayCommands {
|
||||||
|
delayedCommands = append(delayedCommands, func() {
|
||||||
|
i.img.DrawTriangles(src.img, vertices, indices, colorm, mode, filter, address)
|
||||||
|
})
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delayedCommandsM.Unlock()
|
||||||
|
|
||||||
|
i.img.DrawTriangles(src.img, vertices, indices, colorm, mode, filter, address)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user