From a064955a135460dc72637d962ba805f88bcd8ce9 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sat, 20 Apr 2019 15:17:59 +0900 Subject: [PATCH] graphicsdriver/metal: Use NSAutoreleasePool to release drawable correctly Fixes #847 --- internal/driver/graphics.go | 2 ++ internal/graphicscommand/command.go | 3 +++ internal/graphicsdriver/metal/driver.go | 33 ++++++++++++++++++++++++ internal/graphicsdriver/opengl/driver.go | 8 ++++++ 4 files changed, 46 insertions(+) diff --git a/internal/driver/graphics.go b/internal/driver/graphics.go index 92e2b6d96..adac4afbc 100644 --- a/internal/driver/graphics.go +++ b/internal/driver/graphics.go @@ -20,6 +20,8 @@ import ( ) type Graphics interface { + Begin() + End() SetWindow(window uintptr) SetVertices(vertices []float32, indices []uint16) Flush() diff --git a/internal/graphicscommand/command.go b/internal/graphicscommand/command.go index 3ad211c63..555112348 100644 --- a/internal/graphicscommand/command.go +++ b/internal/graphicscommand/command.go @@ -159,6 +159,8 @@ func (q *commandQueue) Flush() { if recordLog() { fmt.Println("--") } + + theGraphicsDriver.Begin() for len(q.commands) > 0 { nv := 0 ne := 0 @@ -199,6 +201,7 @@ func (q *commandQueue) Flush() { } q.commands = q.commands[nc:] } + theGraphicsDriver.End() q.commands = nil q.nvertices = 0 q.nindices = 0 diff --git a/internal/graphicsdriver/metal/driver.go b/internal/graphicsdriver/metal/driver.go index 3e1792b5c..f16821cfc 100644 --- a/internal/graphicsdriver/metal/driver.go +++ b/internal/graphicsdriver/metal/driver.go @@ -30,6 +30,20 @@ import ( "github.com/hajimehoshi/ebiten/internal/mainthread" ) +// #cgo CFLAGS: -x objective-c -mmacosx-version-min=10.11 +// #cgo LDFLAGS: -framework Foundation +// +// #import +// +// static void* allocAutoreleasePool() { +// return [[NSAutoreleasePool alloc] init]; +// } +// +// static void releaseAutoreleasePool(void* pool) { +// [(NSAutoreleasePool*)pool release]; +// } +import "C" + const source = `#include #define FILTER_NEAREST {{.FilterNearest}} @@ -287,6 +301,8 @@ type Driver struct { dst *Image maxImageSize int + + pool unsafe.Pointer } var theDriver Driver @@ -295,6 +311,23 @@ func Get() *Driver { return &theDriver } +func (d *Driver) Begin() { + // NSAutoreleasePool is required to release drawable correctly (#847). + // https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/Drawables.html + mainthread.Run(func() error { + d.pool = C.allocAutoreleasePool() + return nil + }) +} + +func (d *Driver) End() { + mainthread.Run(func() error { + C.releaseAutoreleasePool(d.pool) + d.pool = nil + return nil + }) +} + func (d *Driver) SetWindow(window uintptr) { mainthread.Run(func() error { // Note that [NSApp mainWindow] returns nil when the window is borderless. diff --git a/internal/graphicsdriver/opengl/driver.go b/internal/graphicsdriver/opengl/driver.go index c2724ae49..4b7665a6b 100644 --- a/internal/graphicsdriver/opengl/driver.go +++ b/internal/graphicsdriver/opengl/driver.go @@ -33,6 +33,14 @@ type Driver struct { context context } +func (d *Driver) Begin() { + // Do nothing. +} + +func (d *Driver) End() { + // Do nothing. +} + func (d *Driver) SetWindow(window uintptr) { // Do nothing. }