metal: Clean up manual reference counting. Fixes some memory leaks.
authorAlex Szpakowski <slime73@gmail.com>
Mon, 01 Jan 2018 23:03:50 -0400
changeset 118048dce4b0683e6
parent 11803 454f6dc9cb85
child 11805 ccf4e7af3583
metal: Clean up manual reference counting. Fixes some memory leaks.
src/render/metal/SDL_render_metal.m
     1.1 --- a/src/render/metal/SDL_render_metal.m	Mon Jan 01 19:16:51 2018 -0500
     1.2 +++ b/src/render/metal/SDL_render_metal.m	Mon Jan 01 23:03:50 2018 -0400
     1.3 @@ -140,8 +140,8 @@
     1.4      @property (nonatomic, retain) id<MTLRenderCommandEncoder> mtlcmdencoder;
     1.5      @property (nonatomic, retain) id<MTLLibrary> mtllibrary;
     1.6      @property (nonatomic, retain) id<CAMetalDrawable> mtlbackbuffer;
     1.7 -    @property (nonatomic) METAL_PipelineCache *mtlpipelineprims;
     1.8 -    @property (nonatomic) METAL_PipelineCache *mtlpipelinecopy;
     1.9 +    @property (nonatomic, assign) METAL_PipelineCache *mtlpipelineprims;
    1.10 +    @property (nonatomic, assign) METAL_PipelineCache *mtlpipelinecopy;
    1.11      @property (nonatomic, retain) id<MTLSamplerState> mtlsamplernearest;
    1.12      @property (nonatomic, retain) id<MTLSamplerState> mtlsamplerlinear;
    1.13      @property (nonatomic, retain) id<MTLBuffer> mtlbufclearverts;
    1.14 @@ -151,6 +151,24 @@
    1.15  @end
    1.16  
    1.17  @implementation METAL_RenderData
    1.18 +#if !__has_feature(obc_arc)
    1.19 +- (void)dealloc
    1.20 +{
    1.21 +    [_mtldevice release];
    1.22 +    [_mtlcmdqueue release];
    1.23 +    [_mtlcmdbuffer release];
    1.24 +    [_mtlcmdencoder release];
    1.25 +    [_mtllibrary release];
    1.26 +    [_mtlbackbuffer release];
    1.27 +    [_mtlsamplernearest release];
    1.28 +    [_mtlsamplerlinear release];
    1.29 +    [_mtlbufclearverts release];
    1.30 +    [_mtlbufidentitytransform release];
    1.31 +    [_mtllayer release];
    1.32 +    [_mtlpassdesc release];
    1.33 +    [super dealloc];
    1.34 +}
    1.35 +#endif
    1.36  @end
    1.37  
    1.38  @interface METAL_TextureData : NSObject
    1.39 @@ -159,6 +177,14 @@
    1.40  @end
    1.41  
    1.42  @implementation METAL_TextureData
    1.43 +#if !__has_feature(obc_arc)
    1.44 +- (void)dealloc
    1.45 +{
    1.46 +    [_mtltexture release];
    1.47 +    [_mtlsampler release];
    1.48 +    [super dealloc];
    1.49 +}
    1.50 +#endif
    1.51  @end
    1.52  
    1.53  static int
    1.54 @@ -368,11 +394,7 @@
    1.55      data = [[METAL_RenderData alloc] init];
    1.56      data.beginScene = YES;
    1.57  
    1.58 -#if __has_feature(objc_arc)
    1.59      renderer->driverdata = (void*)CFBridgingRetain(data);
    1.60 -#else
    1.61 -    renderer->driverdata = data;
    1.62 -#endif
    1.63      renderer->window = window;
    1.64  
    1.65  #ifdef __MACOSX__
    1.66 @@ -405,7 +427,8 @@
    1.67  
    1.68      data.mtldevice = layer.device;
    1.69      data.mtllayer = layer;
    1.70 -    data.mtlcmdqueue = [data.mtldevice newCommandQueue];
    1.71 +    id<MTLCommandQueue> mtlcmdqueue = [data.mtldevice newCommandQueue];
    1.72 +    data.mtlcmdqueue = mtlcmdqueue;
    1.73      data.mtlcmdqueue.label = @"SDL Metal Renderer";
    1.74      data.mtlpassdesc = [MTLRenderPassDescriptor renderPassDescriptor];
    1.75  
    1.76 @@ -414,7 +437,8 @@
    1.77      // The compiled .metallib is embedded in a static array in a header file
    1.78      // but the original shader source code is in SDL_shaders_metal.metal.
    1.79      dispatch_data_t mtllibdata = dispatch_data_create(sdl_metallib, sdl_metallib_len, dispatch_get_global_queue(0, 0), ^{});
    1.80 -    data.mtllibrary = [data.mtldevice newLibraryWithData:mtllibdata error:&err];
    1.81 +    id<MTLLibrary> mtllibrary = [data.mtldevice newLibraryWithData:mtllibdata error:&err];
    1.82 +    data.mtllibrary = mtllibrary;
    1.83      SDL_assert(err == nil);
    1.84  #if !__has_feature(objc_arc)
    1.85      dispatch_release(mtllibdata);
    1.86 @@ -428,24 +452,24 @@
    1.87  
    1.88      samplerdesc.minFilter = MTLSamplerMinMagFilterNearest;
    1.89      samplerdesc.magFilter = MTLSamplerMinMagFilterNearest;
    1.90 -    data.mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
    1.91 +    id<MTLSamplerState> mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
    1.92 +    data.mtlsamplernearest = mtlsamplernearest;
    1.93  
    1.94      samplerdesc.minFilter = MTLSamplerMinMagFilterLinear;
    1.95      samplerdesc.magFilter = MTLSamplerMinMagFilterLinear;
    1.96 -    data.mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
    1.97 -
    1.98 -#if !__has_feature(objc_arc)
    1.99 -    [samplerdesc release];
   1.100 -#endif
   1.101 +    id<MTLSamplerState> mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
   1.102 +    data.mtlsamplerlinear = mtlsamplerlinear;
   1.103  
   1.104      static const float clearverts[] = { 0, 0,  0, 3,  3, 0 };
   1.105 -    data.mtlbufclearverts = [data.mtldevice newBufferWithBytes:clearverts length:sizeof(clearverts) options:MTLResourceCPUCacheModeWriteCombined];
   1.106 +    id<MTLBuffer> mtlbufclearverts = [data.mtldevice newBufferWithBytes:clearverts length:sizeof(clearverts) options:MTLResourceCPUCacheModeWriteCombined];
   1.107 +    data.mtlbufclearverts = mtlbufclearverts;
   1.108      data.mtlbufclearverts.label = @"SDL_RenderClear vertices";
   1.109  
   1.110      float identitytx[16];
   1.111      SDL_memset(identitytx, 0, sizeof(identitytx));
   1.112      identitytx[0] = identitytx[5] = identitytx[10] = identitytx[15] = 1.0f;
   1.113 -    data.mtlbufidentitytransform = [data.mtldevice newBufferWithBytes:identitytx length:sizeof(identitytx) options:0];
   1.114 +    id<MTLBuffer> mtlbufidentitytransform = [data.mtldevice newBufferWithBytes:identitytx length:sizeof(identitytx) options:0];
   1.115 +    data.mtlbufidentitytransform = mtlbufidentitytransform;
   1.116      data.mtlbufidentitytransform.label = @"SDL_RenderCopy identity transform";
   1.117  
   1.118      // !!! FIXME: force more clears here so all the drawables are sane to start, and our static buffers are definitely flushed.
   1.119 @@ -486,10 +510,26 @@
   1.120          renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   1.121      }
   1.122  
   1.123 +#if !__has_feature(objc_arc)
   1.124 +    [mtlcmdqueue release];
   1.125 +    [mtllibrary release];
   1.126 +    [samplerdesc release];
   1.127 +    [mtlsamplernearest release];
   1.128 +    [mtlsamplerlinear release];
   1.129 +    [mtlbufclearverts release];
   1.130 +    [mtlbufidentitytransform release];
   1.131 +    [view release];
   1.132 +    [data release];
   1.133 +#ifdef __MACOSX__
   1.134 +    [mtldevice release];
   1.135 +#endif
   1.136 +#endif
   1.137 +
   1.138      return renderer;
   1.139  }
   1.140  
   1.141 -static void METAL_ActivateRenderer(SDL_Renderer * renderer)
   1.142 +static void
   1.143 +METAL_ActivateRenderer(SDL_Renderer * renderer)
   1.144  {
   1.145      METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
   1.146  
   1.147 @@ -596,6 +636,7 @@
   1.148      texture->driverdata = (void*)CFBridgingRetain(texturedata);
   1.149  
   1.150  #if !__has_feature(objc_arc)
   1.151 +    [texturedata release];
   1.152      [mtltexture release];
   1.153  #endif
   1.154  
   1.155 @@ -977,8 +1018,7 @@
   1.156      METAL_ActivateRenderer(renderer);
   1.157      // !!! FIXME: this probably needs to commit the current command buffer, and probably waitUntilCompleted
   1.158      METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
   1.159 -    MTLRenderPassColorAttachmentDescriptor *colorAttachment = data.mtlpassdesc.colorAttachments[0];
   1.160 -    id<MTLTexture> mtltexture = colorAttachment.texture;
   1.161 +    id<MTLTexture> mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
   1.162      MTLRegion mtlregion = MTLRegionMake2D(rect->x, rect->y, rect->w, rect->h);
   1.163  
   1.164      // we only do BGRA8 or RGBA8 at the moment, so 4 will do.
   1.165 @@ -1014,13 +1054,7 @@
   1.166  static void
   1.167  METAL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   1.168  { @autoreleasepool {
   1.169 -    METAL_TextureData *texturedata = CFBridgingRelease(texture->driverdata);
   1.170 -#if __has_feature(objc_arc)
   1.171 -    texturedata = nil;
   1.172 -#else
   1.173 -    [texturedata.mtltexture release];
   1.174 -    [texturedata release];
   1.175 -#endif
   1.176 +    CFBridgingRelease(texture->driverdata);
   1.177      texture->driverdata = NULL;
   1.178  }}
   1.179  
   1.180 @@ -1034,21 +1068,6 @@
   1.181              [data.mtlcmdencoder endEncoding];
   1.182          }
   1.183  
   1.184 -#if !__has_feature(objc_arc)
   1.185 -        [data.mtlbackbuffer release];
   1.186 -        [data.mtlcmdencoder release];
   1.187 -        [data.mtlcmdbuffer release];
   1.188 -        [data.mtlcmdqueue release];
   1.189 -        [data.mtlsamplernearest release];
   1.190 -        [data.mtlsamplerlinear release];
   1.191 -        [data.mtlbufclearverts release];
   1.192 -        [data.mtlbufidentitytransform release];
   1.193 -        [data.mtllibrary release];
   1.194 -        [data.mtldevice release];
   1.195 -        [data.mtlpassdesc release];
   1.196 -        [data.mtllayer release];
   1.197 -#endif
   1.198 -
   1.199          DestroyPipelineCache(data.mtlpipelineprims);
   1.200          DestroyPipelineCache(data.mtlpipelinecopy);
   1.201      }
   1.202 @@ -1056,13 +1075,15 @@
   1.203      SDL_free(renderer);
   1.204  }}
   1.205  
   1.206 -void *METAL_GetMetalLayer(SDL_Renderer * renderer)
   1.207 +static void *
   1.208 +METAL_GetMetalLayer(SDL_Renderer * renderer)
   1.209  { @autoreleasepool {
   1.210      METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
   1.211      return (__bridge void*)data.mtllayer;
   1.212  }}
   1.213  
   1.214 -void *METAL_GetMetalCommandEncoder(SDL_Renderer * renderer)
   1.215 +static void *
   1.216 +METAL_GetMetalCommandEncoder(SDL_Renderer * renderer)
   1.217  { @autoreleasepool {
   1.218      METAL_ActivateRenderer(renderer);
   1.219      METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;