feat(metal): Add native rotation support for Metal driver

* fix crash when frame or frame size is 0
This commit is contained in:
Stuart Carnie 2018-11-29 22:04:43 -07:00
parent 1caf10e1e9
commit 0e295716b9
No known key found for this signature in database
GPG Key ID: 848D9C9718D78B4F
8 changed files with 118 additions and 28 deletions

View File

@ -76,6 +76,7 @@ typedef struct
/*! @brief end commits the command buffer */
- (void)end;
- (void)setRotation:(unsigned)rotation;
- (bool)readBackBuffer:(uint8_t *)buffer;
@end

View File

@ -53,10 +53,16 @@
id<MTLRenderPipelineState> _states[GFX_MAX_SHADERS][2];
id<MTLRenderPipelineState> _clearState;
Uniforms _uniforms;
bool _captureEnabled;
id<MTLTexture> _backBuffer;
unsigned _rotation;
matrix_float4x4 _mvp_no_rot;
matrix_float4x4 _mvp;
Uniforms _uniforms;
Uniforms _uniformsNoRotate;
}
- (instancetype)initWithDevice:(id<MTLDevice>)d
@ -75,6 +81,11 @@
_commandQueue = [_device newCommandQueue];
_clearColor = MTLClearColorMake(0, 0, 0, 1);
_uniforms.projectionMatrix = matrix_proj_ortho(0, 1, 0, 1);
_rotation = 0;
[self setRotation:0];
_mvp_no_rot = matrix_proj_ortho(0, 1, 0, 1);
_mvp = matrix_proj_ortho(0, 1, 0, 1);
{
MTLSamplerDescriptor *sd = [MTLSamplerDescriptor new];
@ -130,6 +141,27 @@
return &_uniforms;
}
- (void)setRotation:(unsigned)rotation
{
_rotation = 270 * rotation;
/* Calculate projection. */
_mvp_no_rot = matrix_proj_ortho(0, 1, 0, 1);
bool allow_rotate = true;
if (!allow_rotate)
{
_mvp = _mvp_no_rot;
return;
}
matrix_float4x4 rot = matrix_rotate_z((float)(M_PI * _rotation / 180.0f));
_mvp = simd_mul(rot, _mvp_no_rot);
_uniforms.projectionMatrix = _mvp;
_uniformsNoRotate.projectionMatrix = _mvp_no_rot;
}
- (void)setDisplaySyncEnabled:(bool)displaySyncEnabled
{
#if TARGET_OS_OSX

View File

@ -55,6 +55,7 @@ typedef NS_ENUM(NSUInteger, RTextureFilter)
};
extern matrix_float4x4 matrix_proj_ortho(float left, float right, float top, float bottom);
extern matrix_float4x4 matrix_rotate_z(float rot);
extern matrix_float4x4 make_matrix_float4x4(const float *v);
#endif /* RendererCommon_h */

View File

@ -86,3 +86,17 @@ matrix_float4x4 matrix_proj_ortho(float left, float right, float top, float bott
matrix_float4x4 mat = {P, Q, R, S};
return mat;
}
matrix_float4x4 matrix_rotate_z(float rot)
{
float cz, sz;
__sincosf(rot, &sz, &cz);
simd_float4 P = simd_make_float4(cz, -sz, 0, 0);
simd_float4 Q = simd_make_float4(sz, cz, 0, 0);
simd_float4 R = simd_make_float4( 0, 0, 1, 0);
simd_float4 S = simd_make_float4( 0, 0, 0, 1);
matrix_float4x4 mat = {P, Q, R, S};
return mat;
}

View File

@ -96,6 +96,8 @@ extern MTLPixelFormat SelectOptimalPixelFormat(MTLPixelFormat fmt);
/*! @brief setNeedsResize triggers a display resize */
- (void)setNeedsResize;
- (void)setViewportWidth:(unsigned)width height:(unsigned)height forceFull:(BOOL)forceFull allowRotate:(BOOL)allowRotate;
- (void)setRotation:(unsigned)rotation;
@end

View File

