Merge pull request #7174 from stuartcarnie/sgc-metal

Fix crashes for metal; buffer overflow in xmb; Metal fullscreen issue
This commit is contained in:
Twinaphex 2018-09-02 21:55:10 +02:00 committed by GitHub
commit 6463f7005b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 130 additions and 133 deletions

View File

@ -347,9 +347,15 @@ static void frontend_darwin_get_environment_settings(int *argc, char *argv[],
#endif
strlcat(home_dir_buf, "/RetroArch", sizeof(home_dir_buf));
#ifdef HAVE_METAL
fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SHADER],
home_dir_buf, "shaders_slang",
sizeof(g_defaults.dirs[DEFAULT_DIR_SHADER]));
#else
fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SHADER],
home_dir_buf, "shaders_glsl",
sizeof(g_defaults.dirs[DEFAULT_DIR_SHADER]));
#endif
#if TARGET_OS_IPHONE
int major, minor;
get_ios_version(&major, &minor);

View File

@ -52,7 +52,7 @@ typedef struct
- (Texture *)newTexture:(struct texture_image)image filter:(enum texture_filter_type)filter;
- (id<MTLTexture>)newTexture:(struct texture_image)image mipmapped:(bool)mipmapped;
- (void)convertFormat:(RPixelFormat)fmt from:(id<MTLBuffer>)src to:(id<MTLTexture>)dst;
- (void)convertFormat:(RPixelFormat)fmt from:(id<MTLTexture>)src to:(id<MTLTexture>)dst;
- (id<MTLRenderPipelineState>)getStockShader:(int)index blend:(bool)blend;
/*! @brief resets the viewport for the main render encoder to the drawable size */

View File

