1 #import "MTLTexturePool.h" 2 #import "Trace.h" 3 4 @implementation MTLTexturePoolItem 5 6 @synthesize texture; 7 @synthesize isBusy; 8 9 - (id) initWithTexture:(id<MTLTexture>)tex { 10 self = [super init]; 11 if (self == nil) return self; 12 self.texture = tex; 13 isBusy = NO; 14 return self; 15 } 16 @end 17 18 @implementation MTLTexturePool 19 20 @synthesize device; 21 @synthesize pool; 22 23 - (id) initWithDevice:(id<MTLDevice>)dev { 24 self = [super init]; 25 if (self == nil) return self; 26 27 self.device = dev; 28 self.pool = [NSMutableArray arrayWithCapacity:10]; 29 return self; 30 } 31 32 // NOTE: called from RQ-thread (on blit operations) 33 - (id<MTLTexture>) getTexture:(int)width height:(int)height format:(MTLPixelFormat)format { 34 @synchronized (self) { 35 // 1. find free item 36 // TODO: optimize search, use Map<(w,h,pf), TexPoolItem> 37 const int count = [self.pool count]; 38 for (int c = 0; c < count; ++c) { 39 MTLTexturePoolItem *tpi = [self.pool objectAtIndex:c]; 40 if (tpi == nil) 41 continue; 42 // TODO: use checks tpi.texture.width <= width && tpi.texture.height <= height 43 if (tpi.texture.width == width && tpi.texture.height == height && tpi.texture.pixelFormat == format && 44 !tpi.isBusy) { 45 tpi.isBusy = YES; 46 return tpi.texture; 47 } 48 } 49 50 // 2. create 51 MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format width:width height:height mipmapped:NO]; 52 id <MTLTexture> tex = [self.device newTextureWithDescriptor:textureDescriptor]; 53 MTLTexturePoolItem *tpi = [[MTLTexturePoolItem alloc] initWithTexture:tex]; 54 [self.pool addObject:tpi]; 55 J2dTraceLn4(J2D_TRACE_VERBOSE, "MTLTexturePool: created pool item: tex=%p, w=%d h=%d, pf=%d", tex, width, height, format); 56 return tpi.texture; 57 } 58 }; 59 60 // NOTE: called from completion-handler (pooled thread) 61 - (void) markTextureFree:(id<MTLTexture>)texture { 62 // TODO: optimize search, use Map<(w,h,pf), TexPoolItem> 63 @synchronized (self) { 64 const int count = [self.pool count]; 65 for (int c = 0; c < count; ++c) { 66 MTLTexturePoolItem * tpi = [self.pool objectAtIndex:c]; 67 if (tpi == nil) 68 continue; 69 if (tpi.texture == texture) { 70 tpi.isBusy = NO; 71 return; 72 } 73 } 74 J2dTraceLn1(J2D_TRACE_ERROR, "MTLTexturePool: can't find item with texture %p", texture); 75 } 76 } 77 78 // NOTE: called from completion-handler (pooled thread) 79 - (void) markAllTexturesFree { 80 @synchronized (self) { 81 const int count = [self.pool count]; 82 for (int c = 0; c < count; ++c) { 83 MTLTexturePoolItem *tpi = [self.pool objectAtIndex:c]; 84 if (tpi == nil) 85 continue; 86 tpi.isBusy = NO; 87 } 88 } 89 } 90 91 92 @end