From eacd52f009699346699ba8a9e4ca64621c56eac9 Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Sat, 23 Jun 2018 13:32:46 -0700 Subject: [PATCH] fix(Metal): improve shader stability * use MTKView, which handles layer and scaling changes automatically between displays --- gfx/common/metal/Renderer.h | 1 - gfx/common/metal/Renderer.m | 79 +++++++------ gfx/common/metal/RendererCommon.h | 33 +++--- gfx/common/metal/TexturedView.h | 5 +- gfx/common/metal/TexturedView.m | 7 +- gfx/common/metal/View.h | 12 +- gfx/common/metal_common.h | 12 +- gfx/common/metal_common.m | 189 +++++++++++++++++++++++------- gfx/drivers/metal.m | 7 +- ui/drivers/cocoa/cocoa_common.h | 16 +-- ui/drivers/cocoa/cocoa_common.m | 28 +++-- ui/drivers/ui_cocoa.m | 21 +--- 12 files changed, 268 insertions(+), 142 deletions(-) diff --git a/gfx/common/metal/Renderer.h b/gfx/common/metal/Renderer.h index 30cbf0dc64..05c50eb65e 100644 --- a/gfx/common/metal/Renderer.h +++ b/gfx/common/metal/Renderer.h @@ -12,7 +12,6 @@ #import "Context.h" #import "PixelConverter.h" -@class ViewDescriptor; @protocol View; @interface Renderer : NSObject diff --git a/gfx/common/metal/Renderer.m b/gfx/common/metal/Renderer.m index cb704c50a1..7c668b7251 100644 --- a/gfx/common/metal/Renderer.m +++ b/gfx/common/metal/Renderer.m @@ -113,9 +113,7 @@ { MTLRenderPassDescriptor *rpd = [MTLRenderPassDescriptor new]; - // Cornflower Blue #58BAF9 - //rpd.colorAttachments[0].clearColor = MTLClearColorMake(0x58 / 255.0, 0xba / 255.0, 0xf9 / 255.0, 1.0); - rpd.colorAttachments[0].loadAction = MTLLoadActionLoad; + rpd.colorAttachments[0].loadAction = MTLLoadActionDontCare; rpd.colorAttachments[0].storeAction = MTLStoreActionStore; _t_rpd = rpd; } @@ -163,49 +161,60 @@ for (id v in _views) { if (!v.visible) continue; - if ([v respondsToSelector:@selector(prepareFrame:)]) { - [v prepareFrame:_context]; + if ([v respondsToSelector:@selector(drawWithContext:)]) { + [v drawWithContext:_context]; } } - - id drawable = _context.nextDrawable; - _t_rpd.colorAttachments[0].texture = drawable.texture; - - id rce = [cb renderCommandEncoderWithDescriptor:_t_rpd]; - [rce setVertexBytes:&_uniforms length:sizeof(_uniforms) atIndex:BufferIndexUniforms]; - + + BOOL pendingDraws = NO; for (id v in _views) { - if (!v.visible || - ![v respondsToSelector:@selector(drawWithEncoder:)]) { - continue; + if (v.visible && (v.drawState & ViewDrawStateEncoder) != 0) { + pendingDraws = YES; + break; } - - // set view state - if (v.format == RPixelFormatBGRX8Unorm) { - [rce setRenderPipelineState:_t_pipelineStateNoAlpha]; - } - else { - [rce setRenderPipelineState:_t_pipelineState]; - } - - if (v.filter == RTextureFilterNearest) { - [rce setFragmentSamplerState:_samplerStateNearest atIndex:SamplerIndexDraw]; - } - else { - [rce setFragmentSamplerState:_samplerStateLinear atIndex:SamplerIndexDraw]; - } - - [v drawWithEncoder:rce]; } - - [rce endEncoding]; + + if (pendingDraws) { + id drawable = _context.nextDrawable; + _t_rpd.colorAttachments[0].texture = drawable.texture; + + id rce = [cb renderCommandEncoderWithDescriptor:_t_rpd]; + [rce setVertexBytes:&_uniforms length:sizeof(_uniforms) atIndex:BufferIndexUniforms]; + + for (id v in _views) { + if (!v.visible || + ![v respondsToSelector:@selector(drawWithEncoder:)] || + (v.drawState & ViewDrawStateEncoder) == 0) { + continue; + } + + // set view state + if (v.format == RPixelFormatBGRX8Unorm || v.format == RPixelFormatB5G6R5Unorm) { + [rce setRenderPipelineState:_t_pipelineStateNoAlpha]; + } + else { + [rce setRenderPipelineState:_t_pipelineState]; + } + + if (v.filter == RTextureFilterNearest) { + [rce setFragmentSamplerState:_samplerStateNearest atIndex:SamplerIndexDraw]; + } + else { + [rce setFragmentSamplerState:_samplerStateLinear atIndex:SamplerIndexDraw]; + } + + [v drawWithEncoder:rce]; + } + + [rce endEncoding]; + } __block dispatch_semaphore_t inflight = _inflightSemaphore; [cb addCompletedHandler:^(id _) { dispatch_semaphore_signal(inflight); }]; - [cb presentDrawable:drawable]; + [cb presentDrawable:_context.nextDrawable]; [_context end]; } diff --git a/gfx/common/metal/RendererCommon.h b/gfx/common/metal/RendererCommon.h index 1aa052186c..1d5f009598 100644 --- a/gfx/common/metal/RendererCommon.h +++ b/gfx/common/metal/RendererCommon.h @@ -11,33 +11,34 @@ #import +// TODO(sgc): implement triple buffering /*! @brief maximum inflight frames */ -#define MAX_INFLIGHT 3 +#define MAX_INFLIGHT 1 #pragma mark - Pixel Formats typedef NS_ENUM(NSUInteger, RPixelFormat) { - - RPixelFormatInvalid, - - /* 16-bit formats */ - RPixelFormatBGRA4Unorm, - RPixelFormatB5G6R5Unorm, - - RPixelFormatBGRA8Unorm, - RPixelFormatBGRX8Unorm, - - RPixelFormatCount, + + RPixelFormatInvalid, + + /* 16-bit formats */ + RPixelFormatBGRA4Unorm, + RPixelFormatB5G6R5Unorm, + + RPixelFormatBGRA8Unorm, + RPixelFormatBGRX8Unorm, // RetroArch XRGB + + RPixelFormatCount, }; extern NSUInteger RPixelFormatToBPP(RPixelFormat format); extern NSString *NSStringFromRPixelFormat(RPixelFormat format); typedef NS_ENUM(NSUInteger, RTextureFilter) { - RTextureFilterNearest, - RTextureFilterLinear, - - RTextureFilterCount, + RTextureFilterNearest, + RTextureFilterLinear, + + RTextureFilterCount, }; #endif /* RendererCommon_h */ diff --git a/gfx/common/metal/TexturedView.h b/gfx/common/metal/TexturedView.h index 0633832540..aa5398ae4f 100644 --- a/gfx/common/metal/TexturedView.h +++ b/gfx/common/metal/TexturedView.h @@ -13,11 +13,12 @@ @property (readwrite) BOOL visible; @property (readwrite) CGRect frame; @property (readwrite) CGSize size; +@property (readonly) ViewDrawState drawState; - (instancetype)initWithDescriptor:(ViewDescriptor *)td renderer:(Renderer *)renderer; -- (void)prepareFrame:(Context *)ctx; -- (void)updateFrame:(void const *)src pitch:(NSUInteger)pitch; +- (void)drawWithContext:(Context *)ctx; - (void)drawWithEncoder:(id)rce; +- (void)updateFrame:(void const *)src pitch:(NSUInteger)pitch; @end diff --git a/gfx/common/metal/TexturedView.m b/gfx/common/metal/TexturedView.m index 246be6859e..4dcc8634cc 100644 --- a/gfx/common/metal/TexturedView.m +++ b/gfx/common/metal/TexturedView.m @@ -35,6 +35,11 @@ _filter = d.filter; _context = r.context; _visible = YES; + if (_format == RPixelFormatBGRA8Unorm || _format == RPixelFormatBGRX8Unorm) { + _drawState = ViewDrawStateEncoder; + } else { + _drawState = ViewDrawStateAll; + } self.size = d.size; self.frame = CGRectMake(0, 0, 1, 1); } @@ -113,7 +118,7 @@ _pixelsDirty = NO; } -- (void)prepareFrame:(Context *)ctx { +- (void)drawWithContext:(Context *)ctx { [self _convertFormat]; } diff --git a/gfx/common/metal/View.h b/gfx/common/metal/View.h index 56afdc4128..5f390cbc34 100644 --- a/gfx/common/metal/View.h +++ b/gfx/common/metal/View.h @@ -10,6 +10,15 @@ #import #import +typedef NS_ENUM(NSInteger, ViewDrawState) +{ + ViewDrawStateNone = 0x00, + ViewDrawStateContext = 0x01, + ViewDrawStateEncoder = 0x02, + + ViewDrawStateAll = 0x03, +}; + @protocol View @property (readonly) RPixelFormat format; @@ -17,9 +26,10 @@ @property (readwrite) BOOL visible; @property (readwrite) CGRect frame; @property (readwrite) CGSize size; +@property (readonly) ViewDrawState drawState; @optional -- (void)prepareFrame:(Context *)ctx; +- (void)drawWithContext:(Context *)ctx; - (void)drawWithEncoder:(id)rce; @end diff --git a/gfx/common/metal_common.h b/gfx/common/metal_common.h index bd34c27326..63ac8cbc3f 100644 --- a/gfx/common/metal_common.h +++ b/gfx/common/metal_common.h @@ -9,6 +9,7 @@ #define METAL_COMMON_H__ #import +#import #import "metal/metal_common.h" #include @@ -20,6 +21,9 @@ RETRO_BEGIN_DECLS +extern MTLPixelFormat glslang_format_to_metal(glslang_format fmt); +extern MTLPixelFormat SelectOptimalPixelFormat(MTLPixelFormat fmt); + #pragma mark - Classes @interface FrameView : NSObject @@ -29,6 +33,7 @@ RETRO_BEGIN_DECLS @property (readwrite) BOOL visible; @property (readwrite) CGRect frame; @property (readwrite) CGSize size; +@property (readonly) ViewDrawState drawState; @property (readonly) struct video_shader* shader; @property (readwrite) uint64_t frameCount; @@ -53,7 +58,7 @@ RETRO_BEGIN_DECLS filter:(RTextureFilter)filter; @end -@interface MetalDriver : NSObject +@interface MetalDriver : NSObject @property (readonly) video_viewport_t* viewport; @property (readwrite) bool keepAspect; @@ -71,11 +76,6 @@ RETRO_BEGIN_DECLS /*! @brief setNeedsResize triggers a display resize */ - (void)setNeedsResize; -- (void)viewDidUpdateFrame:(NSRect)rect; - - -#pragma mark - Menu APIs - @end RETRO_END_DECLS diff --git a/gfx/common/metal_common.m b/gfx/common/metal_common.m index 64ce23b89a..786fe0f71d 100644 --- a/gfx/common/metal_common.m +++ b/gfx/common/metal_common.m @@ -32,7 +32,7 @@ @property (readwrite) video_viewport_t *viewport; - (instancetype)initWithDescriptor:(ViewDescriptor *)td renderer:(Renderer *)renderer; -- (void)prepareFrame:(Context *)ctx; +- (void)drawWithContext:(Context *)ctx; - (void)drawWithEncoder:(id)rce; @end @@ -72,32 +72,19 @@ } } -#pragma mark - swap chain - -- (void)viewDidUpdateFrame:(NSRect)rect -{ - RARCH_LOG("[MetalDriver] viewDidUpdateFrame %s\n", NSStringFromRect(rect).UTF8String); - _viewport->full_width = (unsigned int)rect.size.width; - _viewport->full_height = (unsigned int)rect.size.height; - video_driver_set_size(&_viewport->full_width, &_viewport->full_height); - resize_chain = YES; -} - - #pragma mark - video - (void)setVideo:(const video_info_t *)video { _video = *video; - _viewport->full_width = _video.width; - _viewport->full_height = _video.height; if (!_renderer) { id device = MTLCreateSystemDefaultDevice(); _device = device; - NSView *view = (NSView *)apple_platform.renderView; + MetalView *view = (MetalView *)apple_platform.renderView; + view.device = device; CAMetalLayer *layer = (CAMetalLayer *)view.layer; - layer.device = device; + //layer.device = device; _renderer = [[Renderer alloc] initWithDevice:device layer:layer]; _menu.renderer = _renderer; } @@ -119,11 +106,6 @@ - (void)beginFrame { - if (resize_chain) { - [_renderer drawableSizeWillChange:CGSizeMake(_viewport->full_width, _viewport->full_height)]; - resize_chain = NO; - } - video_driver_update_viewport(_viewport, NO, _keepAspect); [_renderer beginFrame]; @@ -139,6 +121,21 @@ // TODO(sgc): resize all drawables } +#pragma mark - MTKViewDelegate + +- (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size { + RARCH_LOG("[MetalDriver] drawableSizeWillChange: %s\n", NSStringFromSize(size).UTF8String); + _viewport->full_width = (unsigned int)size.width; + _viewport->full_height = (unsigned int)size.height; + video_driver_set_size(&_viewport->full_width, &_viewport->full_height); + [_renderer drawableSizeWillChange:size]; + video_driver_update_viewport(_viewport, NO, _keepAspect); +} + +- (void)drawInMTKView:(MTKView *)view { + +} + extern inline matrix_float4x4 matrix_proj_ortho1(float left, float right, float top, float bottom) { float near = 0; @@ -292,12 +289,18 @@ typedef struct ALIGN(16) _format = d.format; _bpp = RPixelFormatToBPP(_format); _filter = d.filter; + if (_format == RPixelFormatBGRA8Unorm || _format == RPixelFormatBGRX8Unorm) { + _drawState = ViewDrawStateEncoder; + } else { + _drawState = ViewDrawStateAll; + } _visible = YES; _engine.mvp = matrix_proj_ortho1(0, 1, 0, 1); [self _initSamplers]; self.size = d.size; self.frame = CGRectMake(0, 0, 1, 1); + resize_render_targets = YES; } return self; } @@ -425,7 +428,6 @@ typedef struct ALIGN(16) if (init_history) [self _initHistory]; else { - // TODO(sgc): change to ring buffer? int k; /* todo: what about frame-duping ? * maybe clone d3d10_texture_t with AddRef */ @@ -546,7 +548,7 @@ static vertex_t vertex_bytes[] = { } } -- (void)prepareFrame:(Context *)ctx +- (void)drawWithContext:(Context *)ctx { _texture = _engine.frame.texture[0].view; [self _convertFormat]; @@ -567,15 +569,15 @@ static vertex_t vertex_bytes[] = { MTLRenderPassDescriptor *rpd = [MTLRenderPassDescriptor new]; rpd.colorAttachments[0].clearColor = MTLClearColorMake(0, 0, 0, 1.0); - rpd.colorAttachments[0].loadAction = MTLLoadActionDontCare; + rpd.colorAttachments[0].loadAction = MTLLoadActionClear; rpd.colorAttachments[0].storeAction = MTLStoreActionStore; BOOL firstPass = YES; for (unsigned i = 0; i < _shader->passes; i++) { - BOOL lastPass = i == _shader->passes - 1; + BOOL backBuffer = (_engine.pass[i].rt.view == nil); - if (lastPass) { + if (backBuffer) { rpd.colorAttachments[0].texture = _context.nextDrawable.texture; } else { @@ -630,7 +632,7 @@ static vertex_t vertex_bytes[] = { texture_sem++; } - if (lastPass) { + if (backBuffer) { [rce setViewport:_engine.frame.viewport]; } else { @@ -645,7 +647,11 @@ static vertex_t vertex_bytes[] = { [rce endEncoding]; _texture = _engine.pass[i].rt.view; } - _texture = nil; + if (_texture == nil) { + _drawState = ViewDrawStateContext; + } else { + _drawState = ViewDrawStateAll; + } } - (void)_updateRenderTargets @@ -712,15 +718,17 @@ static vertex_t vertex_bytes[] = { } RARCH_LOG("[Metal]: Updating framebuffer size %u x %u.\n", width, height); - - if (i != (_shader->passes - 1)) { - + MTLPixelFormat fmt = SelectOptimalPixelFormat(glslang_format_to_metal(_engine.pass[i].semantics.format)); + if ((i != (_shader->passes - 1)) || + (width != _viewport->width) || (height != _viewport->height) || + fmt != MTLPixelFormatBGRA8Unorm) + { _engine.pass[i].viewport.width = width; _engine.pass[i].viewport.height = height; _engine.pass[i].viewport.znear = 0.0; _engine.pass[i].viewport.zfar = 1.0; - MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm + MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:fmt width:width height:height mipmapped:false]; @@ -823,8 +831,16 @@ static vertex_t vertex_bytes[] = { if (!slang_process(shader, i, RARCH_SHADER_METAL, 20000, &semantics_map, &_engine.pass[i].semantics)) return NO; +#ifdef DEBUG + bool save_msl = true; +#else + bool save_msl = false; +#endif + NSString *vs_src = [NSString stringWithUTF8String:shader->pass[i].source.string.vertex]; + NSString *fs_src = [NSString stringWithUTF8String:shader->pass[i].source.string.fragment]; + + // vertex descriptor @try { - // vertex descriptor MTLVertexDescriptor *vd = [MTLVertexDescriptor new]; vd.attributes[0].offset = offsetof(vertex_t, pos); vd.attributes[0].format = MTLVertexFormatFloat4; @@ -839,8 +855,11 @@ static vertex_t vertex_bytes[] = { psd.label = [NSString stringWithFormat:@"pass %d", i]; MTLRenderPipelineColorAttachmentDescriptor *ca = psd.colorAttachments[0]; - ca.pixelFormat = MTLPixelFormatBGRA8Unorm; - ca.blendingEnabled = YES; + + ca.pixelFormat = SelectOptimalPixelFormat(glslang_format_to_metal(_engine.pass[i].semantics.format)); + + // TODO(sgc): confirm we never need blending for render passes + ca.blendingEnabled = NO; ca.sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha; ca.sourceRGBBlendFactor = MTLBlendFactorSourceAlpha; ca.destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha; @@ -848,19 +867,18 @@ static vertex_t vertex_bytes[] = { psd.sampleCount = 1; psd.vertexDescriptor = vd; - NSString *vs_src = [NSString stringWithUTF8String:shader->pass[i].source.string.vertex]; - NSLog(@"vertex function:\n%@", vs_src); - NSString *fs_src = [NSString stringWithUTF8String:shader->pass[i].source.string.fragment]; - NSLog(@"fragment function:\n%@", fs_src); NSError *err; id lib = [_context.device newLibraryWithSource:vs_src options:nil error:&err]; if (err != nil) { if (lib == nil) { + save_msl = true; RARCH_ERR("Metal]: unable to compile vertex shader: %s\n", err.localizedDescription.UTF8String); return NO; } +#if DEBUG RARCH_WARN("[Metal]: warnings compiling vertex shader: %s\n", err.localizedDescription.UTF8String); +#endif } psd.vertexFunction = [lib newFunctionWithName:@"main0"]; @@ -868,16 +886,20 @@ static vertex_t vertex_bytes[] = { lib = [_context.device newLibraryWithSource:fs_src options:nil error:&err]; if (err != nil) { if (lib == nil) { + save_msl = true; RARCH_ERR("Metal]: unable to compile fragment shader: %s\n", err.localizedDescription.UTF8String); return NO; } +#if DEBUG RARCH_WARN("[Metal]: warnings compiling fragment shader: %s\n", err.localizedDescription.UTF8String); +#endif } psd.fragmentFunction = [lib newFunctionWithName:@"main0"]; STRUCT_ASSIGN(_engine.pass[i]._state, [_context.device newRenderPipelineStateWithDescriptor:psd error:&err]); if (err != nil) { + save_msl = true; RARCH_ERR("error creating pipeline state: %s", err.localizedDescription.UTF8String); return NO; } @@ -892,6 +914,29 @@ static vertex_t vertex_bytes[] = { STRUCT_ASSIGN(_engine.pass[i].buffers[j], buf); } } @finally { + if (save_msl) { + RARCH_LOG("[Metal]: saving metal shader files\n"); + + NSError *err = nil; + NSString *basePath = [[NSString stringWithUTF8String:shader->pass[i].source.path] stringByDeletingPathExtension]; + [vs_src writeToFile:[basePath stringByAppendingPathExtension:@"vs.metal"] + atomically:NO + encoding:NSStringEncodingConversionAllowLossy + error:&err]; + if (err != nil) { + RARCH_ERR("[Metal]: unable to save vertex shader source: %s\n", err.localizedDescription.UTF8String); + } + + err = nil; + [fs_src writeToFile:[basePath stringByAppendingPathExtension:@"fs.metal"] + atomically:NO + encoding:NSStringEncodingConversionAllowLossy + error:&err]; + if (err != nil) { + RARCH_ERR("[Metal]: unable to save fragment shader source: %s\n", err.localizedDescription.UTF8String); + } + } + free(shader->pass[i].source.string.vertex); free(shader->pass[i].source.string.fragment); @@ -945,3 +990,67 @@ static vertex_t vertex_bytes[] = { } @end + +MTLPixelFormat glslang_format_to_metal(glslang_format fmt) +{ +#undef FMT2 +#define FMT2(x,y) case SLANG_FORMAT_##x: return MTLPixelFormat##y + + switch (fmt) + { + FMT2(R8_UNORM, R8Unorm); + FMT2(R8_SINT, R8Sint); + FMT2(R8_UINT, R8Uint); + FMT2(R8G8_UNORM, RG8Unorm); + FMT2(R8G8_SINT, RG8Sint); + FMT2(R8G8_UINT, RG8Uint); + FMT2(R8G8B8A8_UNORM, RGBA8Unorm); + FMT2(R8G8B8A8_SINT, RGBA8Sint); + FMT2(R8G8B8A8_UINT, RGBA8Uint); + FMT2(R8G8B8A8_SRGB, RGBA8Unorm_sRGB); + + FMT2(A2B10G10R10_UNORM_PACK32, RGB10A2Unorm); + FMT2(A2B10G10R10_UINT_PACK32, RGB10A2Uint); + + FMT2(R16_UINT, R16Uint); + FMT2(R16_SINT, R16Sint); + FMT2(R16_SFLOAT, R16Float); + FMT2(R16G16_UINT, RG16Uint); + FMT2(R16G16_SINT, RG16Sint); + FMT2(R16G16_SFLOAT, RG16Float); + FMT2(R16G16B16A16_UINT, RGBA16Uint); + FMT2(R16G16B16A16_SINT, RGBA16Sint); + FMT2(R16G16B16A16_SFLOAT, RGBA16Float); + + FMT2(R32_UINT, R32Uint); + FMT2(R32_SINT, R32Sint); + FMT2(R32_SFLOAT, R32Float); + FMT2(R32G32_UINT, RG32Uint); + FMT2(R32G32_SINT, RG32Sint); + FMT2(R32G32_SFLOAT, RG32Float); + FMT2(R32G32B32A32_UINT, RGBA32Uint); + FMT2(R32G32B32A32_SINT, RGBA32Sint); + FMT2(R32G32B32A32_SFLOAT, RGBA32Float); + + case SLANG_FORMAT_UNKNOWN: + default: + break; + } +#undef FMT2 + return MTLPixelFormatInvalid; +} + +MTLPixelFormat SelectOptimalPixelFormat(MTLPixelFormat fmt) +{ + switch (fmt) + { + case MTLPixelFormatRGBA8Unorm: + return MTLPixelFormatBGRA8Unorm; + + case MTLPixelFormatRGBA8Unorm_sRGB: + return MTLPixelFormatBGRA8Unorm_sRGB; + + default: + return fmt; + } +} diff --git a/gfx/drivers/metal.m b/gfx/drivers/metal.m index f93ad22e24..05a85199bb 100644 --- a/gfx/drivers/metal.m +++ b/gfx/drivers/metal.m @@ -53,13 +53,14 @@ static void *metal_init(const video_info_t *video, gfx_ctx_mode_t mode; [apple_platform setViewType:APPLE_VIEW_TYPE_METAL]; - MetalDriver *md = [MetalDriver new]; if (md == nil) { return NULL; } + MetalView *view = (MetalView *)apple_platform.renderView; + view.delegate = md; - apple_platform.delegate = md; + md.keepAspect = video->force_aspect; RARCH_LOG("[Metal]: Detecting screen resolution %ux%u.\n", video->width, video->height); @@ -67,8 +68,8 @@ static void *metal_init(const video_info_t *video, mode.height = video->height; mode.fullscreen = video->fullscreen; - [apple_platform setVideoMode:mode]; [md setVideo:video]; + [apple_platform setVideoMode:mode]; *input = NULL; *input_data = NULL; diff --git a/ui/drivers/cocoa/cocoa_common.h b/ui/drivers/cocoa/cocoa_common.h index 760fa43c1e..8e0cc1a0dd 100644 --- a/ui/drivers/cocoa/cocoa_common.h +++ b/ui/drivers/cocoa/cocoa_common.h @@ -36,22 +36,16 @@ typedef enum apple_view_type { APPLE_VIEW_TYPE_METAL, } apple_view_type_t; -@protocol PlatformDelegate #ifdef HAVE_METAL -@optional -- (void)viewDidUpdateFrame:(NSRect)rect; -#endif +#import + +@interface MetalView : MTKView @end +#endif + @protocol ApplePlatform -@property (readwrite,retain) id delegate; - -/*! - @brief viewHandle returns an appropriate handle for the current view type - */ -@property (readonly) id viewHandle; - /*! @brief renderView returns the current render view based on the viewType */ @property (readonly) id renderView; diff --git a/ui/drivers/cocoa/cocoa_common.m b/ui/drivers/cocoa/cocoa_common.m index 0f0667e909..451b8a412e 100644 --- a/ui/drivers/cocoa/cocoa_common.m +++ b/ui/drivers/cocoa/cocoa_common.m @@ -19,9 +19,6 @@ #include "cocoa_common.h" #ifdef HAVE_COCOA #include "../ui_cocoa.h" -#ifdef HAVE_VULKAN -#import -#endif #endif #include @@ -46,6 +43,21 @@ #include "../../../location/location_driver.h" #include "../../../camera/camera_driver.h" +#ifdef HAVE_METAL +@implementation MetalView + +- (void)keyDown:(NSEvent*)theEvent +{ +} + +/* Stop the annoying sound when pressing a key. */ +- (BOOL)acceptsFirstResponder +{ + return YES; +} +@end +#endif + static CocoaView* g_instance; #if defined(HAVE_COCOA) @@ -96,15 +108,13 @@ void *glkitview_init(void); } #if defined(HAVE_COCOA) +- (BOOL)layer:(CALayer *)layer shouldInheritContentsScale:(CGFloat)newScale fromWindow:(NSWindow *)window { + return YES; +} + - (void)setFrame:(NSRect)frameRect { [super setFrame:frameRect]; - - if (apple_platform.delegate != nil) - { - [apple_platform.delegate viewDidUpdateFrame:frameRect]; - } - cocoagl_gfx_ctx_update(); } diff --git a/ui/drivers/ui_cocoa.m b/ui/drivers/ui_cocoa.m index 081c4df749..b3173fe66d 100644 --- a/ui/drivers/ui_cocoa.m +++ b/ui/drivers/ui_cocoa.m @@ -53,7 +53,6 @@ id apple_platform; NSWindow* _window; apple_view_type_t _vt; NSView* _renderView; - id _delegate; } @property (nonatomic, retain) NSWindow IBOutlet* window; @@ -259,9 +258,9 @@ static char** waiting_argv; case APPLE_VIEW_TYPE_METAL: #if defined(HAVE_METAL) || defined(HAVE_VULKAN) { - NSView *v = [CocoaView get]; - v.wantsLayer = YES; - v.layer = CAMetalLayer.layer; + MetalView *v = [MetalView new]; + v.paused = YES; + v.enableSetNeedsDisplay = NO; _renderView = v; } #endif @@ -280,7 +279,7 @@ static char** waiting_argv; _renderView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; _renderView.frame = self.window.contentView.bounds; - + [self.window.contentView addSubview:_renderView]; [self.window makeFirstResponder:_renderView]; } @@ -293,18 +292,6 @@ static char** waiting_argv; return _renderView; } -- (id)delegate { - return _delegate; -} - -- (void)setDelegate:(id)delegate { - _delegate = delegate; -} - -- (id)viewHandle { - return nil; -} - - (bool)hasFocus { return [NSApp isActive]; }