mirror of https://github.com/encounter/SDL.git
metal: Clean up manual reference counting. Fixes some memory leaks.
This commit is contained in:
parent
7c667a6f7a
commit
1cc6603378
|
@ -140,8 +140,8 @@ typedef struct METAL_PipelineCache
|
||||||
@property (nonatomic, retain) id<MTLRenderCommandEncoder> mtlcmdencoder;
|
@property (nonatomic, retain) id<MTLRenderCommandEncoder> mtlcmdencoder;
|
||||||
@property (nonatomic, retain) id<MTLLibrary> mtllibrary;
|
@property (nonatomic, retain) id<MTLLibrary> mtllibrary;
|
||||||
@property (nonatomic, retain) id<CAMetalDrawable> mtlbackbuffer;
|
@property (nonatomic, retain) id<CAMetalDrawable> mtlbackbuffer;
|
||||||
@property (nonatomic) METAL_PipelineCache *mtlpipelineprims;
|
@property (nonatomic, assign) METAL_PipelineCache *mtlpipelineprims;
|
||||||
@property (nonatomic) METAL_PipelineCache *mtlpipelinecopy;
|
@property (nonatomic, assign) METAL_PipelineCache *mtlpipelinecopy;
|
||||||
@property (nonatomic, retain) id<MTLSamplerState> mtlsamplernearest;
|
@property (nonatomic, retain) id<MTLSamplerState> mtlsamplernearest;
|
||||||
@property (nonatomic, retain) id<MTLSamplerState> mtlsamplerlinear;
|
@property (nonatomic, retain) id<MTLSamplerState> mtlsamplerlinear;
|
||||||
@property (nonatomic, retain) id<MTLBuffer> mtlbufclearverts;
|
@property (nonatomic, retain) id<MTLBuffer> mtlbufclearverts;
|
||||||
|
@ -151,6 +151,24 @@ typedef struct METAL_PipelineCache
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation METAL_RenderData
|
@implementation METAL_RenderData
|
||||||
|
#if !__has_feature(obc_arc)
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[_mtldevice release];
|
||||||
|
[_mtlcmdqueue release];
|
||||||
|
[_mtlcmdbuffer release];
|
||||||
|
[_mtlcmdencoder release];
|
||||||
|
[_mtllibrary release];
|
||||||
|
[_mtlbackbuffer release];
|
||||||
|
[_mtlsamplernearest release];
|
||||||
|
[_mtlsamplerlinear release];
|
||||||
|
[_mtlbufclearverts release];
|
||||||
|
[_mtlbufidentitytransform release];
|
||||||
|
[_mtllayer release];
|
||||||
|
[_mtlpassdesc release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface METAL_TextureData : NSObject
|
@interface METAL_TextureData : NSObject
|
||||||
|
@ -159,6 +177,14 @@ typedef struct METAL_PipelineCache
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation METAL_TextureData
|
@implementation METAL_TextureData
|
||||||
|
#if !__has_feature(obc_arc)
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[_mtltexture release];
|
||||||
|
[_mtlsampler release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@end
|
@end
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -368,11 +394,7 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
data = [[METAL_RenderData alloc] init];
|
data = [[METAL_RenderData alloc] init];
|
||||||
data.beginScene = YES;
|
data.beginScene = YES;
|
||||||
|
|
||||||
#if __has_feature(objc_arc)
|
|
||||||
renderer->driverdata = (void*)CFBridgingRetain(data);
|
renderer->driverdata = (void*)CFBridgingRetain(data);
|
||||||
#else
|
|
||||||
renderer->driverdata = data;
|
|
||||||
#endif
|
|
||||||
renderer->window = window;
|
renderer->window = window;
|
||||||
|
|
||||||
#ifdef __MACOSX__
|
#ifdef __MACOSX__
|
||||||
|
@ -405,7 +427,8 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
|
|
||||||
data.mtldevice = layer.device;
|
data.mtldevice = layer.device;
|
||||||
data.mtllayer = layer;
|
data.mtllayer = layer;
|
||||||
data.mtlcmdqueue = [data.mtldevice newCommandQueue];
|
id<MTLCommandQueue> mtlcmdqueue = [data.mtldevice newCommandQueue];
|
||||||
|
data.mtlcmdqueue = mtlcmdqueue;
|
||||||
data.mtlcmdqueue.label = @"SDL Metal Renderer";
|
data.mtlcmdqueue.label = @"SDL Metal Renderer";
|
||||||
data.mtlpassdesc = [MTLRenderPassDescriptor renderPassDescriptor];
|
data.mtlpassdesc = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
|
|
||||||
|
@ -414,7 +437,8 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
// The compiled .metallib is embedded in a static array in a header file
|
// The compiled .metallib is embedded in a static array in a header file
|
||||||
// but the original shader source code is in SDL_shaders_metal.metal.
|
// but the original shader source code is in SDL_shaders_metal.metal.
|
||||||
dispatch_data_t mtllibdata = dispatch_data_create(sdl_metallib, sdl_metallib_len, dispatch_get_global_queue(0, 0), ^{});
|
dispatch_data_t mtllibdata = dispatch_data_create(sdl_metallib, sdl_metallib_len, dispatch_get_global_queue(0, 0), ^{});
|
||||||
data.mtllibrary = [data.mtldevice newLibraryWithData:mtllibdata error:&err];
|
id<MTLLibrary> mtllibrary = [data.mtldevice newLibraryWithData:mtllibdata error:&err];
|
||||||
|
data.mtllibrary = mtllibrary;
|
||||||
SDL_assert(err == nil);
|
SDL_assert(err == nil);
|
||||||
#if !__has_feature(objc_arc)
|
#if !__has_feature(objc_arc)
|
||||||
dispatch_release(mtllibdata);
|
dispatch_release(mtllibdata);
|
||||||
|
@ -428,24 +452,24 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
|
|
||||||
samplerdesc.minFilter = MTLSamplerMinMagFilterNearest;
|
samplerdesc.minFilter = MTLSamplerMinMagFilterNearest;
|
||||||
samplerdesc.magFilter = MTLSamplerMinMagFilterNearest;
|
samplerdesc.magFilter = MTLSamplerMinMagFilterNearest;
|
||||||
data.mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
id<MTLSamplerState> mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
||||||
|
data.mtlsamplernearest = mtlsamplernearest;
|
||||||
|
|
||||||
samplerdesc.minFilter = MTLSamplerMinMagFilterLinear;
|
samplerdesc.minFilter = MTLSamplerMinMagFilterLinear;
|
||||||
samplerdesc.magFilter = MTLSamplerMinMagFilterLinear;
|
samplerdesc.magFilter = MTLSamplerMinMagFilterLinear;
|
||||||
data.mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
id<MTLSamplerState> mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
||||||
|
data.mtlsamplerlinear = mtlsamplerlinear;
|
||||||
#if !__has_feature(objc_arc)
|
|
||||||
[samplerdesc release];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const float clearverts[] = { 0, 0, 0, 3, 3, 0 };
|
static const float clearverts[] = { 0, 0, 0, 3, 3, 0 };
|
||||||
data.mtlbufclearverts = [data.mtldevice newBufferWithBytes:clearverts length:sizeof(clearverts) options:MTLResourceCPUCacheModeWriteCombined];
|
id<MTLBuffer> mtlbufclearverts = [data.mtldevice newBufferWithBytes:clearverts length:sizeof(clearverts) options:MTLResourceCPUCacheModeWriteCombined];
|
||||||
|
data.mtlbufclearverts = mtlbufclearverts;
|
||||||
data.mtlbufclearverts.label = @"SDL_RenderClear vertices";
|
data.mtlbufclearverts.label = @"SDL_RenderClear vertices";
|
||||||
|
|
||||||
float identitytx[16];
|
float identitytx[16];
|
||||||
SDL_memset(identitytx, 0, sizeof(identitytx));
|
SDL_memset(identitytx, 0, sizeof(identitytx));
|
||||||
identitytx[0] = identitytx[5] = identitytx[10] = identitytx[15] = 1.0f;
|
identitytx[0] = identitytx[5] = identitytx[10] = identitytx[15] = 1.0f;
|
||||||
data.mtlbufidentitytransform = [data.mtldevice newBufferWithBytes:identitytx length:sizeof(identitytx) options:0];
|
id<MTLBuffer> mtlbufidentitytransform = [data.mtldevice newBufferWithBytes:identitytx length:sizeof(identitytx) options:0];
|
||||||
|
data.mtlbufidentitytransform = mtlbufidentitytransform;
|
||||||
data.mtlbufidentitytransform.label = @"SDL_RenderCopy identity transform";
|
data.mtlbufidentitytransform.label = @"SDL_RenderCopy identity transform";
|
||||||
|
|
||||||
// !!! FIXME: force more clears here so all the drawables are sane to start, and our static buffers are definitely flushed.
|
// !!! FIXME: force more clears here so all the drawables are sane to start, and our static buffers are definitely flushed.
|
||||||
|
@ -486,10 +510,26 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
|
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !__has_feature(objc_arc)
|
||||||
|
[mtlcmdqueue release];
|
||||||
|
[mtllibrary release];
|
||||||
|
[samplerdesc release];
|
||||||
|
[mtlsamplernearest release];
|
||||||
|
[mtlsamplerlinear release];
|
||||||
|
[mtlbufclearverts release];
|
||||||
|
[mtlbufidentitytransform release];
|
||||||
|
[view release];
|
||||||
|
[data release];
|
||||||
|
#ifdef __MACOSX__
|
||||||
|
[mtldevice release];
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
return renderer;
|
return renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void METAL_ActivateRenderer(SDL_Renderer * renderer)
|
static void
|
||||||
|
METAL_ActivateRenderer(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||||
|
|
||||||
|
@ -596,6 +636,7 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
texture->driverdata = (void*)CFBridgingRetain(texturedata);
|
texture->driverdata = (void*)CFBridgingRetain(texturedata);
|
||||||
|
|
||||||
#if !__has_feature(objc_arc)
|
#if !__has_feature(objc_arc)
|
||||||
|
[texturedata release];
|
||||||
[mtltexture release];
|
[mtltexture release];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -977,8 +1018,7 @@ METAL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
METAL_ActivateRenderer(renderer);
|
METAL_ActivateRenderer(renderer);
|
||||||
// !!! FIXME: this probably needs to commit the current command buffer, and probably waitUntilCompleted
|
// !!! FIXME: this probably needs to commit the current command buffer, and probably waitUntilCompleted
|
||||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||||
MTLRenderPassColorAttachmentDescriptor *colorAttachment = data.mtlpassdesc.colorAttachments[0];
|
id<MTLTexture> mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
|
||||||
id<MTLTexture> mtltexture = colorAttachment.texture;
|
|
||||||
MTLRegion mtlregion = MTLRegionMake2D(rect->x, rect->y, rect->w, rect->h);
|
MTLRegion mtlregion = MTLRegionMake2D(rect->x, rect->y, rect->w, rect->h);
|
||||||
|
|
||||||
// we only do BGRA8 or RGBA8 at the moment, so 4 will do.
|
// we only do BGRA8 or RGBA8 at the moment, so 4 will do.
|
||||||
|
@ -1014,13 +1054,7 @@ METAL_RenderPresent(SDL_Renderer * renderer)
|
||||||
static void
|
static void
|
||||||
METAL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
METAL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
{ @autoreleasepool {
|
{ @autoreleasepool {
|
||||||
METAL_TextureData *texturedata = CFBridgingRelease(texture->driverdata);
|
CFBridgingRelease(texture->driverdata);
|
||||||
#if __has_feature(objc_arc)
|
|
||||||
texturedata = nil;
|
|
||||||
#else
|
|
||||||
[texturedata.mtltexture release];
|
|
||||||
[texturedata release];
|
|
||||||
#endif
|
|
||||||
texture->driverdata = NULL;
|
texture->driverdata = NULL;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
@ -1034,21 +1068,6 @@ METAL_DestroyRenderer(SDL_Renderer * renderer)
|
||||||
[data.mtlcmdencoder endEncoding];
|
[data.mtlcmdencoder endEncoding];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !__has_feature(objc_arc)
|
|
||||||
[data.mtlbackbuffer release];
|
|
||||||
[data.mtlcmdencoder release];
|
|
||||||
[data.mtlcmdbuffer release];
|
|
||||||
[data.mtlcmdqueue release];
|
|
||||||
[data.mtlsamplernearest release];
|
|
||||||
[data.mtlsamplerlinear release];
|
|
||||||
[data.mtlbufclearverts release];
|
|
||||||
[data.mtlbufidentitytransform release];
|
|
||||||
[data.mtllibrary release];
|
|
||||||
[data.mtldevice release];
|
|
||||||
[data.mtlpassdesc release];
|
|
||||||
[data.mtllayer release];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DestroyPipelineCache(data.mtlpipelineprims);
|
DestroyPipelineCache(data.mtlpipelineprims);
|
||||||
DestroyPipelineCache(data.mtlpipelinecopy);
|
DestroyPipelineCache(data.mtlpipelinecopy);
|
||||||
}
|
}
|
||||||
|
@ -1056,13 +1075,15 @@ METAL_DestroyRenderer(SDL_Renderer * renderer)
|
||||||
SDL_free(renderer);
|
SDL_free(renderer);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
void *METAL_GetMetalLayer(SDL_Renderer * renderer)
|
static void *
|
||||||
|
METAL_GetMetalLayer(SDL_Renderer * renderer)
|
||||||
{ @autoreleasepool {
|
{ @autoreleasepool {
|
||||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||||
return (__bridge void*)data.mtllayer;
|
return (__bridge void*)data.mtllayer;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
void *METAL_GetMetalCommandEncoder(SDL_Renderer * renderer)
|
static void *
|
||||||
|
METAL_GetMetalCommandEncoder(SDL_Renderer * renderer)
|
||||||
{ @autoreleasepool {
|
{ @autoreleasepool {
|
||||||
METAL_ActivateRenderer(renderer);
|
METAL_ActivateRenderer(renderer);
|
||||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||||
|
|
Loading…
Reference in New Issue