@ -216,21 +216,19 @@
return YES;
}
- (void)_updateUniforms
- (void)setViewportWidth:(unsigned)width height:(unsigned)height forceFull:(BOOL)forceFull allowRotate:(BOOL)allowRotate
{
_uniforms.projectionMatrix = matrix_proj_ortho(0, 1, 0, 1);
}
- (void)_updateViewport:(CGSize)size
{
RARCH_LOG("[Metal]: _updateViewport size %.0fx%.0f\n", size.width, size.height);
#if 0
RARCH_LOG("[Metal]: setViewportWidth size %dx%d\n", width, height);
#endif
_viewport->full_width = (unsigned int)size.width;
_viewport->full_height = (unsigned int)size.height;
_viewport->full_width = width;
_viewport->full_height = height;
video_driver_set_size(&_viewport->full_width, &_viewport->full_height);
_layer.drawableSize = size;
video_driver_update_viewport(_viewport, NO, _keepAspect);
_layer.drawableSize = CGSizeMake(width, height);
video_driver_update_viewport(_viewport, forceFull, _keepAspect);
// update matrix
_context.viewport = _viewport;
_viewportMVP.outputSize = simd_make_float2(_viewport->full_width, _viewport->full_height);
@ -256,8 +254,10 @@
[self _beginFrame];
_frameView.frameCount = frameCount;
_frameView.size = CGSizeMake(width, height);
[_frameView updateFrame:data pitch:pitch];
if (data && width && height) {
_frameView.size = CGSizeMake(width, height);
[_frameView updateFrame:data pitch:pitch];
}
[self _drawViews:video_info];
@ -277,7 +277,7 @@
id<MTLRenderCommandEncoder> rce = _context.rce;
[rce pushDebugGroup:@"overlay"];
[rce setRenderPipelineState:[_context getStockShader:VIDEO_SHADER_STOCK_BLEND blend:YES]];
[rce setVertexBytes:&_uniforms length:sizeof(_uniforms) atIndex:BufferIndexUniforms];
[rce setVertexBytes:_context.uniforms length:sizeof(*_context.uniforms) atIndex:BufferIndexUniforms];
[rce setFragmentSamplerState:_samplerStateLinear atIndex:SamplerIndexDraw];
[_overlay drawWithEncoder:rce];
[rce popDebugGroup];
@ -338,7 +338,6 @@
_context.viewport = _viewport;
}
[_context begin];
[self _updateUniforms];
}
- (void)_drawViews:(video_frame_info_t *)video_info
@ -351,7 +350,7 @@
if ((_frameView.drawState & ViewDrawStateEncoder) != 0)
{
[rce setVertexBytes:&_uniforms length:sizeof(_uniforms) atIndex:BufferIndexUniforms];
[rce setVertexBytes:_context.uniforms length:sizeof(*_context.uniforms) atIndex:BufferIndexUniforms];
[rce setRenderPipelineState:_t_pipelineStateNoAlpha];
if (_frameView.filter == RTextureFilterNearest)
{
@ -410,6 +409,11 @@
// TODO(sgc): resize all drawables
}
- (void)setRotation:(unsigned)rotation
{
[_context setRotation:rotation];
}
- (Uniforms *)viewportMVP
{
return &_viewportMVP;
@ -419,7 +423,7 @@
- (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size
{
[self _updateViewport:size];
[self setViewportWidth:(unsigned int)size.width height:(unsigned int)size.height forceFull:NO allowRotate:YES];
}
- (void)drawInMTKView:(MTKView *)view
@ -897,7 +901,7 @@ typedef struct MTLALIGN(16)
rce = [cb renderCommandEncoderWithDescriptor:rpd];
}
#if METAL_DEBUG
#if DEBUG && METAL_DEBUG
rce.label = [NSString stringWithFormat:@"pass %d", i];
#endif
@ -1126,6 +1130,8 @@ typedef struct MTLALIGN(16)
texture_t *source = &_engine.frame.texture[0];
for (unsigned i = 0; i < shader->passes; source = &_engine.pass[i++].rt)
{
matrix_float4x4 *mvp = (i == shader->passes-1) ? &_context.uniforms->projectionMatrix : &_engine.mvp;
/* clang-format off */
semantics_map_t semantics_map = {
{
@ -1154,7 +1160,7 @@ typedef struct MTLALIGN(16)
&_engine.luts[0].size_data, sizeof(*_engine.luts)},
},
{
&_engine.mvp, /* MVP */
mvp, /* MVP */
&_engine.pass[i].rt.size_data, /* OutputSize */
&_engine.frame.output_size, /* FinalViewportSize */
&_engine.pass[i].frame_count, /* FrameCount */

View File

@ -151,16 +151,22 @@ static void metal_free(void *data)
static void metal_set_viewport(void *data, unsigned viewport_width,
unsigned viewport_height, bool force_full, bool allow_rotate)
{
#if 0
RARCH_LOG("[Metal]: set_viewport size: %dx%d full: %s rotate: %s\n",
viewport_width, viewport_height,
force_full ? "YES" : "NO",
allow_rotate ? "YES" : "NO");
#endif
MetalDriver *md = (__bridge MetalDriver *)data;
if (md == nil) {
return;
}
[md setViewportWidth:viewport_width height:viewport_height forceFull:force_full allowRotate:allow_rotate];
}
static void metal_set_rotation(void *data, unsigned rotation)
{
MetalDriver *md = (__bridge MetalDriver *)data;
if (md == nil) {
return;
}
[md setRotation:rotation];
}
static void metal_viewport_info(void *data, struct video_viewport *vp)

View File

@ -88,6 +88,17 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
05132C6621A74D7A00379846 /* ozone_texture.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ozone_texture.c; sourceTree = "<group>"; };
05132C6721A74D7B00379846 /* ozone_theme.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ozone_theme.h; sourceTree = "<group>"; };
05132C6821A74D7B00379846 /* ozone.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ozone.h; sourceTree = "<group>"; };
05132C6921A74D7B00379846 /* ozone_entries.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ozone_entries.c; sourceTree = "<group>"; };
05132C6A21A74D7B00379846 /* ozone.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ozone.c; sourceTree = "<group>"; };
05132C6B21A74D7B00379846 /* ozone_theme.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ozone_theme.c; sourceTree = "<group>"; };
05132C6C21A74D7B00379846 /* ozone_sidebar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ozone_sidebar.c; sourceTree = "<group>"; };
05132C6D21A74D7B00379846 /* ozone_sidebar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ozone_sidebar.h; sourceTree = "<group>"; };
05132C6E21A74D7B00379846 /* ozone_display.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ozone_display.c; sourceTree = "<group>"; };
05132C6F21A74D7B00379846 /* ozone_texture.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ozone_texture.h; sourceTree = "<group>"; };
05132C7021A74D7B00379846 /* ozone_display.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ozone_display.h; sourceTree = "<group>"; };
05269A6120ABF20500C29F1E /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; };
05366512213F8BE5007E7EA0 /* thumbnailpackdownload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thumbnailpackdownload.cpp; sourceTree = "<group>"; };
05366513213F8BE5007E7EA0 /* ui_qt_application.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ui_qt_application.cpp; sourceTree = "<group>"; };
@ -514,7 +525,6 @@
05D7753320A5678300646447 /* griffin_cpp.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = griffin_cpp.cpp; path = ../../griffin/griffin_cpp.cpp; sourceTree = "<group>"; };
05D7753420A5678400646447 /* griffin_glslang.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = griffin_glslang.cpp; path = ../../griffin/griffin_glslang.cpp; sourceTree = "<group>"; };
05EFAFC22191D64200D27059 /* stripes.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = stripes.c; sourceTree = "<group>"; };
05EFAFC32191D64200D27059 /* ozone.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ozone.c; sourceTree = "<group>"; };
05F2872F20F2BEEA00632D47 /* task_autodetect.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_autodetect.c; sourceTree = "<group>"; };
05F2873020F2BEEA00632D47 /* task_netplay_find_content.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_netplay_find_content.c; sourceTree = "<group>"; };
05F2873120F2BEEA00632D47 /* task_netplay_nat_traversal.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_netplay_nat_traversal.c; sourceTree = "<group>"; };
@ -610,6 +620,24 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
05132C6521A74D5100379846 /* ozone */ = {
isa = PBXGroup;
children = (
05132C6E21A74D7B00379846 /* ozone_display.c */,
05132C7021A74D7B00379846 /* ozone_display.h */,
05132C6921A74D7B00379846 /* ozone_entries.c */,
05132C6C21A74D7B00379846 /* ozone_sidebar.c */,
05132C6D21A74D7B00379846 /* ozone_sidebar.h */,
05132C6621A74D7A00379846 /* ozone_texture.c */,
05132C6F21A74D7B00379846 /* ozone_texture.h */,
05132C6B21A74D7B00379846 /* ozone_theme.c */,
05132C6721A74D7B00379846 /* ozone_theme.h */,
05132C6A21A74D7B00379846 /* ozone.c */,
05132C6821A74D7B00379846 /* ozone.h */,
);
path = ozone;
sourceTree = "<group>";
};
05366511213F8BE5007E7EA0 /* qt */ = {
isa = PBXGroup;
children = (
@ -801,12 +829,12 @@
isa = PBXGroup;
children = (
05A8C53520DB72F000FF7857 /* nuklear */,
05132C6521A74D5100379846 /* ozone */,
05A8C54020DB72F000FF7857 /* materialui.c */,
05A8C53420DB72F000FF7857 /* menu_generic.c */,
05A8C53320DB72F000FF7857 /* menu_generic.h */,
05A8C53D20DB72F000FF7857 /* nuklear.c */,
05A8C53E20DB72F000FF7857 /* null.c */,
05EFAFC32191D64200D27059 /* ozone.c */,
05A8C53C20DB72F000FF7857 /* rgui.c */,
05EFAFC22191D64200D27059 /* stripes.c */,
05A8C53220DB72F000FF7857 /* xmb.c */,