Merge pull request #810 from billhollings/master
Track performance of CAMetalLayer nextDrawable call.
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index 0cf6b29..0871d7e 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -22,6 +22,7 @@
- Fix crash when app does not use queue family zero.
- Fix buffer offset in `vkCmdPushDescriptorSet()` for non-dedicated buffer memory.
- Fix Metal validation error on push constant sizing differences between C and MSL structs.
+- Track performance of `CAMetalLayer nextDrawable` call.
- Update `VK_MVK_MOLTENVK_SPEC_VERSION` to `24`.
diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
index 0e30b48..72226de 100644
--- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
+++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
@@ -608,7 +608,6 @@
MVKPerformanceTracker glslToSPRIV; /** Convert GLSL to SPIR-V code. */
} MVKShaderCompilationPerformance;
-
/** MoltenVK performance of pipeline cache activities. */
typedef struct {
MVKPerformanceTracker sizePipelineCache; /** Calculate the size of cache data required to write MSL to pipeline cache data stream. */
@@ -620,6 +619,7 @@
typedef struct {
MVKPerformanceTracker mtlQueueAccess; /** Create an MTLCommmandQueue or access an existing cached instance. */
MVKPerformanceTracker mtlCommandBufferCompletion; /** Completion of a MTLCommandBuffer on the GPU, from commit to completion callback. */
+ MVKPerformanceTracker nextCAMetalDrawable; /** Retrieve next CAMetalDrawable from CAMetalLayer during presentation. */
} MVKQueuePerformance;
/**
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index 3d72136..b6ed1e8 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -2493,6 +2493,7 @@
if (&activityTracker == &_performanceStatistics.pipelineCache.readPipelineCache) { return "read MSL from pipeline cache"; }
if (&activityTracker == &_performanceStatistics.queue.mtlQueueAccess) { return "access MTLCommandQueue"; }
if (&activityTracker == &_performanceStatistics.queue.mtlCommandBufferCompletion) { return "complete MTLCommandBuffer"; }
+ if (&activityTracker == &_performanceStatistics.queue.nextCAMetalDrawable) { return "retrieve a CAMetalDrawable from CAMetalLayer"; }
return "Unknown performance activity";
}
@@ -2638,6 +2639,7 @@
_performanceStatistics.pipelineCache.readPipelineCache = initPerf;
_performanceStatistics.queue.mtlQueueAccess = initPerf;
_performanceStatistics.queue.mtlCommandBufferCompletion = initPerf;
+ _performanceStatistics.queue.nextCAMetalDrawable = initPerf;
}
void MVKDevice::initPhysicalDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo* pCreateInfo) {
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
index d2cd34b..6be77dd 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
@@ -269,7 +269,7 @@
// otherwise if this instance has no content, it will not finish() and be destroyed.
if (signalCompletion || _trackPerformance) {
[getActiveMTLCommandBuffer() addCompletedHandler: ^(id<MTLCommandBuffer> mtlCmdBuff) {
- _queue->_device->addActivityPerformance(mkvDev->_performanceStatistics.queue.mtlCommandBufferCompletion, startTime);
+ mkvDev->addActivityPerformance(mkvDev->_performanceStatistics.queue.mtlCommandBufferCompletion, startTime);
if (signalCompletion) { this->finish(); }
}];
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
index 3d146fd..003db8f 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
@@ -346,15 +346,19 @@
#pragma mark Metal
id<CAMetalDrawable> MVKSwapchain::getCAMetalDrawable(uint32_t imageIndex) {
- if ( _mtlDrawables[imageIndex] ) { return _mtlDrawables[imageIndex]; }
- @autoreleasepool { // Allow auto-released drawable object to be reclaimed before end of loop
- id<CAMetalDrawable> nextDrwbl = nil;
- while ( !(nextDrwbl = [_mtlLayer nextDrawable]) ) {
- MVKLogError("Drawable could not be retrieved! Elapsed time: %.6f ms.", mvkGetElapsedMilliseconds());
- }
- _mtlDrawables[imageIndex] = [nextDrwbl retain];
- }
- return _mtlDrawables[imageIndex];
+ id<CAMetalDrawable> nextDrwbl = _mtlDrawables[imageIndex];
+ while ( !nextDrwbl ) {
+ @autoreleasepool { // Allow auto-released drawable object to be reclaimed before end of loop
+ uint64_t startTime = _device->getPerformanceTimestamp();
+
+ nextDrwbl = _mtlLayer.nextDrawable;
+ if ( !nextDrwbl ) { MVKLogError("Drawable could not be retrieved! Elapsed time: %.6f ms.", mvkGetElapsedMilliseconds()); }
+ _mtlDrawables[imageIndex] = [nextDrwbl retain];
+
+ _device->addActivityPerformance(_device->_performanceStatistics.queue.nextCAMetalDrawable, startTime);
+ }
+ }
+ return nextDrwbl;
}
// Removes and releases a Metal drawable object, so that it can be lazily created by getCAMetalDrawable().