diff --git a/backends/gpu/metal/sources/device.m b/backends/gpu/metal/sources/device.m index 0689aaae1..5d3e7430c 100644 --- a/backends/gpu/metal/sources/device.m +++ b/backends/gpu/metal/sources/device.m @@ -123,8 +123,12 @@ static void set_next_fence(kore_gpu_device *device, void *fence) { } void kore_metal_device_create(kore_gpu_device *device, const kore_gpu_device_wishlist *wishlist) { - id metal_device = MTLCreateSystemDefaultDevice(); - getMetalLayer().device = metal_device; + id metal_device = getMetalLayer().device; + + if(metal_device == nil) { + metal_device = MTLCreateSystemDefaultDevice(); + } + device->metal.device = (__bridge_retained void *)metal_device; device->metal.library = (__bridge_retained void *)[metal_device newDefaultLibrary]; diff --git a/backends/gpu/metal/sources/metalunit.h b/backends/gpu/metal/sources/metalunit.h index 7570c39ad..4b5fab8ce 100644 --- a/backends/gpu/metal/sources/metalunit.h +++ b/backends/gpu/metal/sources/metalunit.h @@ -5,7 +5,8 @@ #include -#import +#include +#include static id drawable = nil; diff --git a/backends/system/macos/includes/kore3/backend/BasicOpenGLView.h b/backends/system/macos/includes/kore3/backend/BasicOpenGLView.h index c2c8ad017..3335dd6a4 100644 --- a/backends/system/macos/includes/kore3/backend/BasicOpenGLView.h +++ b/backends/system/macos/includes/kore3/backend/BasicOpenGLView.h @@ -1,5 +1,8 @@ #ifdef KORE_METAL -#import +#import +#import +#import +#import #else #import #import @@ -13,7 +16,7 @@ struct kore_g5_render_target; -@interface BasicOpenGLView : MTKView { +@interface BasicOpenGLView : NSView { @private id device; id commandQueue; @@ -34,6 +37,8 @@ struct kore_g5_render_target; #ifdef KORE_METAL - (CAMetalLayer *)metalLayer; + +- (void)updateDrawableSize; #else - (void)prepareOpenGL; - (void)switchBuffers; diff --git a/backends/system/macos/sources/BasicOpenGLView.m b/backends/system/macos/sources/BasicOpenGLView.m index faaabff33..6ab153cec 100644 --- a/backends/system/macos/sources/BasicOpenGLView.m +++ b/backends/system/macos/sources/BasicOpenGLView.m @@ -1,4 +1,4 @@ -#import "BasicOpenGLView.h" +#import #include #include @@ -6,6 +6,10 @@ #include #ifdef KORE_METAL +#import +#import +#import + // #include #endif @@ -404,6 +408,8 @@ - (void)prepareOpenGL { - (void)update { // window resizes, moves and display changes (resize, depth and display config change) #ifdef KORE_OPENGL [super update]; +#else + [self updateDrawableSize]; #endif } @@ -418,15 +424,29 @@ - (id)initWithFrame:(NSRect)frameRect { return self; } #else +- (void)updateDrawableSize { // This is the high DPI version of resize + CAMetalLayer *metalLayer = (CAMetalLayer *)self.layer; + NSSize size = self.bounds.size; + NSSize backingSize = size; -static CAMetalLayer *metalLayer = NULL; + backingSize = [self convertSizeToBacking:size]; + + metalLayer.contentsScale = backingSize.height / size.height; + metalLayer.drawableSize = NSSizeToCGSize(backingSize); +} - (id)initWithFrame:(NSRect)frameRect { self = [super initWithFrame:frameRect]; - metalLayer = (CAMetalLayer *)self.layer; + if(self->device == nil) { + self->device = MTLCreateSystemDefaultDevice(); + } + + self.wantsLayer = YES; + self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; - // metalLayer.device = device; + CAMetalLayer* metalLayer = (CAMetalLayer *)self.layer; + metalLayer.device = self->device; metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; metalLayer.framebufferOnly = NO; // metalLayer.presentsWithTransaction = YES; @@ -434,8 +454,40 @@ - (id)initWithFrame:(NSRect)frameRect { metalLayer.opaque = YES; metalLayer.backgroundColor = nil; + [self updateDrawableSize]; return self; } + ++ (Class)layerClass { + return [CAMetalLayer class]; +} + +- (void)setBounds:(NSRect)bounds { + [super setBounds:bounds]; + [self updateDrawableSize]; +} + +- (BOOL)wantsUpdateLayer { + return YES; +} + +- (CALayer *)makeBackingLayer { + return [CAMetalLayer layer]; +} + +- (void)viewDidChangeBackingProperties { + [super viewDidChangeBackingProperties]; + [self updateDrawableSize]; +} + +- (void)setFrame:(NSRect)frame { + [super setFrame:frame]; + [self updateDrawableSize]; +} + +- (CAMetalLayer *)metalLayer { + return (CAMetalLayer *)self.layer; +} #endif - (BOOL)acceptsFirstResponder { @@ -454,12 +506,6 @@ - (void)resize:(NSSize)size { [self setFrameSize:size]; } -#ifdef KORE_METAL -- (CAMetalLayer *)metalLayer { - return (CAMetalLayer *)self.layer; -} -#endif - @end void kore_copy_to_clipboard(const char *text) { diff --git a/backends/system/macos/sources/system.m b/backends/system/macos/sources/system.m index 0ecbcdc3d..75dad88b8 100644 --- a/backends/system/macos/sources/system.m +++ b/backends/system/macos/sources/system.m @@ -1,6 +1,7 @@ #import "BasicOpenGLView.h" #import +#import #include #include @@ -8,6 +9,10 @@ #include #include +#ifdef KORE_METAL +#include +#endif + bool withAutoreleasepool(bool (*f)(void)) { @autoreleasepool { return f(); @@ -41,6 +46,11 @@ - (void)windowDidBecomeMain:(NSNotification *)notification; static KoreAppDelegate *delegate; static struct HIDManager *hidManager; +#ifdef KORE_METAL +static kore_event displayLinkEvent; +static CVDisplayLinkRef displayLink; +#endif + /*struct KoreWindow : public KoreWindowBase { NSWindow* handle; BasicOpenGLView* view; @@ -55,6 +65,17 @@ - (void)windowDidBecomeMain:(NSNotification *)notification; CAMetalLayer *getMetalLayer(void) { return [view metalLayer]; } + +static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, + const CVTimeStamp* now, + const CVTimeStamp* outputTime, + CVOptionFlags flagsIn, + CVOptionFlags* flagsOut, + void* displayLinkContext) { + + kore_event_signal(&displayLinkEvent); + return kCVReturnSuccess; +} #endif bool kore_internal_handle_messages(void) { @@ -68,15 +89,17 @@ bool kore_internal_handle_messages(void) { } // Sleep for a frame to limit the calls when the window is not visible. - if (!window.visible) { - [NSThread sleepForTimeInterval:1.0 / 60]; - } + // if (!window.visible) { + // [NSThread sleepForTimeInterval:1.0 / 60]; + // } return true; } void swapBuffersMac(int windowId) { #ifndef KORE_METAL [windows[windowId].view switchBuffers]; +#else + kore_event_wait(&displayLinkEvent); #endif } @@ -192,6 +215,13 @@ int kore_init(const char *name, int width, int height, kore_window_parameters *w // kore_g4_internal_init(); // TODO // kore_g4_internal_init_window(windowId, frame->depth_bits, frame->stencil_bits, true); // TODO +#ifdef KORE_METAL + kore_event_init(&displayLinkEvent, false); + CVDisplayLinkCreateWithActiveCGDisplays(&displayLink); + CVDisplayLinkSetOutputCallback(displayLink, &displayLinkCallback, NULL); + CVDisplayLinkStart(displayLink); +#endif + return 0; } @@ -226,7 +256,16 @@ void kore_load_url(const char *url) { return language; } -void kore_internal_shutdown(void) {} +void kore_internal_shutdown(void) { +#ifdef KORE_METAL + if (displayLink) { + CVDisplayLinkStop(displayLink); + CVDisplayLinkRelease(displayLink); + displayLink = NULL; + } + kore_event_destroy(&displayLinkEvent); +#endif +} static const char *getSavePath(void) { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); diff --git a/kfile.js b/kfile.js index 2d5a87f35..464acb617 100644 --- a/kfile.js +++ b/kfile.js @@ -196,7 +196,7 @@ else if (platform === Platform.OSX) { addBackend('gpu/metal'); addKoreDefine('METAL'); project.addLib('Metal'); - project.addLib('MetalKit'); + project.addLib('QuartzCore'); } else if (graphics === GraphicsApi.OpenGL) { addBackend('gpu/opengl');