|
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 |