@ -65,7 +65,9 @@
_inflightSemaphore = dispatch_semaphore_create(MAX_INFLIGHT);
_device = d;
_layer = layer;
#if TARGET_OS_OSX
_layer.displaySyncEnabled = YES;
#endif
_library = l;
_commandQueue = [_device newCommandQueue];
_clearColor = MTLClearColorMake(0, 0, 0, 1);
@ -127,7 +129,16 @@
- (void)setDisplaySyncEnabled:(bool)displaySyncEnabled
{
#if TARGET_OS_OSX
_layer.displaySyncEnabled = displaySyncEnabled;
#endif
}
- (bool)displaySyncEnabled
{
#if TARGET_OS_OSX
return _layer.displaySyncEnabled;
#endif
}
#pragma mark - shaders
@ -154,11 +165,6 @@
return _states[index][blend ? 1 : 0];
}
- (bool)displaySyncEnabled
{
return _layer.displaySyncEnabled;
}
- (MTLVertexDescriptor *)_spriteVertexDescriptor
{
MTLVertexDescriptor *vd = [MTLVertexDescriptor new];
@ -376,7 +382,7 @@
{
assert(filter >= TEXTURE_FILTER_LINEAR && filter <= TEXTURE_FILTER_MIPMAP_NEAREST);
if (!image.pixels && !image.width && !image.height)
if (!image.pixels || !image.width || !image.height)
{
/* Create a dummy texture instead. */
#define T0 0xff000000u
@ -397,6 +403,7 @@
image.pixels = (uint32_t *)checkerboard;
image.width = 8;
image.height = 8;
filter = TEXTURE_FILTER_MIPMAP_NEAREST;
}
BOOL mipmapped = filter == TEXTURE_FILTER_MIPMAP_LINEAR || filter == TEXTURE_FILTER_MIPMAP_NEAREST;
@ -441,13 +448,13 @@
return _drawable;
}
- (void)convertFormat:(RPixelFormat)fmt from:(id<MTLBuffer>)src to:(id<MTLTexture>)dst
- (void)convertFormat:(RPixelFormat)fmt from:(id<MTLTexture>)src to:(id<MTLTexture>)dst
{
assert(dst.width * dst.height == src.length / RPixelFormatToBPP(fmt));
assert(src.width == dst.width && src.height == dst.height);
assert(fmt >= 0 && fmt < RPixelFormatCount);
Filter *conv = _filters[fmt];
assert(conv != nil);
[conv apply:self.blitCommandBuffer inBuf:src outTex:dst];
[conv apply:self.blitCommandBuffer in:src out:dst];
}
- (id<MTLCommandBuffer>)blitCommandBuffer
@ -615,6 +622,7 @@ static const NSUInteger kConstantAlignment = 4;
- (void)commitRanges
{
#if TARGET_OS_OSX
for (BufferNode *n = _head; n != nil; n = n.next)
{
if (n.allocated > 0)
@ -622,6 +630,7 @@ static const NSUInteger kConstantAlignment = 4;
[n.src didModifyRange:NSMakeRange(0, n.allocated)];
}
}
#endif
}
- (void)discard
@ -635,9 +644,15 @@ static const NSUInteger kConstantAlignment = 4;
{
bzero(range, sizeof(*range));
#if TARGET_OS_OSX
MTLResourceOptions opts = MTLResourceStorageModeManaged;
#else
MTLResourceOptions opts = MTLResourceStorageModeShared;
#endif
if (!_head)
{
_head = [[BufferNode alloc] initWithBuffer:[_device newBufferWithLength:_blockLen options:MTLResourceStorageModeManaged]];
_head = [[BufferNode alloc] initWithBuffer:[_device newBufferWithLength:_blockLen options:opts]];
_length += _blockLen;
_current = _head;
_offset = 0;
@ -659,7 +674,7 @@ static const NSUInteger kConstantAlignment = 4;
blockLen = length;
}
_current.next = [[BufferNode alloc] initWithBuffer:[_device newBufferWithLength:blockLen options:MTLResourceStorageModeManaged]];
_current.next = [[BufferNode alloc] initWithBuffer:[_device newBufferWithLength:blockLen options:opts]];
if (!_current.next)
return NO;

View File

@ -81,38 +81,32 @@ fragment half4 stock_fragment_color(FontFragmentIn in [[ stage_in ]])
#pragma mark - filter kernels
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 ]])
kernel void convert_bgra4444_to_bgra8888(texture2d<ushort, access::read> in [[ texture(0) ]],
texture2d<half, access::write> out [[ texture(1) ]],
uint2 gid [[ thread_position_in_grid ]])
{
uint16_t pix = in[id];
uchar4 pix2 = uchar4(
extract_bits(pix, 4, 4),
extract_bits(pix, 8, 4),
extract_bits(pix, 12, 4),
extract_bits(pix, 0, 4)
);
uint ypos = id / out.get_width();
uint xpos = id % out.get_width();
out.write(half4(pix2) / 15.0, uint2(xpos, ypos));
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_rgb565_to_bgra8888(device uint16_t * in [[ buffer(0) ]],
texture2d<half, access::write> out [[ texture(0) ]],
uint id [[ thread_position_in_grid ]])
kernel void convert_rgb565_to_bgra8888(texture2d<ushort, access::read> in [[ texture(0) ]],
texture2d<half, access::write> out [[ texture(1) ]],
uint2 gid [[ thread_position_in_grid ]])
{
uint16_t pix = in[id];
uchar4 pix2 = uchar4(
extract_bits(pix, 11, 5),
extract_bits(pix, 5, 6),
extract_bits(pix, 0, 5),
0xf
);
uint ypos = id / out.get_width();
uint xpos = id % out.get_width();
out.write(half4(pix2) / half4(0x1f, 0x3f, 0x1f, 0xf), uint2(xpos, ypos));
ushort pix = in.read(gid).r;
uchar4 pix2 = uchar4(
extract_bits(pix, 11, 5),
extract_bits(pix, 5, 6),
extract_bits(pix, 0, 5),
0xf
);
out.write(half4(pix2) / half4(0x1f, 0x3f, 0x1f, 0xf), gid);
}

View File

@ -16,8 +16,8 @@
CGRect _frame;
NSUInteger _bpp;
id<MTLBuffer> _pixels; // frame buffer in _srcFmt
bool _pixelsDirty;
id<MTLTexture> _src; // source texture
bool _srcDirty;
}
- (instancetype)initWithDescriptor:(ViewDescriptor *)d context:(Context *)c
@ -53,7 +53,6 @@
_size = size;
// create new texture
{
MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
width:(NSUInteger)size.width
@ -65,8 +64,11 @@
if (_format != RPixelFormatBGRA8Unorm && _format != RPixelFormatBGRX8Unorm)
{
_pixels = [_context.device newBufferWithLength:(NSUInteger)(size.width * size.height * 2)
options:MTLResourceStorageModeManaged];
MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR16Uint
width:(NSUInteger)size.width
height:(NSUInteger)size.height
mipmapped:NO];
_src = [_context.device newTextureWithDescriptor:td];
}
}
@ -112,11 +114,11 @@
if (_format == RPixelFormatBGRA8Unorm || _format == RPixelFormatBGRX8Unorm)
return;
if (!_pixelsDirty)
if (!_srcDirty)
return;
[_context convertFormat:_format from:_pixels to:_texture];
_pixelsDirty = NO;
[_context convertFormat:_format from:_src to:_texture];
_srcDirty = NO;
}
- (void)drawWithContext:(Context *)ctx
@ -141,26 +143,10 @@
}
else
{
void *dst = _pixels.contents;
size_t len = (size_t)(_bpp * _size.width);
assert(len <= pitch); // the length can't be larger?
if (len < pitch)
{
for (int i = 0; i < _size.height; i++)
{
memcpy(dst, src, len);
dst += len;
src += pitch;
}
}
else
{
memcpy(dst, src, _pixels.length);
}
[_pixels didModifyRange:NSMakeRange(0, _pixels.length)];
_pixelsDirty = YES;
[_src replaceRegion:MTLRegionMake2D(0, 0, (NSUInteger)_size.width, (NSUInteger)_size.height)
mipmapLevel:0 withBytes:src
bytesPerRow:(NSUInteger)(pitch)];
_srcDirty = YES;
}
}

