Merge pull request #6912 from stuartcarnie/sgc-metal

More metal resize, stability improvements
This commit is contained in:
Twinaphex 2018-06-24 00:28:22 +02:00 committed by GitHub
commit c10aab9830
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 357 additions and 214 deletions

View File

@ -21,10 +21,10 @@
{
_context = c;
NSError *err = nil;
_filters[RPixelFormatBGRA4Unorm] = [Filter newFilterWithFunctionName:@"convert_abgr4444_to_bgra8888"
_filters[RPixelFormatBGRA4Unorm] = [Filter newFilterWithFunctionName:@"convert_bgra4444_to_bgra8888"
device:c.device library:c.library
error:&err];
_filters[RPixelFormatB5G6R5Unorm] = [Filter newFilterWithFunctionName:@"convert_bgr565_to_bgra8888"
_filters[RPixelFormatB5G6R5Unorm] = [Filter newFilterWithFunctionName:@"convert_rgb565_to_bgra8888"
device:c.device
library:c.library
error:&err];

View File

@ -12,23 +12,7 @@ using namespace metal;
#pragma mark - filter kernels
kernel void convert_abgr4444_to_bgra8888_tex(texture2d<ushort, access::read> in [[ texture(0) ]],
texture2d<half, access::write> out [[ texture(1) ]],
uint2 gid [[ thread_position_in_grid ]])
{
ushort pix = in.read(gid).r;
uchar4 pix2 = uchar4(
extract_bits(pix, 4, 4),
extract_bits(pix, 8, 4),
extract_bits(pix, 12, 4),
extract_bits(pix, 0, 4)
);
out.write(half4(pix2) / 15.0, gid);
}
kernel void convert_abgr4444_to_bgra8888(device uint16_t * in [[ buffer(0) ]],
kernel void convert_bgra4444_to_bgra8888(device uint16_t * in [[ buffer(0) ]],
texture2d<half, access::write> out [[ texture(0) ]],
uint id [[ thread_position_in_grid ]])
{
@ -46,7 +30,7 @@ kernel void convert_abgr4444_to_bgra8888(device uint16_t * in [[ b
out.write(half4(pix2) / 15.0, uint2(xpos, ypos));
}
kernel void convert_bgr565_to_bgra8888(device uint16_t * in [[ buffer(0) ]],
kernel void convert_rgb565_to_bgra8888(device uint16_t * in [[ buffer(0) ]],
texture2d<half, access::write> out [[ texture(0) ]],
uint id [[ thread_position_in_grid ]])
{

View File

@ -12,7 +12,6 @@
#import "Context.h"
#import "PixelConverter.h"
@class ViewDescriptor;
@protocol View;
@interface Renderer : NSObject

View File

@ -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<View> v in _views) {
if (!v.visible) continue;
if ([v respondsToSelector:@selector(prepareFrame:)]) {
[v prepareFrame:_context];
if ([v respondsToSelector:@selector(drawWithContext:)]) {
[v drawWithContext:_context];
}
}
id<CAMetalDrawable> drawable = _context.nextDrawable;
_t_rpd.colorAttachments[0].texture = drawable.texture;
id<MTLRenderCommandEncoder> rce = [cb renderCommandEncoderWithDescriptor:_t_rpd];
[rce setVertexBytes:&_uniforms length:sizeof(_uniforms) atIndex:BufferIndexUniforms];
BOOL pendingDraws = NO;
for (id<View> 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<CAMetalDrawable> drawable = _context.nextDrawable;
_t_rpd.colorAttachments[0].texture = drawable.texture;
id<MTLRenderCommandEncoder> rce = [cb renderCommandEncoderWithDescriptor:_t_rpd];
[rce setVertexBytes:&_uniforms length:sizeof(_uniforms) atIndex:BufferIndexUniforms];
for (id<View> 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<MTLCommandBuffer> _) {
dispatch_semaphore_signal(inflight);
}];
[cb presentDrawable:drawable];
[cb presentDrawable:_context.nextDrawable];
[_context end];
}

View File

@ -11,33 +11,34 @@
#import <Foundation/Foundation.h>
// 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 */

View File

@ -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<MTLRenderCommandEncoder>)rce;
- (void)updateFrame:(void const *)src pitch:(NSUInteger)pitch;
@end

View File

@ -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];
}

View File

@ -10,6 +10,15 @@
#import <Foundation/Foundation.h>
#import <Metal/Metal.h>
typedef NS_ENUM(NSInteger, ViewDrawState)
{
ViewDrawStateNone = 0x00,
ViewDrawStateContext = 0x01,
ViewDrawStateEncoder = 0x02,
ViewDrawStateAll = 0x03,
};
@protocol View<NSObject>
@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<MTLRenderCommandEncoder>)rce;
@end

View File

@ -9,6 +9,7 @@
#define METAL_COMMON_H__
#import <Metal/Metal.h>
#import <MetalKit/MetalKit.h>
#import "metal/metal_common.h"
#include <retro_common_api.h>
@ -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<View>
@ -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<PlatformDelegate>
@interface MetalDriver : NSObject<MTKViewDelegate>
@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

View File

@ -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<MTLRenderCommandEncoder>)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<MTLDevice> 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<MTLLibrary> 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;
}
}

View File

@ -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;

View File

@ -44,6 +44,22 @@
/* Begin PBXFileReference section */
05269A6120ABF20500C29F1E /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; };
0538874D20DDD5C600769232 /* dxgi_common.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dxgi_common.c; sourceTree = "<group>"; };
0538874E20DDD5C600769232 /* dxgi_common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dxgi_common.h; sourceTree = "<group>"; };
0538875120DE11D200769232 /* retro_common_api.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_common_api.h; sourceTree = "<group>"; };
0538875220DE11D200769232 /* retro_environment.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_environment.h; sourceTree = "<group>"; };
0538875320DE11D200769232 /* retro_timers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_timers.h; sourceTree = "<group>"; };
0538875420DE11D200769232 /* retro_dirent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_dirent.h; sourceTree = "<group>"; };
0538875520DE11D300769232 /* retro_common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_common.h; sourceTree = "<group>"; };
0538875620DE11D300769232 /* retro_inline.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_inline.h; sourceTree = "<group>"; };
0538875720DE11D300769232 /* retro_assert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_assert.h; sourceTree = "<group>"; };
0538875820DE11D300769232 /* retro_endianness.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_endianness.h; sourceTree = "<group>"; };
0538875920DE11D300769232 /* libretro.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libretro.h; sourceTree = "<group>"; };
055312AB20DE130A00C4D7F4 /* gl_capabilities.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = gl_capabilities.c; sourceTree = "<group>"; };
055312AD20DE130A00C4D7F4 /* scaler_int.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = scaler_int.c; sourceTree = "<group>"; };
055312AE20DE130A00C4D7F4 /* pixconv.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pixconv.c; sourceTree = "<group>"; };
055312AF20DE130A00C4D7F4 /* scaler_filter.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = scaler_filter.c; sourceTree = "<group>"; };
055312B020DE130A00C4D7F4 /* scaler.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = scaler.c; sourceTree = "<group>"; };
05A8C51B20DB72F000FF7857 /* menu_shader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = menu_shader.h; sourceTree = "<group>"; };
05A8C51D20DB72F000FF7857 /* menu_cbs_get_value.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = menu_cbs_get_value.c; sourceTree = "<group>"; };
05A8C51E20DB72F000FF7857 /* menu_cbs_sublabel.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = menu_cbs_sublabel.c; sourceTree = "<group>"; };
@ -169,15 +185,7 @@
05A8C5C020DB72F000FF7857 /* ui_cocoa_window.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ui_cocoa_window.m; sourceTree = "<group>"; };
05A8C5C120DB72F000FF7857 /* ui_cocoa_application.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ui_cocoa_application.m; sourceTree = "<group>"; };
05A8C5C220DB72F000FF7857 /* cocoa_common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cocoa_common.h; sourceTree = "<group>"; };
05A8C5C420DB72F000FF7857 /* ui_null_browser_window.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ui_null_browser_window.c; sourceTree = "<group>"; };
05A8C5C520DB72F000FF7857 /* ui_null_msg_window.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ui_null_msg_window.c; sourceTree = "<group>"; };
05A8C5C620DB72F000FF7857 /* ui_null_application.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ui_null_application.c; sourceTree = "<group>"; };
05A8C5C720DB72F000FF7857 /* ui_null_window.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ui_null_window.c; sourceTree = "<group>"; };
05A8C5C820DB72F000FF7857 /* ui_qt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ui_qt.h; sourceTree = "<group>"; };
05A8C5CA20DB72F000FF7857 /* ui_win32_application.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ui_win32_application.c; sourceTree = "<group>"; };
05A8C5CB20DB72F000FF7857 /* ui_win32_msg_window.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ui_win32_msg_window.c; sourceTree = "<group>"; };
05A8C5CC20DB72F000FF7857 /* ui_win32_browser_window.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ui_win32_browser_window.c; sourceTree = "<group>"; };
05A8C5CD20DB72F000FF7857 /* ui_win32_window.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ui_win32_window.c; sourceTree = "<group>"; };
05A8C5CE20DB72F000FF7857 /* ui_cocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ui_cocoa.h; sourceTree = "<group>"; };
05A8C5CF20DB72F000FF7857 /* ui_cocoatouch.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ui_cocoatouch.m; sourceTree = "<group>"; };
05A8C5D020DB72F000FF7857 /* ui_qt.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ui_qt.cpp; sourceTree = "<group>"; };
@ -389,9 +397,56 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0538874F20DE117B00769232 /* libretro-common */ = {
isa = PBXGroup;
children = (
0538875020DE11A800769232 /* include */,
055312AA20DE130A00C4D7F4 /* gfx */,
);
name = "libretro-common";
path = "../../libretro-common";
sourceTree = "<group>";
};
0538875020DE11A800769232 /* include */ = {
isa = PBXGroup;
children = (
0538875920DE11D300769232 /* libretro.h */,
0538875720DE11D300769232 /* retro_assert.h */,
0538875120DE11D200769232 /* retro_common_api.h */,
0538875520DE11D300769232 /* retro_common.h */,
0538875420DE11D200769232 /* retro_dirent.h */,
0538875820DE11D300769232 /* retro_endianness.h */,
0538875220DE11D200769232 /* retro_environment.h */,
0538875620DE11D300769232 /* retro_inline.h */,
0538875320DE11D200769232 /* retro_timers.h */,
);
path = include;
sourceTree = "<group>";
};
055312AA20DE130A00C4D7F4 /* gfx */ = {
isa = PBXGroup;
children = (
055312AC20DE130A00C4D7F4 /* scaler */,
055312AB20DE130A00C4D7F4 /* gl_capabilities.c */,
);
path = gfx;
sourceTree = "<group>";
};
055312AC20DE130A00C4D7F4 /* scaler */ = {
isa = PBXGroup;
children = (
055312AD20DE130A00C4D7F4 /* scaler_int.c */,
055312AE20DE130A00C4D7F4 /* pixconv.c */,
055312AF20DE130A00C4D7F4 /* scaler_filter.c */,
055312B020DE130A00C4D7F4 /* scaler.c */,
);
path = scaler;
sourceTree = "<group>";
};
05A8C51920DB72C200FF7857 /* Sources */ = {
isa = PBXGroup;
children = (
0538874F20DE117B00769232 /* libretro-common */,
05A8C59520DB72F000FF7857 /* frontend */,
05A8C5D420DB72F000FF7857 /* gfx */,
05A8C57120DB72F000FF7857 /* intl */,
@ -602,8 +657,6 @@
isa = PBXGroup;
children = (
05A8C5BB20DB72F000FF7857 /* cocoa */,
05A8C5C320DB72F000FF7857 /* null */,
05A8C5C920DB72F000FF7857 /* win32 */,
05A8C5CE20DB72F000FF7857 /* ui_cocoa.h */,
05A8C5BA20DB72F000FF7857 /* ui_cocoa.m */,
05A8C5CF20DB72F000FF7857 /* ui_cocoatouch.m */,
@ -620,39 +673,17 @@
05A8C5BB20DB72F000FF7857 /* cocoa */ = {
isa = PBXGroup;
children = (
05A8C5BC20DB72F000FF7857 /* ui_cocoa_msg_window.m */,
05A8C5C220DB72F000FF7857 /* cocoa_common.h */,
05A8C5BD20DB72F000FF7857 /* cocoa_common.m */,
05A8C5BE20DB72F000FF7857 /* cocoatouch_menu.m */,
05A8C5BF20DB72F000FF7857 /* ui_cocoa_browser_window.m */,
05A8C5C020DB72F000FF7857 /* ui_cocoa_window.m */,
05A8C5C120DB72F000FF7857 /* ui_cocoa_application.m */,
05A8C5C220DB72F000FF7857 /* cocoa_common.h */,
05A8C5BF20DB72F000FF7857 /* ui_cocoa_browser_window.m */,
05A8C5BC20DB72F000FF7857 /* ui_cocoa_msg_window.m */,
05A8C5C020DB72F000FF7857 /* ui_cocoa_window.m */,
);
path = cocoa;
sourceTree = "<group>";
};
05A8C5C320DB72F000FF7857 /* null */ = {
isa = PBXGroup;
children = (
05A8C5C420DB72F000FF7857 /* ui_null_browser_window.c */,
05A8C5C520DB72F000FF7857 /* ui_null_msg_window.c */,
05A8C5C620DB72F000FF7857 /* ui_null_application.c */,
05A8C5C720DB72F000FF7857 /* ui_null_window.c */,
);
path = null;
sourceTree = "<group>";
};
05A8C5C920DB72F000FF7857 /* win32 */ = {
isa = PBXGroup;
children = (
05A8C5CA20DB72F000FF7857 /* ui_win32_application.c */,
05A8C5CB20DB72F000FF7857 /* ui_win32_msg_window.c */,
05A8C5CC20DB72F000FF7857 /* ui_win32_browser_window.c */,
05A8C5CD20DB72F000FF7857 /* ui_win32_window.c */,
);
path = win32;
sourceTree = "<group>";
};
05A8C5D420DB72F000FF7857 /* gfx */ = {
isa = PBXGroup;
children = (
@ -810,6 +841,8 @@
05A8C77020DB72F100FF7857 /* d3d_common.h */,
05A8C77720DB72F100FF7857 /* d3d10_common.c */,
05A8C76320DB72F100FF7857 /* d3d10_common.h */,
0538874D20DDD5C600769232 /* dxgi_common.c */,
0538874E20DDD5C600769232 /* dxgi_common.h */,
05A8C75D20DB72F100FF7857 /* gl_common.c */,
05A8C76F20DB72F100FF7857 /* gl_common.h */,
05A8C74420DB72F100FF7857 /* metal_common.h */,
@ -823,26 +856,26 @@
05A8C74520DB72F100FF7857 /* metal */ = {
isa = PBXGroup;
children = (
05A8C74B20DB72F100FF7857 /* Context.h */,
05A8C75320DB72F100FF7857 /* Context.m */,
05A8C75720DB72F100FF7857 /* Filter.h */,
05A8C75020DB72F100FF7857 /* Filter.m */,
05A8C74820DB72F100FF7857 /* metal_common.h */,
05A8C74620DB72F100FF7857 /* MetalRenderer.h */,
05A8C74720DB72F100FF7857 /* PixelConverter.h */,
05A8C74820DB72F100FF7857 /* metal_common.h */,
05A8C74920DB72F100FF7857 /* TexturedView.h */,
05A8C74A20DB72F100FF7857 /* Renderer.h */,
05A8C74B20DB72F100FF7857 /* Context.h */,
05A8C74C20DB72F100FF7857 /* RendererCommon.h */,
05A8C74D20DB72F100FF7857 /* PixelConverter+private.h */,
05A8C74E20DB72F100FF7857 /* Shaders.metal */,
05A8C74F20DB72F100FF7857 /* View.h */,
05A8C75020DB72F100FF7857 /* Filter.m */,
05A8C75120DB72F100FF7857 /* ShaderTypes.h */,
05A8C75220DB72F100FF7857 /* PixelConverter.m */,
05A8C75320DB72F100FF7857 /* Context.m */,
05A8C75420DB72F100FF7857 /* RendererCommon.m */,
05A8C75520DB72F100FF7857 /* Renderer.m */,
05A8C75620DB72F100FF7857 /* TexturedView.m */,
05A8C75720DB72F100FF7857 /* Filter.h */,
05A8C75820DB72F100FF7857 /* View.m */,
05A8C75920DB72F100FF7857 /* PixelConverter.metal */,
05A8C74D20DB72F100FF7857 /* PixelConverter+private.h */,
05A8C74A20DB72F100FF7857 /* Renderer.h */,
05A8C75520DB72F100FF7857 /* Renderer.m */,
05A8C74C20DB72F100FF7857 /* RendererCommon.h */,
05A8C75420DB72F100FF7857 /* RendererCommon.m */,
05A8C74E20DB72F100FF7857 /* Shaders.metal */,
05A8C75120DB72F100FF7857 /* ShaderTypes.h */,
05A8C74920DB72F100FF7857 /* TexturedView.h */,
05A8C75620DB72F100FF7857 /* TexturedView.m */,
05A8C74F20DB72F100FF7857 /* View.h */,
05A8C75820DB72F100FF7857 /* View.m */,
);
path = metal;
sourceTree = "<group>";

View File

@ -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 <MetalKit/MetalKit.h>
@interface MetalView : MTKView
@end
#endif
@protocol ApplePlatform
@property (readwrite,retain) id<PlatformDelegate> 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;

View File

@ -19,9 +19,6 @@
#include "cocoa_common.h"
#ifdef HAVE_COCOA
#include "../ui_cocoa.h"
#ifdef HAVE_VULKAN
#import <QuartzCore/CAMetalLayer.h>
#endif
#endif
#include <retro_assert.h>
@ -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();
}

View File

@ -53,7 +53,6 @@ id<ApplePlatform> apple_platform;
NSWindow* _window;
apple_view_type_t _vt;
NSView* _renderView;
id<PlatformDelegate> _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<PlatformDelegate>)delegate {
_delegate = delegate;
}
- (id)viewHandle {
return nil;
}
- (bool)hasFocus {
return [NSApp isActive];
}