6
6
#include " ../Source/Maths.h"
7
7
#include " ../Source/Test.h"
8
8
9
-
10
9
static const NSUInteger kMaxBuffersInFlight = 3 ;
11
10
12
11
#if TARGET_OS_IPHONE
15
14
#define kMetalBufferMode MTLResourceStorageModeManaged
16
15
#endif
17
16
18
- #if DO_COMPUTE_GPU
19
17
// Metal on Mac needs buffer offsets to be 256-byte aligned
20
18
static int AlignedSize (int sz)
21
19
{
@@ -34,7 +32,6 @@ static int AlignedSize(int sz)
34
32
float lerpFac;
35
33
int emissiveCount;
36
34
};
37
- #endif
38
35
39
36
40
37
@implementation Renderer
@@ -45,7 +42,8 @@ @implementation Renderer
45
42
46
43
id <MTLRenderPipelineState > _pipelineState;
47
44
id <MTLDepthStencilState > _depthState;
48
- #if DO_COMPUTE_GPU
45
+
46
+ // GPU tracing things:
49
47
id <MTLComputePipelineState > _computeState;
50
48
// all the data in separate buffers
51
49
id <MTLBuffer > _computeSpheres;
@@ -57,30 +55,29 @@ @implementation Renderer
57
55
int _objSize;
58
56
int _matSize;
59
57
int _uniformBufferIndex;
60
- #endif
61
58
62
59
id <MTLTexture > _backbuffer, _backbuffer2;
63
60
int _backbufferIndex;
64
61
float * _backbufferPixels;
65
62
66
63
mach_timebase_info_data_t _clock_timebase;
67
- #if !TARGET_OS_IPHONE
64
+ #if TARGET_OS_IPHONE
65
+ UILabel* _label;
66
+ #else
68
67
NSTextField * _label;
69
68
#endif
70
69
}
71
70
72
71
#if TARGET_OS_IPHONE
73
- -(nonnull instancetype )initWithMetalKitView : (nonnull MTKView *)view ;
72
+ -(nonnull instancetype )initWithMetalKitView : (nonnull MTKView *)view withLabel : (nonnull UILabel*) label ;
74
73
#else
75
74
-(nonnull instancetype )initWithMetalKitView : (nonnull MTKView *)view withLabel : (nonnull NSTextField *) label ;
76
75
#endif
77
76
{
78
77
self = [super init ];
79
78
if (self)
80
79
{
81
- #if !TARGET_OS_IPHONE
82
80
_label = label;
83
- #endif
84
81
_device = view.device ;
85
82
printf (" GPU: %s\n " , [[_device name ] UTF8String ]);
86
83
_inFlightSemaphore = dispatch_semaphore_create (kMaxBuffersInFlight );
@@ -102,12 +99,12 @@ - (void)_loadMetalWithView:(nonnull MTKView *)view;
102
99
id <MTLLibrary > defaultLibrary = [_device newDefaultLibrary ];
103
100
id <MTLFunction > vertexFunction = [defaultLibrary newFunctionWithName: @" vertexShader" ];
104
101
id <MTLFunction > fragmentFunction = [defaultLibrary newFunctionWithName: @" fragmentShader" ];
105
- #if DO_COMPUTE_GPU
102
+
103
+ // GPU tracing things:
106
104
id <MTLFunction > computeFunction = [defaultLibrary newFunctionWithName: @" TraceGPU" ];
107
105
_computeState = [_device newComputePipelineStateWithFunction: computeFunction error: &error];
108
106
if (!_computeState)
109
107
NSLog (@" Failed to created compute pipeline state, error %@ " , error);
110
-
111
108
int camSize;
112
109
GetObjectCount (_sphereCount, _objSize, _matSize, camSize);
113
110
assert (_objSize == 20 );
@@ -119,7 +116,6 @@ - (void)_loadMetalWithView:(nonnull MTKView *)view;
119
116
_computeEmissives = [_device newBufferWithLength: AlignedSize (_sphereCount*4 )*kMaxBuffersInFlight options: kMetalBufferMode ];
120
117
_computeCounter = [_device newBufferWithLength: AlignedSize (4 )*kMaxBuffersInFlight options: MTLStorageModeShared ];
121
118
_uniformBufferIndex = 0 ;
122
- #endif
123
119
124
120
MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc ] init ];
125
121
pipelineStateDescriptor.sampleCount = view.sampleCount ;
@@ -144,10 +140,7 @@ - (void)_loadMetalWithView:(nonnull MTKView *)view;
144
140
145
141
MTLTextureDescriptor * desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatRGBA32Float width: kBackbufferWidth height: kBackbufferHeight mipmapped: NO ];
146
142
desc.usage = MTLTextureUsageShaderRead ;
147
- #if DO_COMPUTE_GPU
148
143
desc.usage |= MTLTextureUsageShaderWrite ;
149
- desc.storageMode = MTLStorageModePrivate ;
150
- #endif
151
144
152
145
_backbuffer = [_device newTextureWithDescriptor: desc];
153
146
_backbuffer2 = [_device newTextureWithDescriptor: desc];
@@ -165,22 +158,13 @@ - (void)_loadAssets
165
158
static uint64_t _computeStartTime;
166
159
static uint64_t _computeDur;
167
160
static size_t rayCounter = 0 ;
168
- unsigned g_TestFlags = kFlagProgressive ;
161
+ unsigned g_TestFlags = kFlagProgressive | kFlagAnimate ;
162
+ static bool g_UseGPU = true ;
163
+ static int totalCounter = 0 ;
164
+ static int frameCounter = 0 ;
169
165
170
- - (void )_doRenderingWith : (id <MTLCommandBuffer >) cmd ;
166
+ - (void )_drawTestGpu : (id <MTLCommandBuffer >) cmd ;
171
167
{
172
- static int totalCounter = 0 ;
173
- static int frameCounter = 0 ;
174
- static uint64_t frameTime = 0 ;
175
- uint64_t time1 = mach_absolute_time ();
176
- _computeStartTime = time1;
177
-
178
- uint64_t curNs = (time1 * _clock_timebase.numer ) / _clock_timebase.denom ;
179
- float curT = float (curNs * 1 .0e-9f );
180
-
181
- UpdateTest (curT, totalCounter, kBackbufferWidth , kBackbufferHeight , g_TestFlags);
182
-
183
- #if DO_COMPUTE_GPU
184
168
_backbufferIndex = 1 -_backbufferIndex;
185
169
_uniformBufferIndex = (_uniformBufferIndex + 1 ) % kMaxBuffersInFlight ;
186
170
uint8_t * dataSpheres = (uint8_t *)[_computeSpheres contents ];
@@ -227,40 +211,62 @@ - (void)_doRenderingWith:(id <MTLCommandBuffer>) cmd;
227
211
MTLSize groupCount = {kBackbufferWidth /groupSize.width , kBackbufferHeight /groupSize.height , 1 };
228
212
[enc dispatchThreadgroups: groupCount threadsPerThreadgroup: groupSize];
229
213
[enc endEncoding ];
230
- #else
231
- int rayCount;
232
- DrawTest (curT, totalCounter, kBackbufferWidth , kBackbufferHeight , _backbufferPixels, rayCount, g_TestFlags);
233
- rayCounter += rayCount;
234
- #endif
214
+ }
215
+
216
+ - (void )_doRenderingWith : (id <MTLCommandBuffer >) cmd ;
217
+ {
218
+ static uint64_t frameTime = 0 ;
219
+ uint64_t time1 = mach_absolute_time ();
220
+ _computeStartTime = time1;
221
+
222
+ uint64_t curNs = (time1 * _clock_timebase.numer ) / _clock_timebase.denom ;
223
+ float curT = float (curNs * 1 .0e-9f );
224
+
225
+ UpdateTest (curT, totalCounter, kBackbufferWidth , kBackbufferHeight , g_TestFlags);
226
+
227
+ if (g_UseGPU)
228
+ {
229
+ [self _drawTestGpu: cmd];
230
+ }
231
+ else
232
+ {
233
+ int rayCount;
234
+ DrawTest (curT, totalCounter, kBackbufferWidth , kBackbufferHeight , _backbufferPixels, rayCount, g_TestFlags);
235
+ rayCounter += rayCount;
236
+ }
235
237
236
238
uint64_t time2 = mach_absolute_time ();
237
239
(void )time2;
238
240
++frameCounter;
239
241
++totalCounter;
240
- #if !DO_COMPUTE_GPU
241
- frameTime += (time2-time1);
242
- #else
243
- frameTime += _computeDur;
244
- #endif
242
+ if (g_UseGPU)
243
+ frameTime += _computeDur;
244
+ else
245
+ frameTime += (time2-time1);
245
246
if (frameCounter > 10 )
246
247
{
247
248
uint64_t ns = (frameTime * _clock_timebase.numer ) / _clock_timebase.denom ;
248
249
float s = (float )(ns * 1.0e-9 ) / frameCounter;
249
- char buffer[200 ];
250
- snprintf (buffer, 200 , " %.2fms (%.1f FPS) %.1fMrays/s %.2fMrays/frame frames %i" , s * 1000 .0f , 1 .f / s, rayCounter / frameCounter / s * 1 .0e-6f , rayCounter / frameCounter * 1 .0e-6f , totalCounter);
250
+ char buffer[500 ];
251
+ snprintf (buffer, 200 , " %s: %.2fms (%.1f FPS) %.1fMrays/s %.2fMrays/frame frames %i" ,
252
+ g_UseGPU ? " GPU" : " CPU" ,
253
+ s * 1000 .0f , 1 .f / s, rayCounter / frameCounter / s * 1 .0e-6f , rayCounter / frameCounter * 1 .0e-6f , totalCounter);
251
254
puts (buffer);
252
- #if !TARGET_OS_IPHONE
253
255
NSString * str = [[NSString alloc ] initWithUTF8String: buffer];
256
+ #if TARGET_OS_IPHONE
257
+ _label.text = str;
258
+ #else
254
259
_label.stringValue = str;
255
260
#endif
256
261
frameCounter = 0 ;
257
262
frameTime = 0 ;
258
263
rayCounter = 0 ;
259
264
}
260
-
261
- #if !DO_COMPUTE_GPU
262
- [_backbuffer replaceRegion: MTLRegionMake2D (0 ,0 ,kBackbufferWidth ,kBackbufferHeight ) mipmapLevel: 0 withBytes: _backbufferPixels bytesPerRow: kBackbufferWidth *16 ];
263
- #endif
265
+
266
+ if (!g_UseGPU)
267
+ {
268
+ [_backbuffer replaceRegion: MTLRegionMake2D (0 ,0 ,kBackbufferWidth ,kBackbufferHeight ) mipmapLevel: 0 withBytes: _backbufferPixels bytesPerRow: kBackbufferWidth *16 ];
269
+ }
264
270
}
265
271
266
272
- (void )drawInMTKView : (nonnull MTKView *)view
@@ -270,22 +276,21 @@ - (void)drawInMTKView:(nonnull MTKView *)view
270
276
id <MTLCommandBuffer > cmd = [_commandQueue commandBuffer ];
271
277
272
278
__block dispatch_semaphore_t block_sema = _inFlightSemaphore;
273
- #if DO_COMPUTE_GPU
274
279
int counterIndex = (_uniformBufferIndex+1 )%kMaxBuffersInFlight ;
275
280
id <MTLBuffer > counterBuffer = _computeCounter;
276
- #endif
277
281
[cmd addCompletedHandler: ^(id <MTLCommandBuffer > buffer)
278
282
{
279
- #if DO_COMPUTE_GPU
280
- // There's no easy/proper way to do GPU timing on Metal (or at least I couldn't find any),
281
- // so I'm timing CPU side, from beginning of command buffer invocation to when we get the
282
- // callback that the GPU is done with it. Not 100% proper, but gets similar results to
283
- // what Xcode reports for the GPU duration.
284
- uint64_t time2 = mach_absolute_time ();
285
- _computeDur = (time2 - _computeStartTime);
286
- int rayCount = *(const int *)(((const uint8_t *)[counterBuffer contents ]) + counterIndex*AlignedSize (4 ));
287
- rayCounter += rayCount;
288
- #endif
283
+ if (g_UseGPU)
284
+ {
285
+ // There's no easy/proper way to do GPU timing on Metal (or at least I couldn't find any),
286
+ // so I'm timing CPU side, from beginning of command buffer invocation to when we get the
287
+ // callback that the GPU is done with it. Not 100% proper, but gets similar results to
288
+ // what Xcode reports for the GPU duration.
289
+ uint64_t time2 = mach_absolute_time ();
290
+ _computeDur = (time2 - _computeStartTime);
291
+ int rayCount = *(const int *)(((const uint8_t *)[counterBuffer contents ]) + counterIndex*AlignedSize (4 ));
292
+ rayCounter += rayCount;
293
+ }
289
294
290
295
dispatch_semaphore_signal (block_sema);
291
296
}];
@@ -315,4 +320,24 @@ - (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size
315
320
// printf("View size %ix%i\n", (int)size.width, (int)size.height);
316
321
}
317
322
323
+ -(void )toggleGPU
324
+ {
325
+ g_UseGPU = !g_UseGPU;
326
+ frameCounter = 0 ;
327
+ totalCounter = 0 ;
328
+ }
329
+ -(void )toggleAnimation
330
+ {
331
+ g_TestFlags ^= kFlagAnimate ;
332
+ frameCounter = 0 ;
333
+ totalCounter = 0 ;
334
+ }
335
+ -(void )toggleProgressive
336
+ {
337
+ g_TestFlags ^= kFlagProgressive ;
338
+ frameCounter = 0 ;
339
+ totalCounter = 0 ;
340
+ }
341
+
342
+
318
343
@end
0 commit comments