mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
internal/graphicsdriver/metal: Make FPS stable by 'presentsWithTransaction'
Closes #1196
This commit is contained in:
parent
ae0e30196b
commit
4573883b03
@ -147,6 +147,13 @@ func (ml MetalLayer) NextDrawable() (MetalDrawable, error) {
|
|||||||
return MetalDrawable{md}, nil
|
return MetalDrawable{md}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PresentsWithTransaction returns a Boolean value that determines whether the layer presents its content using a Core Animation transaction.
|
||||||
|
//
|
||||||
|
// Reference: https://developer.apple.com/documentation/quartzcore/cametallayer/1478157-presentswithtransaction
|
||||||
|
func (ml MetalLayer) PresentsWithTransaction() bool {
|
||||||
|
return C.MetalLayer_PresentsWithTransaction(ml.metalLayer) != 0
|
||||||
|
}
|
||||||
|
|
||||||
// SetFramebufferOnly sets a Boolean value that determines whether the layer’s textures are used only for rendering.
|
// SetFramebufferOnly sets a Boolean value that determines whether the layer’s textures are used only for rendering.
|
||||||
//
|
//
|
||||||
// https://developer.apple.com/documentation/quartzcore/cametallayer/1478168-framebufferonly
|
// https://developer.apple.com/documentation/quartzcore/cametallayer/1478168-framebufferonly
|
||||||
@ -175,3 +182,10 @@ func (md MetalDrawable) Drawable() unsafe.Pointer { return md.metalDrawable }
|
|||||||
func (md MetalDrawable) Texture() mtl.Texture {
|
func (md MetalDrawable) Texture() mtl.Texture {
|
||||||
return mtl.NewTexture(C.MetalDrawable_Texture(md.metalDrawable))
|
return mtl.NewTexture(C.MetalDrawable_Texture(md.metalDrawable))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Present presents the drawable onscreen as soon as possible.
|
||||||
|
//
|
||||||
|
// Reference: https://developer.apple.com/documentation/metal/mtldrawable/1470284-present.
|
||||||
|
func (md MetalDrawable) Present() {
|
||||||
|
C.MetalDrawable_Present(md.metalDrawable)
|
||||||
|
}
|
||||||
|
@ -31,5 +31,7 @@ void MetalLayer_SetDisplaySyncEnabled(void *metalLayer,
|
|||||||
void MetalLayer_SetDrawableSize(void *metalLayer, double width, double height);
|
void MetalLayer_SetDrawableSize(void *metalLayer, double width, double height);
|
||||||
void *MetalLayer_NextDrawable(void *metalLayer);
|
void *MetalLayer_NextDrawable(void *metalLayer);
|
||||||
void MetalLayer_SetFramebufferOnly(void *metalLayer, uint8_t framebufferOnly);
|
void MetalLayer_SetFramebufferOnly(void *metalLayer, uint8_t framebufferOnly);
|
||||||
|
uint8_t MetalLayer_PresentsWithTransaction(void *metalLayer);
|
||||||
|
|
||||||
void *MetalDrawable_Texture(void *drawable);
|
void *MetalDrawable_Texture(void *drawable);
|
||||||
|
void MetalDrawable_Present(void *drawable);
|
||||||
|
@ -85,6 +85,14 @@ void MetalLayer_SetDisplaySyncEnabled(void *metalLayer,
|
|||||||
[((CAMetalLayer *)metalLayer) setDisplaySyncEnabled:displaySyncEnabled];
|
[((CAMetalLayer *)metalLayer) setDisplaySyncEnabled:displaySyncEnabled];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// setting presentsWithTransaction YES makes the FPS stable (#1196). We're not
|
||||||
|
// sure why...
|
||||||
|
if (displaySyncEnabled) {
|
||||||
|
[((CAMetalLayer *)metalLayer) setPresentsWithTransaction:YES];
|
||||||
|
} else {
|
||||||
|
[((CAMetalLayer *)metalLayer) setPresentsWithTransaction:NO];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalLayer_SetDrawableSize(void *metalLayer, double width, double height) {
|
void MetalLayer_SetDrawableSize(void *metalLayer, double width, double height) {
|
||||||
@ -99,6 +107,14 @@ void *MetalDrawable_Texture(void *metalDrawable) {
|
|||||||
return ((id<CAMetalDrawable>)metalDrawable).texture;
|
return ((id<CAMetalDrawable>)metalDrawable).texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MetalDrawable_Present(void *metalDrawable) {
|
||||||
|
[((id<CAMetalDrawable>)metalDrawable) present];
|
||||||
|
}
|
||||||
|
|
||||||
void MetalLayer_SetFramebufferOnly(void *metalLayer, uint8_t framebufferOnly) {
|
void MetalLayer_SetFramebufferOnly(void *metalLayer, uint8_t framebufferOnly) {
|
||||||
[((CAMetalLayer *)metalLayer) setFramebufferOnly:framebufferOnly];
|
[((CAMetalLayer *)metalLayer) setFramebufferOnly:framebufferOnly];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t MetalLayer_PresentsWithTransaction(void *metalLayer) {
|
||||||
|
return [((CAMetalLayer *)metalLayer) presentsWithTransaction];
|
||||||
|
}
|
||||||
|
@ -467,10 +467,14 @@ func (g *Graphics) flushIfNeeded(present bool) {
|
|||||||
}
|
}
|
||||||
g.flushRenderCommandEncoderIfNeeded()
|
g.flushRenderCommandEncoderIfNeeded()
|
||||||
|
|
||||||
if present && g.screenDrawable != (ca.MetalDrawable{}) {
|
if !g.view.presentsWithTransaction() && present && g.screenDrawable != (ca.MetalDrawable{}) {
|
||||||
g.cb.PresentDrawable(g.screenDrawable)
|
g.cb.PresentDrawable(g.screenDrawable)
|
||||||
}
|
}
|
||||||
g.cb.Commit()
|
g.cb.Commit()
|
||||||
|
if g.view.presentsWithTransaction() && present && g.screenDrawable != (ca.MetalDrawable{}) {
|
||||||
|
g.cb.WaitUntilScheduled()
|
||||||
|
g.screenDrawable.Present()
|
||||||
|
}
|
||||||
|
|
||||||
for _, t := range g.tmpTextures {
|
for _, t := range g.tmpTextures {
|
||||||
t.Release()
|
t.Release()
|
||||||
|
@ -670,6 +670,13 @@ func (cb CommandBuffer) WaitUntilCompleted() {
|
|||||||
C.CommandBuffer_WaitUntilCompleted(cb.commandBuffer)
|
C.CommandBuffer_WaitUntilCompleted(cb.commandBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WaitUntilScheduled blocks execution of the current thread until the command buffer is scheduled.
|
||||||
|
//
|
||||||
|
// Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443036-waituntilscheduled.
|
||||||
|
func (cb CommandBuffer) WaitUntilScheduled() {
|
||||||
|
C.CommandBuffer_WaitUntilScheduled(cb.commandBuffer)
|
||||||
|
}
|
||||||
|
|
||||||
// MakeRenderCommandEncoder creates an encoder object that can
|
// MakeRenderCommandEncoder creates an encoder object that can
|
||||||
// encode graphics rendering commands into this command buffer.
|
// encode graphics rendering commands into this command buffer.
|
||||||
//
|
//
|
||||||
|
@ -153,6 +153,7 @@ uint8_t CommandBuffer_Status(void *commandBuffer);
|
|||||||
void CommandBuffer_PresentDrawable(void *commandBuffer, void *drawable);
|
void CommandBuffer_PresentDrawable(void *commandBuffer, void *drawable);
|
||||||
void CommandBuffer_Commit(void *commandBuffer);
|
void CommandBuffer_Commit(void *commandBuffer);
|
||||||
void CommandBuffer_WaitUntilCompleted(void *commandBuffer);
|
void CommandBuffer_WaitUntilCompleted(void *commandBuffer);
|
||||||
|
void CommandBuffer_WaitUntilScheduled(void *commandBuffer);
|
||||||
void *
|
void *
|
||||||
CommandBuffer_MakeRenderCommandEncoder(void *commandBuffer,
|
CommandBuffer_MakeRenderCommandEncoder(void *commandBuffer,
|
||||||
struct RenderPassDescriptor descriptor);
|
struct RenderPassDescriptor descriptor);
|
||||||
|
@ -188,6 +188,10 @@ void CommandBuffer_WaitUntilCompleted(void *commandBuffer) {
|
|||||||
[(id<MTLCommandBuffer>)commandBuffer waitUntilCompleted];
|
[(id<MTLCommandBuffer>)commandBuffer waitUntilCompleted];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandBuffer_WaitUntilScheduled(void *commandBuffer) {
|
||||||
|
[(id<MTLCommandBuffer>)commandBuffer waitUntilScheduled];
|
||||||
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
CommandBuffer_MakeRenderCommandEncoder(void *commandBuffer,
|
CommandBuffer_MakeRenderCommandEncoder(void *commandBuffer,
|
||||||
struct RenderPassDescriptor descriptor) {
|
struct RenderPassDescriptor descriptor) {
|
||||||
|
@ -69,7 +69,10 @@ func (v *view) reset() error {
|
|||||||
// MTLPixelFormatBGRA8Unorm_sRGB, MTLPixelFormatRGBA16Float, MTLPixelFormatBGRA10_XR, or
|
// MTLPixelFormatBGRA8Unorm_sRGB, MTLPixelFormatRGBA16Float, MTLPixelFormatBGRA10_XR, or
|
||||||
// MTLPixelFormatBGRA10_XR_sRGB.
|
// MTLPixelFormatBGRA10_XR_sRGB.
|
||||||
v.ml.SetPixelFormat(mtl.PixelFormatBGRA8UNorm)
|
v.ml.SetPixelFormat(mtl.PixelFormatBGRA8UNorm)
|
||||||
v.ml.SetMaximumDrawableCount(3)
|
|
||||||
|
// When presentsWithTransaction is YES and triple buffering is enabled, nextDrawing returns immediately once every two times.
|
||||||
|
// This makes FPS doubled. To avoid this, disable the triple buffering.
|
||||||
|
v.ml.SetMaximumDrawableCount(2)
|
||||||
|
|
||||||
// The vsync state might be reset. Set the state again (#1364).
|
// The vsync state might be reset. Set the state again (#1364).
|
||||||
v.ml.SetDisplaySyncEnabled(v.vsync)
|
v.ml.SetDisplaySyncEnabled(v.vsync)
|
||||||
@ -86,3 +89,7 @@ func (v *view) nextDrawable() ca.MetalDrawable {
|
|||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *view) presentsWithTransaction() bool {
|
||||||
|
return v.ml.PresentsWithTransaction()
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user