View File

@ -299,30 +299,29 @@
settings_t *settings = config_get_ptr();
if (settings && settings->bools.video_msg_bgcolor_enable)
{
int msg_width =
int msg_width =
font_driver_get_message_width(NULL, msg, (unsigned)strlen(msg), 1.0f);
float x = video_info->font_msg_pos_x;
float y = 1.0f - video_info->font_msg_pos_y;
float width = msg_width / (float)_viewport->full_width;
float height =
float x = video_info->font_msg_pos_x;
float y = 1.0f - video_info->font_msg_pos_y;
float width = msg_width / (float)_viewport->full_width;
float height =
settings->floats.video_font_size / (float)_viewport->full_height;
y -= height;
float x2 = 0.005f; /* extend background around text */
float y2 = 0.005f;
x -= x2;
y -= y2;
width += x2;
height += y2;
float r = settings->uints.video_msg_bgcolor_red / 255.0f;
float g = settings->uints.video_msg_bgcolor_green / 255.0f;
float b = settings->uints.video_msg_bgcolor_blue / 255.0f;
float a = settings->floats.video_msg_bgcolor_opacity;
float x2 = 0.005f; /* extend background around text */
float y2 = 0.005f;
x -= x2;
y -= y2;
width += x2;
height += y2;
float r = settings->uints.video_msg_bgcolor_red / 255.0f;
float g = settings->uints.video_msg_bgcolor_green / 255.0f;
float b = settings->uints.video_msg_bgcolor_blue / 255.0f;
float a = settings->floats.video_msg_bgcolor_opacity;
[_context resetRenderViewport];
[_context drawQuadX:x y:y w:width h:height r:r g:g b:b a:a];
}
@ -332,7 +331,12 @@
- (void)_beginFrame
{
video_viewport_t vp = *_viewport;
video_driver_update_viewport(_viewport, NO, _keepAspect);
if (memcmp(&vp, _viewport, sizeof(vp)) != 0)
{
_context.viewport = _viewport;
}
[_context begin];
[self _updateUniforms];
}
@ -546,8 +550,8 @@ typedef struct MTLALIGN(16)
CGRect _frame;
NSUInteger _bpp;
id<MTLBuffer> _pixels; // frame buffer in _srcFmt
bool _pixelsDirty;
id<MTLTexture> _src; // src texture
bool _srcDirty;
id<MTLSamplerState> _samplers[RARCH_FILTER_MAX][RARCH_WRAP_MAX];
struct video_shader *_shader;
@ -655,8 +659,11 @@ typedef struct MTLALIGN(16)
if (_format != RPixelFormatBGRA8Unorm && _format != RPixelFormatBGRX8Unorm)
{
_pixels = [_context.device newBufferWithLength:(NSUInteger)(size.width * size.height * 2)
options:MTLResourceStorageModeManaged];
MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR16Uint
width:(NSUInteger)size.width
height:(NSUInteger)size.height
mipmapped:NO];
_src = [_context.device newTextureWithDescriptor:td];
}
}
@ -702,11 +709,11 @@ typedef struct MTLALIGN(16)
if (_format == RPixelFormatBGRA8Unorm || _format == RPixelFormatBGRX8Unorm)
return;
if (!_pixelsDirty)
if (!_srcDirty)
return;
[_context convertFormat:_format from:_pixels to:_texture];
_pixelsDirty = NO;
[_context convertFormat:_format from:_src to:_texture];
_srcDirty = NO;
}
- (void)_updateHistory
@ -778,26 +785,10 @@ typedef struct MTLALIGN(16)
}
else
{
void *dst = _pixels.contents;
size_t len = (size_t)(_bpp * _size.width);
assert(len <= pitch); // the length can't be larger?
if (len < pitch)
{
for (int i = 0; i < _size.height; i++)
{
memcpy(dst, src, len);
dst += len;
src += pitch;
}
}
else
{
memcpy(dst, src, _pixels.length);
}
[_pixels didModifyRange:NSMakeRange(0, _pixels.length)];
_pixelsDirty = YES;
[_src replaceRegion:MTLRegionMake2D(0, 0, (NSUInteger)_size.width, (NSUInteger)_size.height)
mipmapLevel:0 withBytes:src
bytesPerRow:(NSUInteger)(pitch)];
_srcDirty = YES;
}
}
@ -1204,7 +1195,7 @@ static vertex_t vertex_bytes[] = {
if (lib == nil)
{
save_msl = true;
RARCH_ERR("Metal]: unable to compile vertex shader: %s\n", err.localizedDescription.UTF8String);
RARCH_ERR("[Metal]: unable to compile vertex shader: %s\n", err.localizedDescription.UTF8String);
return NO;
}
#if DEBUG
@ -1220,7 +1211,7 @@ static vertex_t vertex_bytes[] = {
if (lib == nil)
{
save_msl = true;
RARCH_ERR("Metal]: unable to compile fragment shader: %s\n", err.localizedDescription.UTF8String);
RARCH_ERR("[Metal]: unable to compile fragment shader: %s\n", err.localizedDescription.UTF8String);
return NO;
}
#if DEBUG
@ -1234,7 +1225,8 @@ static vertex_t vertex_bytes[] = {
if (err != nil)
{
save_msl = true;
RARCH_ERR("error creating pipeline state: %s", err.localizedDescription.UTF8String);
RARCH_ERR("[Metal]: error creating pipeline state for pass %d: %s\n", i,
err.localizedDescription.UTF8String);
return NO;
}
@ -1253,10 +1245,11 @@ static vertex_t vertex_bytes[] = {
{
if (save_msl)
{
RARCH_LOG("[Metal]: saving metal shader files\n");
NSString *basePath = [[NSString stringWithUTF8String:shader->pass[i].source.path] stringByDeletingPathExtension];
RARCH_LOG("[Metal]: saving metal shader files to %s\n", basePath.UTF8String);
NSError *err = nil;
NSString *basePath = [[NSString stringWithUTF8String:shader->pass[i].source.path] stringByDeletingPathExtension];
[vs_src writeToFile:[basePath stringByAppendingPathExtension:@"vs.metal"]
atomically:NO
encoding:NSStringEncodingConversionAllowLossy

View File

@ -35,7 +35,6 @@ enum aspect_ratio
ASPECT_RATIO_16_9,
ASPECT_RATIO_16_10,
ASPECT_RATIO_16_15,
ASPECT_RATIO_21_9,
ASPECT_RATIO_1_1,
ASPECT_RATIO_2_1,
ASPECT_RATIO_3_2,
@ -55,6 +54,7 @@ enum aspect_ratio
ASPECT_RATIO_SQUARE,
ASPECT_RATIO_CORE,
ASPECT_RATIO_CUSTOM,
ASPECT_RATIO_21_9,
ASPECT_RATIO_END
};

View File

@ -2007,7 +2007,8 @@ static void xmb_context_reset_horizontal_list(
{
struct texture_image ti;
char sysname[256];
char *sysname = (char*)
malloc(PATH_MAX_LENGTH * sizeof(char));
char *iconpath = (char*)
malloc(PATH_MAX_LENGTH * sizeof(char));
char *texturepath = (char*)
@ -2018,7 +2019,8 @@ static void xmb_context_reset_horizontal_list(
iconpath[0] = sysname[0] =
texturepath[0] = content_texturepath[0] = '\0';
fill_pathname_base_noext(sysname, path, sizeof(sysname));
fill_pathname_base_noext(sysname, path,
PATH_MAX_LENGTH * sizeof(char));
fill_pathname_application_special(iconpath,
PATH_MAX_LENGTH * sizeof(char),
@ -2080,6 +2082,7 @@ static void xmb_context_reset_horizontal_list(
image_texture_free(&ti);
}
free(sysname);
free(iconpath);
free(texturepath);
free(content_texturepath);

View File

@ -37,7 +37,7 @@
#include "../../retroarch.h"
#include "../../tasks/tasks_internal.h"
#if HAVE_METAL
#ifdef HAVE_METAL
#import <Metal/Metal.h>
#import <MetalKit/MetalKit.h>
#endif
@ -297,6 +297,8 @@ static char** waiting_argv;
[self performSelectorOnMainThread:@selector(rarch_main) withObject:nil waitUntilDone:NO];
}
#pragma mark - ApplePlatform
- (void)setViewType:(apple_view_type_t)vt {
if (vt == _vt) {
return;
@ -359,19 +361,16 @@ static char** waiting_argv;
return [NSApp isActive];
}
#define NS_FULLSCREEN_WINDOW_MASK (1 << 14)
- (void)setVideoMode:(gfx_ctx_mode_t)mode {
BOOL isFullScreen = (self.window.styleMask & NS_FULLSCREEN_WINDOW_MASK) == NS_FULLSCREEN_WINDOW_MASK;
SEL fselector = NSSelectorFromString(BOXSTRING("toggleFullScreen"));
if (mode.fullscreen && !isFullScreen && [self.window respondsToSelector:fselector])
#ifdef HAVE_METAL
BOOL isFullScreen = (self.window.styleMask & NSFullScreenWindowMask) == NSFullScreenWindowMask;
if (mode.fullscreen && !isFullScreen)
{
[self.window toggleFullScreen:self];
return;
}
if (!mode.fullscreen && isFullScreen && [self.window respondsToSelector:fselector])
if (!mode.fullscreen && isFullScreen)
{
[self.window toggleFullScreen:self];
}
@ -382,6 +381,7 @@ static char** waiting_argv;
[self.window setContentSize:NSMakeSize(mode.width-1, mode.height)];
}
[self.window setContentSize:NSMakeSize(mode.width, mode.height)];
#endif
}
- (void)setCursorVisible:(bool)v {
@ -739,7 +739,7 @@ static void *ui_companion_cocoa_init(void)
static void ui_companion_cocoa_event_command(void *data, enum event_command cmd)
{
(void)data;
command_event(cmd, NULL);
(void)cmd;
}
static void ui_companion_cocoa_notify_list_pushed(void *data,