(Metal common) Cleanups

This commit is contained in:
libretroadmin 2022-10-01 21:41:32 +02:00
parent 86dccbf1d6
commit 13ac88c9df

View File

@ -57,21 +57,12 @@
@implementation MetalView @implementation MetalView
#if !defined(HAVE_COCOATOUCH) #if !defined(HAVE_COCOATOUCH)
- (void)keyDown:(NSEvent*)theEvent - (void)keyDown:(NSEvent*)theEvent { }
{
}
#endif #endif
/* Stop the annoying sound when pressing a key. */ /* Stop the annoying sound when pressing a key. */
- (BOOL)acceptsFirstResponder - (BOOL)acceptsFirstResponder { return YES; }
{ - (BOOL)isFlipped { return YES; }
return YES;
}
- (BOOL)isFlipped
{
return YES;
}
@end @end
#pragma mark - private categories #pragma mark - private categories
@ -110,14 +101,14 @@
CAMetalLayer *_layer; CAMetalLayer *_layer;
// render target layer state /* Render target layer state */
id<MTLRenderPipelineState> _t_pipelineState; id<MTLRenderPipelineState> _t_pipelineState;
id<MTLRenderPipelineState> _t_pipelineStateNoAlpha; id<MTLRenderPipelineState> _t_pipelineStateNoAlpha;
id<MTLSamplerState> _samplerStateLinear; id<MTLSamplerState> _samplerStateLinear;
id<MTLSamplerState> _samplerStateNearest; id<MTLSamplerState> _samplerStateNearest;
// other state /* other state */
Uniforms _viewportMVP; Uniforms _viewportMVP;
} }
@ -127,22 +118,20 @@
{ {
if (self = [super init]) if (self = [super init])
{ {
_device = MTLCreateSystemDefaultDevice(); _device = MTLCreateSystemDefaultDevice();
MetalView *view = (MetalView *)apple_platform.renderView; MetalView *view = (MetalView *)apple_platform.renderView;
view.device = _device; view.device = _device;
view.delegate = self; view.delegate = self;
_layer = (CAMetalLayer *)view.layer; _layer = (CAMetalLayer *)view.layer;
if (![self _initMetal]) if (![self _initMetal])
{
return nil; return nil;
}
_video = *video; _video = *video;
_viewport = (video_viewport_t *)calloc(1, sizeof(video_viewport_t)); _viewport = (video_viewport_t *)calloc(1, sizeof(video_viewport_t));
_viewportMVP.projectionMatrix = matrix_proj_ortho(0, 1, 0, 1); _viewportMVP.projectionMatrix = matrix_proj_ortho(0, 1, 0, 1);
_keepAspect = _video.force_aspect; _keepAspect = _video.force_aspect;
gfx_ctx_mode_t mode = { gfx_ctx_mode_t mode = {
.width = _video.width, .width = _video.width,
@ -155,33 +144,31 @@
// 0 indicates full screen, so we'll use the view's dimensions, which should already be full screen // 0 indicates full screen, so we'll use the view's dimensions, which should already be full screen
// If this turns out to be the wrong assumption, we can use NSScreen to query the dimensions // If this turns out to be the wrong assumption, we can use NSScreen to query the dimensions
CGSize size = view.frame.size; CGSize size = view.frame.size;
mode.width = (unsigned int)size.width; mode.width = (unsigned int)size.width;
mode.height = (unsigned int)size.height; mode.height = (unsigned int)size.height;
} }
[apple_platform setVideoMode:mode]; [apple_platform setVideoMode:mode];
*input = NULL; *input = NULL;
*inputData = NULL; *inputData = NULL;
/* graphics display driver */
_display = [[MenuDisplay alloc] initWithContext:_context];
/* menu view */
_menu = [[MetalMenu alloc] initWithContext:_context];
// graphics display driver /* Framebuffer view */
_display = [[MenuDisplay alloc] initWithContext:_context];
// menu view
_menu = [[MetalMenu alloc] initWithContext:_context];
// frame buffer view
{ {
ViewDescriptor *vd = [ViewDescriptor new]; ViewDescriptor *vd = [ViewDescriptor new];
vd.format = _video.rgb32 ? RPixelFormatBGRX8Unorm : RPixelFormatB5G6R5Unorm; vd.format = _video.rgb32 ? RPixelFormatBGRX8Unorm : RPixelFormatB5G6R5Unorm;
vd.size = CGSizeMake(video->width, video->height); vd.size = CGSizeMake(video->width, video->height);
vd.filter = _video.smooth ? RTextureFilterLinear : RTextureFilterNearest; vd.filter = _video.smooth ? RTextureFilterLinear : RTextureFilterNearest;
_frameView = [[FrameView alloc] initWithDescriptor:vd context:_context]; _frameView = [[FrameView alloc] initWithDescriptor:vd context:_context];
_frameView.viewport = _viewport; _frameView.viewport = _viewport;
[_frameView setFilteringIndex:0 smooth:video->smooth]; [_frameView setFilteringIndex:0 smooth:video->smooth];
} }
// overlay view /* Overlay view */
_overlay = [[Overlay alloc] initWithContext:_context]; _overlay = [[Overlay alloc] initWithContext:_context];
font_driver_init_osd((__bridge void *)self, font_driver_init_osd((__bridge void *)self,
@ -211,30 +198,33 @@
library:_library]; library:_library];
{ {
MTLVertexDescriptor *vd = [MTLVertexDescriptor new];
vd.attributes[0].offset = 0;
vd.attributes[0].format = MTLVertexFormatFloat3;
vd.attributes[1].offset = offsetof(Vertex, texCoord);
vd.attributes[1].format = MTLVertexFormatFloat2;
vd.layouts[0].stride = sizeof(Vertex);
MTLRenderPipelineDescriptor *psd = [MTLRenderPipelineDescriptor new];
psd.label = @"Pipeline+Alpha";
MTLRenderPipelineColorAttachmentDescriptor *ca = psd.colorAttachments[0];
ca.pixelFormat = _layer.pixelFormat;
ca.blendingEnabled = YES;
ca.sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
ca.sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
ca.destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
ca.destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
psd.sampleCount = 1;
psd.vertexDescriptor = vd;
psd.vertexFunction = [_library newFunctionWithName:@"basic_vertex_proj_tex"];
psd.fragmentFunction = [_library newFunctionWithName:@"basic_fragment_proj_tex"];
NSError *err; NSError *err;
MTLRenderPipelineDescriptor *psd;
MTLRenderPipelineColorAttachmentDescriptor *ca;
MTLVertexDescriptor *vd = [MTLVertexDescriptor new];
vd.attributes[0].offset = 0;
vd.attributes[0].format = MTLVertexFormatFloat3;
vd.attributes[1].offset = offsetof(Vertex, texCoord);
vd.attributes[1].format = MTLVertexFormatFloat2;
vd.layouts[0].stride = sizeof(Vertex);
psd = [MTLRenderPipelineDescriptor new];
psd.label = @"Pipeline+Alpha";
ca = psd.colorAttachments[0];
ca.pixelFormat = _layer.pixelFormat;
ca.blendingEnabled = YES;
ca.sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
ca.sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
ca.destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
ca.destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
psd.sampleCount = 1;
psd.vertexDescriptor = vd;
psd.vertexFunction = [_library newFunctionWithName:@"basic_vertex_proj_tex"];
psd.fragmentFunction = [_library newFunctionWithName:@"basic_fragment_proj_tex"];
_t_pipelineState = [_device newRenderPipelineStateWithDescriptor:psd error:&err]; _t_pipelineState = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
if (err != nil) if (err != nil)
{ {
@ -242,8 +232,8 @@
return NO; return NO;
} }
psd.label = @"Pipeline+No Alpha"; psd.label = @"Pipeline+No Alpha";
ca.blendingEnabled = NO; ca.blendingEnabled = NO;
_t_pipelineStateNoAlpha = [_device newRenderPipelineStateWithDescriptor:psd error:&err]; _t_pipelineStateNoAlpha = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
if (err != nil) if (err != nil)
{ {
@ -254,11 +244,11 @@
{ {
MTLSamplerDescriptor *sd = [MTLSamplerDescriptor new]; MTLSamplerDescriptor *sd = [MTLSamplerDescriptor new];
_samplerStateNearest = [_device newSamplerStateWithDescriptor:sd]; _samplerStateNearest = [_device newSamplerStateWithDescriptor:sd];
sd.minFilter = MTLSamplerMinMagFilterLinear; sd.minFilter = MTLSamplerMinMagFilterLinear;
sd.magFilter = MTLSamplerMinMagFilterLinear; sd.magFilter = MTLSamplerMinMagFilterLinear;
_samplerStateLinear = [_device newSamplerStateWithDescriptor:sd]; _samplerStateLinear = [_device newSamplerStateWithDescriptor:sd];
} }
return YES; return YES;
@ -266,24 +256,18 @@
- (void)setViewportWidth:(unsigned)width height:(unsigned)height forceFull:(BOOL)forceFull allowRotate:(BOOL)allowRotate - (void)setViewportWidth:(unsigned)width height:(unsigned)height forceFull:(BOOL)forceFull allowRotate:(BOOL)allowRotate
{ {
_viewport->full_width = width; _viewport->full_width = width;
_viewport->full_height = height; _viewport->full_height = height;
video_driver_set_size(_viewport->full_width, _viewport->full_height); video_driver_set_size(_viewport->full_width, _viewport->full_height);
_layer.drawableSize = CGSizeMake(width, height); _layer.drawableSize = CGSizeMake(width, height);
video_driver_update_viewport(_viewport, forceFull, _keepAspect); video_driver_update_viewport(_viewport, forceFull, _keepAspect);
_context.viewport = _viewport; /* Update matrix */
// update matrix
_context.viewport = _viewport;
_viewportMVP.outputSize = simd_make_float2(_viewport->full_width, _viewport->full_height); _viewportMVP.outputSize = simd_make_float2(_viewport->full_width, _viewport->full_height);
} }
#pragma mark - video #pragma mark - video
- (void)setVideo:(const video_info_t *)video - (void)setVideo:(const video_info_t *)video { }
{
}
- (bool)renderFrame:(const void *)frame - (bool)renderFrame:(const void *)frame
data:(void*)data data:(void*)data
@ -427,13 +411,9 @@
[rce setVertexBytes:_context.uniforms length:sizeof(*_context.uniforms) atIndex:BufferIndexUniforms]; [rce setVertexBytes:_context.uniforms length:sizeof(*_context.uniforms) atIndex:BufferIndexUniforms];
[rce setRenderPipelineState:_t_pipelineStateNoAlpha]; [rce setRenderPipelineState:_t_pipelineStateNoAlpha];
if (_frameView.filter == RTextureFilterNearest) if (_frameView.filter == RTextureFilterNearest)
{
[rce setFragmentSamplerState:_samplerStateNearest atIndex:SamplerIndexDraw]; [rce setFragmentSamplerState:_samplerStateNearest atIndex:SamplerIndexDraw];
}
else else
{
[rce setFragmentSamplerState:_samplerStateLinear atIndex:SamplerIndexDraw]; [rce setFragmentSamplerState:_samplerStateLinear atIndex:SamplerIndexDraw];
}
[_frameView drawWithEncoder:rce]; [_frameView drawWithEncoder:rce];
} }
[rce popDebugGroup]; [rce popDebugGroup];
@ -455,13 +435,9 @@
[rce setVertexBytes:_context.uniforms length:sizeof(*_context.uniforms) atIndex:BufferIndexUniforms]; [rce setVertexBytes:_context.uniforms length:sizeof(*_context.uniforms) atIndex:BufferIndexUniforms];
[rce setRenderPipelineState:_t_pipelineState]; [rce setRenderPipelineState:_t_pipelineState];
if (_menu.view.filter == RTextureFilterNearest) if (_menu.view.filter == RTextureFilterNearest)
{
[rce setFragmentSamplerState:_samplerStateNearest atIndex:SamplerIndexDraw]; [rce setFragmentSamplerState:_samplerStateNearest atIndex:SamplerIndexDraw];
}
else else
{
[rce setFragmentSamplerState:_samplerStateLinear atIndex:SamplerIndexDraw]; [rce setFragmentSamplerState:_samplerStateLinear atIndex:SamplerIndexDraw];
}
[_menu.view drawWithEncoder:rce]; [_menu.view drawWithEncoder:rce];
[rce popDebugGroup]; [rce popDebugGroup];
} }
@ -476,31 +452,16 @@
#endif #endif
} }
- (void)_endFrame - (void)_endFrame { [_context end]; }
{ /* TODO/FIXME (sgc): resize*/
[_context end]; - (void)setNeedsResize { }
} - (void)setRotation:(unsigned)rotation { [_context setRotation:rotation]; }
- (Uniforms *)viewportMVP { return &_viewportMVP; }
- (void)setNeedsResize
{
// TODO(sgc): resize all drawables
}
- (void)setRotation:(unsigned)rotation
{
[_context setRotation:rotation];
}
- (Uniforms *)viewportMVP
{
return &_viewportMVP;
}
#pragma mark - MTKViewDelegate #pragma mark - MTKViewDelegate
- (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size - (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size
{ {
NSLog(@"mtkView drawableSizeWillChange to: %f x %f",size.width,size.height);
#ifdef HAVE_COCOATOUCH #ifdef HAVE_COCOATOUCH
CGFloat scale = [[UIScreen mainScreen] scale]; CGFloat scale = [[UIScreen mainScreen] scale];
[self setViewportWidth:(unsigned int)view.bounds.size.width*scale height:(unsigned int)view.bounds.size.height*scale forceFull:NO allowRotate:YES]; [self setViewportWidth:(unsigned int)view.bounds.size.width*scale height:(unsigned int)view.bounds.size.height*scale forceFull:NO allowRotate:YES];
@ -509,11 +470,7 @@
#endif #endif
} }
- (void)drawInMTKView:(MTKView *)view - (void)drawInMTKView:(MTKView *)view { }
{
}
@end @end
@implementation MetalMenu @implementation MetalMenu
@ -526,28 +483,21 @@
- (instancetype)initWithContext:(Context *)context - (instancetype)initWithContext:(Context *)context
{ {
if (self = [super init]) if (self = [super init])
{
_context = context; _context = context;
}
return self; return self;
} }
- (bool)hasFrame - (bool)hasFrame { return _view != nil; }
{
return _view != nil;
}
- (void)setEnabled:(bool)enabled - (void)setEnabled:(bool)enabled
{ {
if (_enabled == enabled) return; if (_enabled == enabled)
_enabled = enabled; return;
_enabled = enabled;
_view.visible = enabled; _view.visible = enabled;
} }
- (bool)enabled - (bool)enabled { return _enabled; }
{
return _enabled;
}
- (void)updateWidth:(int)width - (void)updateWidth:(int)width
height:(int)height height:(int)height
@ -561,19 +511,17 @@
if (!(CGSizeEqualToSize(_view.size, size) && if (!(CGSizeEqualToSize(_view.size, size) &&
_view.format == format && _view.format == format &&
_view.filter == filter)) _view.filter == filter))
{
_view = nil; _view = nil;
}
} }
if (!_view) if (!_view)
{ {
ViewDescriptor *vd = [ViewDescriptor new]; ViewDescriptor *vd = [ViewDescriptor new];
vd.format = format; vd.format = format;
vd.filter = filter; vd.filter = filter;
vd.size = size; vd.size = size;
_view = [[TexturedView alloc] initWithDescriptor:vd context:_context]; _view = [[TexturedView alloc] initWithDescriptor:vd context:_context];
_view.visible = _enabled; _view.visible = _enabled;
} }
} }
@ -632,14 +580,14 @@ typedef struct MTLALIGN(16)
@implementation FrameView @implementation FrameView
{ {
Context *_context; Context *_context;
id<MTLTexture> _texture; // final render texture id<MTLTexture> _texture; /* final render texture */
Vertex _v[4]; Vertex _v[4];
VertexSlang _vertex[4]; VertexSlang _vertex[4];
CGSize _size; // size of view in pixels CGSize _size; /* size of view in pixels */
CGRect _frame; CGRect _frame;
NSUInteger _bpp; NSUInteger _bpp;
id<MTLTexture> _src; // src texture id<MTLTexture> _src; /* source texture */
bool _srcDirty; bool _srcDirty;
id<MTLSamplerState> _samplers[RARCH_FILTER_MAX][RARCH_WRAP_MAX]; id<MTLSamplerState> _samplers[RARCH_FILTER_MAX][RARCH_WRAP_MAX];
@ -657,28 +605,24 @@ typedef struct MTLALIGN(16)
self = [super init]; self = [super init];
if (self) if (self)
{ {
_context = c; _context = c;
_format = d.format; _format = d.format;
_bpp = RPixelFormatToBPP(_format); _bpp = RPixelFormatToBPP(_format);
_filter = d.filter; _filter = d.filter;
if (_format == RPixelFormatBGRA8Unorm || _format == RPixelFormatBGRX8Unorm) if (_format == RPixelFormatBGRA8Unorm || _format == RPixelFormatBGRX8Unorm)
{ _drawState = ViewDrawStateEncoder;
_drawState = ViewDrawStateEncoder;
}
else else
{ _drawState = ViewDrawStateAll;
_drawState = ViewDrawStateAll; _visible = YES;
} _engine.mvp = matrix_proj_ortho(0, 1, 0, 1);
_visible = YES;
_engine.mvp = matrix_proj_ortho(0, 1, 0, 1);
[self _initSamplers]; [self _initSamplers];
self.size = d.size; self.size = d.size;
self.frame = CGRectMake(0, 0, 1, 1); self.frame = CGRectMake(0, 0, 1, 1);
resize_render_targets = YES; resize_render_targets = YES;
// init slang vertex buffer /* Initialize slang vertex buffer */
VertexSlang v[4] = { VertexSlang v[4] = {
{simd_make_float4(0, 1, 0, 1), simd_make_float2(0, 1)}, {simd_make_float4(0, 1, 0, 1), simd_make_float2(0, 1)},
{simd_make_float4(1, 1, 0, 1), simd_make_float2(1, 1)}, {simd_make_float4(1, 1, 0, 1), simd_make_float2(1, 1)},
{simd_make_float4(0, 0, 0, 1), simd_make_float2(0, 0)}, {simd_make_float4(0, 0, 0, 1), simd_make_float2(0, 0)},
@ -691,10 +635,11 @@ typedef struct MTLALIGN(16)
- (void)_initSamplers - (void)_initSamplers
{ {
int i;
MTLSamplerDescriptor *sd = [MTLSamplerDescriptor new]; MTLSamplerDescriptor *sd = [MTLSamplerDescriptor new];
/* Initialize samplers */ /* Initialize samplers */
for (unsigned i = 0; i < RARCH_WRAP_MAX; i++) for (i = 0; i < RARCH_WRAP_MAX; i++)
{ {
switch (i) switch (i)
{ {
@ -721,25 +666,26 @@ typedef struct MTLALIGN(16)
default: default:
continue; continue;
} }
sd.tAddressMode = sd.sAddressMode; sd.tAddressMode = sd.sAddressMode;
sd.rAddressMode = sd.sAddressMode; sd.rAddressMode = sd.sAddressMode;
sd.minFilter = MTLSamplerMinMagFilterLinear; sd.minFilter = MTLSamplerMinMagFilterLinear;
sd.magFilter = MTLSamplerMinMagFilterLinear; sd.magFilter = MTLSamplerMinMagFilterLinear;
id<MTLSamplerState> ss = [_context.device newSamplerStateWithDescriptor:sd]; id<MTLSamplerState> ss = [_context.device newSamplerStateWithDescriptor:sd];
_samplers[RARCH_FILTER_LINEAR][i] = ss; _samplers[RARCH_FILTER_LINEAR][i] = ss;
sd.minFilter = MTLSamplerMinMagFilterNearest; sd.minFilter = MTLSamplerMinMagFilterNearest;
sd.magFilter = MTLSamplerMinMagFilterNearest; sd.magFilter = MTLSamplerMinMagFilterNearest;
ss = [_context.device newSamplerStateWithDescriptor:sd]; ss = [_context.device newSamplerStateWithDescriptor:sd];
_samplers[RARCH_FILTER_NEAREST][i] = ss; _samplers[RARCH_FILTER_NEAREST][i] = ss;
} }
} }
- (void)setFilteringIndex:(int)index smooth:(bool)smooth - (void)setFilteringIndex:(int)index smooth:(bool)smooth
{ {
for (int i = 0; i < RARCH_WRAP_MAX; i++) int i;
for (i = 0; i < RARCH_WRAP_MAX; i++)
{ {
if (smooth) if (smooth)
_samplers[RARCH_FILTER_UNSPEC][i] = _samplers[RARCH_FILTER_LINEAR][i]; _samplers[RARCH_FILTER_UNSPEC][i] = _samplers[RARCH_FILTER_LINEAR][i];
@ -753,11 +699,11 @@ typedef struct MTLALIGN(16)
if (CGSizeEqualToSize(_size, size)) if (CGSizeEqualToSize(_size, size))
return; return;
_size = size; _size = size;
resize_render_targets = YES; resize_render_targets = YES;
if (_format != RPixelFormatBGRA8Unorm && _format != RPixelFormatBGRX8Unorm) if ( _format != RPixelFormatBGRA8Unorm
&& _format != RPixelFormatBGRX8Unorm)
{ {
MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR16Uint MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR16Uint
width:(NSUInteger)size.width width:(NSUInteger)size.width
@ -767,26 +713,21 @@ typedef struct MTLALIGN(16)
} }
} }
- (CGSize)size - (CGSize)size { return _size; }
{
return _size;
}
- (void)setFrame:(CGRect)frame - (void)setFrame:(CGRect)frame
{ {
if (CGRectEqualToRect(_frame, frame)) if (CGRectEqualToRect(_frame, frame))
return; return;
_frame = frame; /* update vertices */
CGPoint o = frame.origin;
CGSize s = frame.size;
// update vertices CGFloat l = o.x;
CGPoint o = frame.origin; CGFloat t = o.y;
CGSize s = frame.size; CGFloat r = o.x + s.width;
CGFloat b = o.y + s.height;
CGFloat l = o.x;
CGFloat t = o.y;
CGFloat r = o.x + s.width;
CGFloat b = o.y + s.height;
Vertex v[4] = { Vertex v[4] = {
{simd_make_float3(l, b, 0), simd_make_float2(0, 1)}, {simd_make_float3(l, b, 0), simd_make_float2(0, 1)},
@ -794,13 +735,12 @@ typedef struct MTLALIGN(16)
{simd_make_float3(l, t, 0), simd_make_float2(0, 0)}, {simd_make_float3(l, t, 0), simd_make_float2(0, 0)},
{simd_make_float3(r, t, 0), simd_make_float2(1, 0)}, {simd_make_float3(r, t, 0), simd_make_float2(1, 0)},
}; };
_frame = frame;
memcpy(_v, v, sizeof(_v)); memcpy(_v, v, sizeof(_v));
} }
- (CGRect)frame - (CGRect)frame { return _frame; }
{
return _frame;
}
- (void)_convertFormat - (void)_convertFormat
{ {
@ -837,13 +777,13 @@ typedef struct MTLALIGN(16)
} }
/* either no history, or we moved a texture of a different size in the front slot */ /* either no history, or we moved a texture of a different size in the front slot */
if (_engine.frame.texture[0].size_data.x != _size.width || if ( _engine.frame.texture[0].size_data.x != _size.width
_engine.frame.texture[0].size_data.y != _size.height) || _engine.frame.texture[0].size_data.y != _size.height)
{ {
MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
width:(NSUInteger)_size.width width:(NSUInteger)_size.width
height:(NSUInteger)_size.height height:(NSUInteger)_size.height
mipmapped:false]; mipmapped:false];
td.usage = MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite; td.usage = MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite;
[self _initTexture:&_engine.frame.texture[0] withDescriptor:td]; [self _initTexture:&_engine.frame.texture[0] withDescriptor:td];
} }
@ -851,13 +791,14 @@ typedef struct MTLALIGN(16)
- (bool)readViewport:(uint8_t *)buffer isIdle:(bool)isIdle - (bool)readViewport:(uint8_t *)buffer isIdle:(bool)isIdle
{ {
bool res;
bool enabled = _context.captureEnabled; bool enabled = _context.captureEnabled;
if (!enabled) if (!enabled)
_context.captureEnabled = YES; _context.captureEnabled = YES;
video_driver_cached_frame(); video_driver_cached_frame();
bool res = [_context readBackBuffer:buffer]; res = [_context readBackBuffer:buffer];
if (!enabled) if (!enabled)
_context.captureEnabled = NO; _context.captureEnabled = NO;
@ -869,7 +810,7 @@ typedef struct MTLALIGN(16)
{ {
if (_shader && (_engine.frame.output_size.x != _viewport->width || if (_shader && (_engine.frame.output_size.x != _viewport->width ||
_engine.frame.output_size.y != _viewport->height)) _engine.frame.output_size.y != _viewport->height))
resize_render_targets = YES; resize_render_targets = YES;
_engine.frame.viewport.originX = _viewport->x; _engine.frame.viewport.originX = _viewport->x;
_engine.frame.viewport.originY = _viewport->y; _engine.frame.viewport.originY = _viewport->y;
@ -887,7 +828,8 @@ typedef struct MTLALIGN(16)
[self _updateHistory]; [self _updateHistory];
if (_format == RPixelFormatBGRA8Unorm || _format == RPixelFormatBGRX8Unorm) if ( _format == RPixelFormatBGRA8Unorm
|| _format == RPixelFormatBGRX8Unorm)
{ {
id<MTLTexture> tex = _engine.frame.texture[0].view; id<MTLTexture> tex = _engine.frame.texture[0].view;
[tex replaceRegion:MTLRegionMake2D(0, 0, (NSUInteger)_size.width, (NSUInteger)_size.height) [tex replaceRegion:MTLRegionMake2D(0, 0, (NSUInteger)_size.width, (NSUInteger)_size.height)
@ -916,10 +858,12 @@ typedef struct MTLALIGN(16)
{ {
int i; int i;
MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
width:(NSUInteger)_size.width width:(NSUInteger)_size.width
height:(NSUInteger)_size.height height:(NSUInteger)_size.height
mipmapped:false]; mipmapped:false];
td.usage = MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite | MTLTextureUsageRenderTarget; td.usage = MTLTextureUsageShaderRead
| MTLTextureUsageShaderWrite
| MTLTextureUsageRenderTarget;
for (i = 0; i < _shader->history_size + 1; i++) for (i = 0; i < _shader->history_size + 1; i++)
[self _initTexture:&_engine.frame.texture[i] withDescriptor:td]; [self _initTexture:&_engine.frame.texture[i] withDescriptor:td];
@ -939,7 +883,7 @@ typedef struct MTLALIGN(16)
- (void)drawWithContext:(Context *)ctx - (void)drawWithContext:(Context *)ctx
{ {
unsigned i; int i;
_texture = _engine.frame.texture[0].view; _texture = _engine.frame.texture[0].view;
[self _convertFormat]; [self _convertFormat];
@ -959,20 +903,21 @@ typedef struct MTLALIGN(16)
id<MTLCommandBuffer> cb = ctx.blitCommandBuffer; id<MTLCommandBuffer> cb = ctx.blitCommandBuffer;
[cb pushDebugGroup:@"shaders"]; [cb pushDebugGroup:@"shaders"];
MTLRenderPassDescriptor *rpd = [MTLRenderPassDescriptor new]; MTLRenderPassDescriptor *rpd = [MTLRenderPassDescriptor new];
rpd.colorAttachments[0].loadAction = MTLLoadActionDontCare; rpd.colorAttachments[0].loadAction = MTLLoadActionDontCare;
rpd.colorAttachments[0].storeAction = MTLStoreActionStore; rpd.colorAttachments[0].storeAction = MTLStoreActionStore;
for (unsigned i = 0; i < _shader->passes; i++) for (i = 0; i < _shader->passes; i++)
{ {
id<MTLRenderCommandEncoder> rce = nil; int j;
__unsafe_unretained id<MTLTexture> textures[SLANG_NUM_BINDINGS] = {NULL};
id<MTLSamplerState> samplers[SLANG_NUM_BINDINGS] = {NULL};
id<MTLRenderCommandEncoder> rce = nil;
BOOL backBuffer = (_engine.pass[i].rt.view == nil); BOOL backBuffer = (_engine.pass[i].rt.view == nil);
if (backBuffer) if (backBuffer)
{
rce = _context.rce; rce = _context.rce;
}
else else
{ {
rpd.colorAttachments[0].texture = _engine.pass[i].rt.view; rpd.colorAttachments[0].texture = _engine.pass[i].rt.view;
@ -996,7 +941,7 @@ typedef struct MTLALIGN(16)
_engine.pass[i].frame_direction = 1; _engine.pass[i].frame_direction = 1;
#endif #endif
for (unsigned j = 0; j < SLANG_CBUFFER_MAX; j++) for (j = 0; j < SLANG_CBUFFER_MAX; j++)
{ {
id<MTLBuffer> buffer = _engine.pass[i].buffers[j]; id<MTLBuffer> buffer = _engine.pass[i].buffers[j];
cbuffer_sem_t *buffer_sem = &_engine.pass[i].semantics.cbuffers[j]; cbuffer_sem_t *buffer_sem = &_engine.pass[i].semantics.cbuffers[j];
@ -1024,9 +969,6 @@ typedef struct MTLALIGN(16)
} }
} }
__unsafe_unretained id<MTLTexture> textures[SLANG_NUM_BINDINGS] = {NULL};
id<MTLSamplerState> samplers[SLANG_NUM_BINDINGS] = {NULL};
texture_sem_t *texture_sem = _engine.pass[i].semantics.textures; texture_sem_t *texture_sem = _engine.pass[i].semantics.textures;
while (texture_sem->stage_mask) while (texture_sem->stage_mask)
{ {
@ -1038,13 +980,9 @@ typedef struct MTLALIGN(16)
} }
if (backBuffer) if (backBuffer)
{
[rce setViewport:_engine.frame.viewport]; [rce setViewport:_engine.frame.viewport];
}
else else
{
[rce setViewport:_engine.pass[i].viewport]; [rce setViewport:_engine.pass[i].viewport];
}
[rce setFragmentTextures:textures withRange:NSMakeRange(0, SLANG_NUM_BINDINGS)]; [rce setFragmentTextures:textures withRange:NSMakeRange(0, SLANG_NUM_BINDINGS)];
[rce setFragmentSamplerStates:samplers withRange:NSMakeRange(0, SLANG_NUM_BINDINGS)]; [rce setFragmentSamplerStates:samplers withRange:NSMakeRange(0, SLANG_NUM_BINDINGS)];
@ -1052,9 +990,7 @@ typedef struct MTLALIGN(16)
[rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4]; [rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
if (!backBuffer) if (!backBuffer)
{
[rce endEncoding]; [rce endEncoding];
}
_texture = _engine.pass[i].rt.view; _texture = _engine.pass[i].rt.view;
} }
@ -1069,10 +1005,12 @@ typedef struct MTLALIGN(16)
- (void)_updateRenderTargets - (void)_updateRenderTargets
{ {
int i;
NSUInteger width, height;
if (!_shader || !resize_render_targets) return; if (!_shader || !resize_render_targets) return;
// release existing targets // release existing targets
for (int i = 0; i < _shader->passes; i++) for (i = 0; i < _shader->passes; i++)
{ {
STRUCT_ASSIGN(_engine.pass[i].rt.view, nil); STRUCT_ASSIGN(_engine.pass[i].rt.view, nil);
STRUCT_ASSIGN(_engine.pass[i].feedback.view, nil); STRUCT_ASSIGN(_engine.pass[i].feedback.view, nil);
@ -1080,9 +1018,10 @@ typedef struct MTLALIGN(16)
memset(&_engine.pass[i].feedback, 0, sizeof(_engine.pass[i].feedback)); memset(&_engine.pass[i].feedback, 0, sizeof(_engine.pass[i].feedback));
} }
NSUInteger width = (NSUInteger)_size.width, height = (NSUInteger)_size.height; width = (NSUInteger)_size.width;
height = (NSUInteger)_size.height;
for (unsigned i = 0; i < _shader->passes; i++) for (i = 0; i < _shader->passes; i++)
{ {
struct video_shader_pass *shader_pass = &_shader->pass[i]; struct video_shader_pass *shader_pass = &_shader->pass[i];
@ -1149,17 +1088,15 @@ typedef struct MTLALIGN(16)
_engine.pass[i].viewport.zfar = 1.0; _engine.pass[i].viewport.zfar = 1.0;
MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:fmt MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:fmt
width:width width:width height:height mipmapped:false];
height:height
mipmapped:false];
td.storageMode = MTLStorageModePrivate; td.storageMode = MTLStorageModePrivate;
td.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget; td.usage = MTLTextureUsageShaderRead
| MTLTextureUsageRenderTarget;
[self _initTexture:&_engine.pass[i].rt withDescriptor:td]; [self _initTexture:&_engine.pass[i].rt withDescriptor:td];
if (shader_pass->feedback) if (shader_pass->feedback)
{
[self _initTexture:&_engine.pass[i].feedback withDescriptor:td]; [self _initTexture:&_engine.pass[i].feedback withDescriptor:td];
}
} }
else else
{ {
@ -1175,11 +1112,13 @@ typedef struct MTLALIGN(16)
- (void)_freeVideoShader:(struct video_shader *)shader - (void)_freeVideoShader:(struct video_shader *)shader
{ {
int i;
if (!shader) if (!shader)
return; return;
for (int i = 0; i < GFX_MAX_SHADERS; i++) for (i = 0; i < GFX_MAX_SHADERS; i++)
{ {
int j;
STRUCT_ASSIGN(_engine.pass[i].rt.view, nil); STRUCT_ASSIGN(_engine.pass[i].rt.view, nil);
STRUCT_ASSIGN(_engine.pass[i].feedback.view, nil); STRUCT_ASSIGN(_engine.pass[i].feedback.view, nil);
memset(&_engine.pass[i].rt, 0, sizeof(_engine.pass[i].rt)); memset(&_engine.pass[i].rt, 0, sizeof(_engine.pass[i].rt));
@ -1187,13 +1126,13 @@ typedef struct MTLALIGN(16)
STRUCT_ASSIGN(_engine.pass[i]._state, nil); STRUCT_ASSIGN(_engine.pass[i]._state, nil);
for (unsigned j = 0; j < SLANG_CBUFFER_MAX; j++) for (j = 0; j < SLANG_CBUFFER_MAX; j++)
{ {
STRUCT_ASSIGN(_engine.pass[i].buffers[j], nil); STRUCT_ASSIGN(_engine.pass[i].buffers[j], nil);
} }
} }
for (int i = 0; i < GFX_MAX_TEXTURES; i++) for (i = 0; i < GFX_MAX_TEXTURES; i++)
{ {
STRUCT_ASSIGN(_engine.luts[i].view, nil); STRUCT_ASSIGN(_engine.luts[i].view, nil);
} }
@ -1204,7 +1143,7 @@ typedef struct MTLALIGN(16)
- (BOOL)setShaderFromPath:(NSString *)path - (BOOL)setShaderFromPath:(NSString *)path
{ {
[self _freeVideoShader:_shader]; [self _freeVideoShader:_shader];
_shader = nil; _shader = nil;
struct video_shader *shader = (struct video_shader *)calloc(1, sizeof(*shader)); struct video_shader *shader = (struct video_shader *)calloc(1, sizeof(*shader));
settings_t *settings = config_get_ptr(); settings_t *settings = config_get_ptr();
@ -1213,7 +1152,7 @@ typedef struct MTLALIGN(16)
@try @try
{ {
unsigned i; int i;
texture_t *source = NULL; texture_t *source = NULL;
if (!video_shader_load_preset_into_shader(path.UTF8String, shader)) if (!video_shader_load_preset_into_shader(path.UTF8String, shader))
return NO; return NO;
@ -1265,9 +1204,9 @@ typedef struct MTLALIGN(16)
return NO; return NO;
#ifdef DEBUG #ifdef DEBUG
bool save_msl = true; bool save_msl = true;
#else #else
bool save_msl = false; bool save_msl = false;
#endif #endif
NSString *vs_src = [NSString stringWithUTF8String:shader->pass[i].source.string.vertex]; NSString *vs_src = [NSString stringWithUTF8String:shader->pass[i].source.string.vertex];
NSString *fs_src = [NSString stringWithUTF8String:shader->pass[i].source.string.fragment]; NSString *fs_src = [NSString stringWithUTF8String:shader->pass[i].source.string.fragment];
@ -1388,24 +1327,26 @@ typedef struct MTLALIGN(16)
free(shader->pass[i].source.string.vertex); free(shader->pass[i].source.string.vertex);
free(shader->pass[i].source.string.fragment); free(shader->pass[i].source.string.fragment);
shader->pass[i].source.string.vertex = NULL; shader->pass[i].source.string.vertex = NULL;
shader->pass[i].source.string.fragment = NULL; shader->pass[i].source.string.fragment = NULL;
} }
} }
for (i = 0; i < shader->luts; i++) for (i = 0; i < shader->luts; i++)
{ {
struct texture_image image = {0}; struct texture_image image;
image.pixels = NULL;
image.width = 0;
image.height = 0;
image.supports_rgba = true; image.supports_rgba = true;
if (!image_texture_load(&image, shader->lut[i].path)) if (!image_texture_load(&image, shader->lut[i].path))
return NO; return NO;
MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
width:image.width width:image.width height:image.height
height:image.height mipmapped:shader->lut[i].mipmap];
mipmapped:shader->lut[i].mipmap]; td.usage = MTLTextureUsageShaderRead;
td.usage = MTLTextureUsageShaderRead;
[self _initTexture:&_engine.luts[i] withDescriptor:td]; [self _initTexture:&_engine.luts[i] withDescriptor:td];
[_engine.luts[i].view replaceRegion:MTLRegionMake2D(0, 0, image.width, image.height) [_engine.luts[i].view replaceRegion:MTLRegionMake2D(0, 0, image.width, image.height)
@ -1421,13 +1362,11 @@ typedef struct MTLALIGN(16)
@finally @finally
{ {
if (shader) if (shader)
{
[self _freeVideoShader:shader]; [self _freeVideoShader:shader];
}
} }
resize_render_targets = YES; resize_render_targets = YES;
init_history = YES; init_history = YES;
return YES; return YES;
} }
@ -1445,25 +1384,22 @@ typedef struct MTLALIGN(16)
- (instancetype)initWithContext:(Context *)context - (instancetype)initWithContext:(Context *)context
{ {
if (self = [super init]) if (self = [super init])
{
_context = context; _context = context;
}
return self; return self;
} }
- (bool)loadImages:(const struct texture_image *)images count:(NSUInteger)count - (bool)loadImages:(const struct texture_image *)images count:(NSUInteger)count
{ {
int i;
[self _freeImages]; [self _freeImages];
_images = [NSMutableArray arrayWithCapacity:count]; _images = [NSMutableArray arrayWithCapacity:count];
NSUInteger needed = sizeof(SpriteVertex) * count * 4; NSUInteger needed = sizeof(SpriteVertex) * count * 4;
if (!_vert || _vert.length < needed) if (!_vert || _vert.length < needed)
{
_vert = [_context.device newBufferWithLength:needed options:PLATFORM_METAL_RESOURCE_STORAGE_MODE]; _vert = [_context.device newBufferWithLength:needed options:PLATFORM_METAL_RESOURCE_STORAGE_MODE];
}
for (NSUInteger i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
_images[i] = [_context newTexture:images[i] mipmapped:NO]; _images[i] = [_context newTexture:images[i] mipmapped:NO];
[self updateVertexX:0 y:0 w:1 h:1 index:i]; [self updateVertexX:0 y:0 w:1 h:1 index:i];
@ -1478,6 +1414,8 @@ typedef struct MTLALIGN(16)
- (void)drawWithEncoder:(id<MTLRenderCommandEncoder>)rce - (void)drawWithEncoder:(id<MTLRenderCommandEncoder>)rce
{ {
int i;
NSUInteger count;
#if !defined(HAVE_COCOATOUCH) #if !defined(HAVE_COCOATOUCH)
if (_vertDirty) if (_vertDirty)
{ {
@ -1486,8 +1424,8 @@ typedef struct MTLALIGN(16)
} }
#endif #endif
NSUInteger count = _images.count; count = _images.count;
for (NSUInteger i = 0; i < count; ++i) for (i = 0; i < count; ++i)
{ {
NSUInteger offset = sizeof(SpriteVertex) * 4 * i; NSUInteger offset = sizeof(SpriteVertex) * 4 * i;
[rce setVertexBuffer:_vert offset:offset atIndex:BufferIndexPositions]; [rce setVertexBuffer:_vert offset:offset atIndex:BufferIndexPositions];
@ -1505,12 +1443,12 @@ typedef struct MTLALIGN(16)
- (void)_updateColorRed:(float)r green:(float)g blue:(float)b alpha:(float)a index:(NSUInteger)index - (void)_updateColorRed:(float)r green:(float)g blue:(float)b alpha:(float)a index:(NSUInteger)index
{ {
simd_float4 color = simd_make_float4(r, g, b, a); simd_float4 color = simd_make_float4(r, g, b, a);
SpriteVertex *pv = [self _getForIndex:index]; SpriteVertex *pv = [self _getForIndex:index];
pv[0].color = color; pv[0].color = color;
pv[1].color = color; pv[1].color = color;
pv[2].color = color; pv[2].color = color;
pv[3].color = color; pv[3].color = color;
_vertDirty = YES; _vertDirty = YES;
} }
- (void)updateAlpha:(float)alpha index:(NSUInteger)index - (void)updateAlpha:(float)alpha index:(NSUInteger)index
@ -1521,27 +1459,24 @@ typedef struct MTLALIGN(16)
- (void)updateVertexX:(float)x y:(float)y w:(float)w h:(float)h index:(NSUInteger)index - (void)updateVertexX:(float)x y:(float)y w:(float)w h:(float)h index:(NSUInteger)index
{ {
SpriteVertex *pv = [self _getForIndex:index]; SpriteVertex *pv = [self _getForIndex:index];
pv[0].position = simd_make_float2(x, y); pv[0].position = simd_make_float2(x, y);
pv[1].position = simd_make_float2(x + w, y); pv[1].position = simd_make_float2(x + w, y);
pv[2].position = simd_make_float2(x, y + h); pv[2].position = simd_make_float2(x, y + h);
pv[3].position = simd_make_float2(x + w, y + h); pv[3].position = simd_make_float2(x + w, y + h);
_vertDirty = YES; _vertDirty = YES;
} }
- (void)updateTextureCoordsX:(float)x y:(float)y w:(float)w h:(float)h index:(NSUInteger)index - (void)updateTextureCoordsX:(float)x y:(float)y w:(float)w h:(float)h index:(NSUInteger)index
{ {
SpriteVertex *pv = [self _getForIndex:index]; SpriteVertex *pv = [self _getForIndex:index];
pv[0].texCoord = simd_make_float2(x, y); pv[0].texCoord = simd_make_float2(x, y);
pv[1].texCoord = simd_make_float2(x + w, y); pv[1].texCoord = simd_make_float2(x + w, y);
pv[2].texCoord = simd_make_float2(x, y + h); pv[2].texCoord = simd_make_float2(x, y + h);
pv[3].texCoord = simd_make_float2(x + w, y + h); pv[3].texCoord = simd_make_float2(x + w, y + h);
_vertDirty = YES; _vertDirty = YES;
} }
- (void)_freeImages - (void)_freeImages { _images = nil; }
{
_images = nil;
}
@end @end