mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
internal/ui: re-enable skipping to render the final screen when possible
With Metal, nextDrawable could return immediately when a command buffer is empty. To avoid high CPU usage, this change adds a slight sleep in this case. With DirectX, Present waits for a while even though nothing is updated, then that's fine. Updates #2341 Updates #2342 Updates #2520
This commit is contained in:
parent
edb952c9e7
commit
7418576c16
@ -19,6 +19,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/cocoa"
|
"github.com/hajimehoshi/ebiten/v2/internal/cocoa"
|
||||||
@ -58,6 +59,8 @@ type Graphics struct {
|
|||||||
maxImageSize int
|
maxImageSize int
|
||||||
tmpTextures []mtl.Texture
|
tmpTextures []mtl.Texture
|
||||||
|
|
||||||
|
lastFlush time.Time
|
||||||
|
|
||||||
pool cocoa.NSAutoreleasePool
|
pool cocoa.NSAutoreleasePool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,14 +214,26 @@ func (g *Graphics) flushIfNeeded(present bool) {
|
|||||||
if g.cb == (mtl.CommandBuffer{}) && !present {
|
if g.cb == (mtl.CommandBuffer{}) && !present {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
defer func() {
|
||||||
|
g.lastFlush = now
|
||||||
|
}()
|
||||||
|
|
||||||
g.flushRenderCommandEncoderIfNeeded()
|
g.flushRenderCommandEncoderIfNeeded()
|
||||||
|
|
||||||
if present {
|
if present {
|
||||||
// This check is necessary when skipping to render the screen (SetScreenClearedEveryFrame(false)).
|
// This check is necessary when skipping to render the screen (SetScreenClearedEveryFrame(false)).
|
||||||
if g.screenDrawable == (ca.MetalDrawable{}) {
|
if g.screenDrawable == (ca.MetalDrawable{}) {
|
||||||
// nextDrawable can return immediately when the command buffer is empty.
|
if g.cb != (mtl.CommandBuffer{}) {
|
||||||
// TODO: Can we wait for a while to get the next drawable? (#2520)
|
g.screenDrawable = g.view.nextDrawable()
|
||||||
g.screenDrawable = g.view.nextDrawable()
|
} else {
|
||||||
|
if delta := time.Second/60 - now.Sub(g.lastFlush); delta > 0 {
|
||||||
|
// nextDrawable can return immediately when the command buffer is empty.
|
||||||
|
// To avoid busy, sleep instead (#2520).
|
||||||
|
time.Sleep(delta)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if g.screenDrawable != (ca.MetalDrawable{}) {
|
if g.screenDrawable != (ca.MetalDrawable{}) {
|
||||||
g.cb.PresentDrawable(g.screenDrawable)
|
g.cb.PresentDrawable(g.screenDrawable)
|
||||||
|
@ -198,11 +198,7 @@ func (c *context) drawGame(graphicsDriver graphicsdriver.Graphics, forceDraw boo
|
|||||||
c.skipCount = 0
|
c.skipCount = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
skippable := c.skipCount >= maxSkipCount
|
if c.skipCount < maxSkipCount {
|
||||||
|
|
||||||
// TODO: Metal (and maybe DirectX) cannot vsync without swapping the buffer by rendering the screen framebuffer (#2520).
|
|
||||||
// Implement this skipping appropriately for Metal and DirectX.
|
|
||||||
if !skippable || !graphicsDriver.IsGL() {
|
|
||||||
if graphicsDriver.NeedsClearingScreen() {
|
if graphicsDriver.NeedsClearingScreen() {
|
||||||
// This clear is needed for fullscreen mode or some mobile platforms (#622).
|
// This clear is needed for fullscreen mode or some mobile platforms (#622).
|
||||||
c.screen.clear()
|
c.screen.clear()
|
||||||
|
Loading…
Reference in New Issue
Block a user