From e6224803f6801dd1fb19c875feef545e1da4615f Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Mon, 6 Jan 2020 09:38:14 -0500 Subject: [PATCH] Track performance of CAMetalLayer nextDrawable call. Add MVKQueuePerformance::nextCAMetalDrawable. --- Docs/Whats_New.md | 1 + MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h | 2 +- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 2 ++ MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm | 2 +- MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm | 22 ++++++++++++-------- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 0cf6b295..0871d7ea 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -22,6 +22,7 @@ Released TBD - 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 0e30b482..72226dea 100644 --- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h +++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h @@ -608,7 +608,6 @@ typedef struct { 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 { 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 3d721361..b6ed1e8c 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -2493,6 +2493,7 @@ const char* MVKDevice::getActivityPerformanceDescription(MVKPerformanceTracker& 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 @@ void MVKDevice::initPerformanceTracking() { _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 d2cd34ba..6be77ddf 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm @@ -269,7 +269,7 @@ void MVKQueueCommandBufferSubmission::commitActiveMTLCommandBuffer(bool signalCo // otherwise if this instance has no content, it will not finish() and be destroyed. if (signalCompletion || _trackPerformance) { [getActiveMTLCommandBuffer() addCompletedHandler: ^(id 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 3d146fdf..003db8fb 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm @@ -346,15 +346,19 @@ void MVKSwapchain::setHDRMetadataEXT(const VkHdrMetadataEXT& metadata) { #pragma mark Metal id 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 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 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().