metal: Clean up manual reference counting. Fixes some memory leaks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m
index 814ad59..e1dd56e 100644
--- a/src/render/metal/SDL_render_metal.m
+++ b/src/render/metal/SDL_render_metal.m
@@ -140,8 +140,8 @@ typedef struct METAL_PipelineCache
@property (nonatomic, retain) id<MTLRenderCommandEncoder> mtlcmdencoder;
@property (nonatomic, retain) id<MTLLibrary> mtllibrary;
@property (nonatomic, retain) id<CAMetalDrawable> mtlbackbuffer;
- @property (nonatomic) METAL_PipelineCache *mtlpipelineprims;
- @property (nonatomic) METAL_PipelineCache *mtlpipelinecopy;
+ @property (nonatomic, assign) METAL_PipelineCache *mtlpipelineprims;
+ @property (nonatomic, assign) METAL_PipelineCache *mtlpipelinecopy;
@property (nonatomic, retain) id<MTLSamplerState> mtlsamplernearest;
@property (nonatomic, retain) id<MTLSamplerState> mtlsamplerlinear;
@property (nonatomic, retain) id<MTLBuffer> mtlbufclearverts;
@@ -151,6 +151,24 @@ typedef struct METAL_PipelineCache
@end
@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
@interface METAL_TextureData : NSObject
@@ -159,6 +177,14 @@ typedef struct METAL_PipelineCache
@end
@implementation METAL_TextureData
+#if !__has_feature(obc_arc)
+- (void)dealloc
+{
+ [_mtltexture release];
+ [_mtlsampler release];
+ [super dealloc];
+}
+#endif
@end
static int
@@ -368,11 +394,7 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
data = [[METAL_RenderData alloc] init];
data.beginScene = YES;
-#if __has_feature(objc_arc)
renderer->driverdata = (void*)CFBridgingRetain(data);
-#else
- renderer->driverdata = data;
-#endif
renderer->window = window;
#ifdef __MACOSX__
@@ -405,7 +427,8 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
data.mtldevice = layer.device;
data.mtllayer = layer;
- data.mtlcmdqueue = [data.mtldevice newCommandQueue];
+ id<MTLCommandQueue> mtlcmdqueue = [data.mtldevice newCommandQueue];
+ data.mtlcmdqueue = mtlcmdqueue;
data.mtlcmdqueue.label = @"SDL Metal Renderer";
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
// 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), ^{});
- data.mtllibrary = [data.mtldevice newLibraryWithData:mtllibdata error:&err];
+ id<MTLLibrary> mtllibrary = [data.mtldevice newLibraryWithData:mtllibdata error:&err];
+ data.mtllibrary = mtllibrary;
SDL_assert(err == nil);
#if !__has_feature(objc_arc)
dispatch_release(mtllibdata);
@@ -428,24 +452,24 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
samplerdesc.minFilter = MTLSamplerMinMagFilterNearest;
samplerdesc.magFilter = MTLSamplerMinMagFilterNearest;
- data.mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
+ id<MTLSamplerState> mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
+ data.mtlsamplernearest = mtlsamplernearest;
samplerdesc.minFilter = MTLSamplerMinMagFilterLinear;
samplerdesc.magFilter = MTLSamplerMinMagFilterLinear;
- data.mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
-
-#if !__has_feature(objc_arc)
- [samplerdesc release];
-#endif
+ id<MTLSamplerState> mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
+ data.mtlsamplerlinear = mtlsamplerlinear;
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";
float identitytx[16];
SDL_memset(identitytx, 0, sizeof(identitytx));
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";
// !!! 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;
}
+#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;
}
-static void METAL_ActivateRenderer(SDL_Renderer * renderer)
+static void
+METAL_ActivateRenderer(SDL_Renderer * renderer)
{
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);
#if !__has_feature(objc_arc)
+ [texturedata release];
[mtltexture release];
#endif
@@ -977,8 +1018,7 @@ METAL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
METAL_ActivateRenderer(renderer);
// !!! FIXME: this probably needs to commit the current command buffer, and probably waitUntilCompleted
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
- MTLRenderPassColorAttachmentDescriptor *colorAttachment = data.mtlpassdesc.colorAttachments[0];
- id<MTLTexture> mtltexture = colorAttachment.texture;
+ id<MTLTexture> mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
MTLRegion mtlregion = MTLRegionMake2D(rect->x, rect->y, rect->w, rect->h);
// we only do BGRA8 or RGBA8 at the moment, so 4 will do.
@@ -1014,13 +1054,7 @@ METAL_RenderPresent(SDL_Renderer * renderer)
static void
METAL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{ @autoreleasepool {
- METAL_TextureData *texturedata = CFBridgingRelease(texture->driverdata);
-#if __has_feature(objc_arc)
- texturedata = nil;
-#else
- [texturedata.mtltexture release];
- [texturedata release];
-#endif
+ CFBridgingRelease(texture->driverdata);
texture->driverdata = NULL;
}}
@@ -1034,21 +1068,6 @@ METAL_DestroyRenderer(SDL_Renderer * renderer)
[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.mtlpipelinecopy);
}
@@ -1056,13 +1075,15 @@ METAL_DestroyRenderer(SDL_Renderer * renderer)
SDL_free(renderer);
}}
-void *METAL_GetMetalLayer(SDL_Renderer * renderer)
+static void *
+METAL_GetMetalLayer(SDL_Renderer * renderer)
{ @autoreleasepool {
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
return (__bridge void*)data.mtllayer;
}}
-void *METAL_GetMetalCommandEncoder(SDL_Renderer * renderer)
+static void *
+METAL_GetMetalCommandEncoder(SDL_Renderer * renderer)
{ @autoreleasepool {
METAL_ActivateRenderer(renderer);
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;