From a28437d8f21dff45563eaa550a8331698a32babb Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Tue, 5 Sep 2023 14:56:43 -0400 Subject: [PATCH] Updates to code review on swapchain image presentation improvement. - Fix failure building on Xcode 14. - Track frame interval statistics, regardless of whether performance tracking is enabled. - Determine wait time for swapchain presentations from frame intervals. - MVKSwapchain call markFrameInterval() from within mutex lock. - MVKDevice rename addActivityPerformance() to addPerformanceInterval() and addActivityByteCount() to addPerformanceByteCount(). - Add documentation about performance being measured in milliseconds. --- MoltenVK/MoltenVK/API/mvk_private_api.h | 44 +++++++++---------- .../MoltenVK/Commands/MVKCommandBuffer.mm | 2 +- .../Commands/MVKCommandResourceFactory.mm | 8 ++-- MoltenVK/MoltenVK/GPUObjects/MVKDevice.h | 23 +++++----- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 8 ++-- MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 4 +- MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm | 6 +-- MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm | 14 +++--- .../MoltenVK/GPUObjects/MVKShaderModule.mm | 22 +++++----- MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm | 8 ++-- MoltenVK/MoltenVK/GPUObjects/MVKSync.mm | 2 +- 11 files changed, 70 insertions(+), 71 deletions(-) diff --git a/MoltenVK/MoltenVK/API/mvk_private_api.h b/MoltenVK/MoltenVK/API/mvk_private_api.h index e496fc5a..8ed5b754 100644 --- a/MoltenVK/MoltenVK/API/mvk_private_api.h +++ b/MoltenVK/MoltenVK/API/mvk_private_api.h @@ -167,40 +167,40 @@ typedef struct { /** MoltenVK performance of shader compilation activities. */ typedef struct { - MVKPerformanceTracker hashShaderCode; /** Create a hash from the incoming shader code. */ - MVKPerformanceTracker spirvToMSL; /** Convert SPIR-V to MSL source code. */ - MVKPerformanceTracker mslCompile; /** Compile MSL source code into a MTLLibrary. */ - MVKPerformanceTracker mslLoad; /** Load pre-compiled MSL code into a MTLLibrary. */ - MVKPerformanceTracker mslCompress; /** Compress MSL source code after compiling a MTLLibrary, to hold it in a pipeline cache. */ - MVKPerformanceTracker mslDecompress; /** Decompress MSL source code to write the MSL when serializing a pipeline cache. */ - MVKPerformanceTracker shaderLibraryFromCache; /** Retrieve a shader library from the cache, lazily creating it if needed. */ - MVKPerformanceTracker functionRetrieval; /** Retrieve a MTLFunction from a MTLLibrary. */ - MVKPerformanceTracker functionSpecialization; /** Specialize a retrieved MTLFunction. */ - MVKPerformanceTracker pipelineCompile; /** Compile MTLFunctions into a pipeline. */ - MVKPerformanceTracker glslToSPRIV; /** Convert GLSL to SPIR-V code. */ + MVKPerformanceTracker hashShaderCode; /** Create a hash from the incoming shader code, in milliseconds. */ + MVKPerformanceTracker spirvToMSL; /** Convert SPIR-V to MSL source code, in milliseconds. */ + MVKPerformanceTracker mslCompile; /** Compile MSL source code into a MTLLibrary, in milliseconds. */ + MVKPerformanceTracker mslLoad; /** Load pre-compiled MSL code into a MTLLibrary, in milliseconds. */ + MVKPerformanceTracker mslCompress; /** Compress MSL source code after compiling a MTLLibrary, to hold it in a pipeline cache, in milliseconds. */ + MVKPerformanceTracker mslDecompress; /** Decompress MSL source code to write the MSL when serializing a pipeline cache, in milliseconds. */ + MVKPerformanceTracker shaderLibraryFromCache; /** Retrieve a shader library from the cache, lazily creating it if needed, in milliseconds. */ + MVKPerformanceTracker functionRetrieval; /** Retrieve a MTLFunction from a MTLLibrary, in milliseconds. */ + MVKPerformanceTracker functionSpecialization; /** Specialize a retrieved MTLFunction, in milliseconds. */ + MVKPerformanceTracker pipelineCompile; /** Compile MTLFunctions into a pipeline, in milliseconds. */ + MVKPerformanceTracker glslToSPRIV; /** Convert GLSL to SPIR-V code, in milliseconds. */ } 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. */ - MVKPerformanceTracker writePipelineCache; /** Write MSL to pipeline cache data stream. */ - MVKPerformanceTracker readPipelineCache; /** Read MSL from pipeline cache data stream. */ + MVKPerformanceTracker sizePipelineCache; /** Calculate the size of cache data required to write MSL to pipeline cache data stream, in milliseconds. */ + MVKPerformanceTracker writePipelineCache; /** Write MSL to pipeline cache data stream, in milliseconds. */ + MVKPerformanceTracker readPipelineCache; /** Read MSL from pipeline cache data stream, in milliseconds. */ } MVKPipelineCachePerformance; /** MoltenVK performance of queue activities. */ typedef struct { - MVKPerformanceTracker retrieveMTLCommandBuffer; /** Retrieve a MTLCommandBuffer from a MTLQueue. */ - MVKPerformanceTracker commandBufferEncoding; /** Encode a single VkCommandBuffer to a MTLCommandBuffer (excludes MTLCommandBuffer encoding from configured immediate prefilling). */ - MVKPerformanceTracker submitCommandBuffers; /** Submit and encode all VkCommandBuffers in a vkQueueSubmit() operation to MTLCommandBuffers (including both prefilled and deferred encoding). */ - MVKPerformanceTracker mtlCommandBufferExecution; /** Execute a MTLCommandBuffer on the GPU, from commit to completion callback. */ - MVKPerformanceTracker retrieveCAMetalDrawable; /** Retrieve next CAMetalDrawable from a CAMetalLayer. */ - MVKPerformanceTracker presentSwapchains; /** Present the swapchains in a vkQueuePresentKHR() on the GPU, from commit to presentation callback. */ - MVKPerformanceTracker frameInterval; /** Frame presentation interval (1000/FPS). */ + MVKPerformanceTracker retrieveMTLCommandBuffer; /** Retrieve a MTLCommandBuffer from a MTLQueue, in milliseconds. */ + MVKPerformanceTracker commandBufferEncoding; /** Encode a single VkCommandBuffer to a MTLCommandBuffer (excludes MTLCommandBuffer encoding from configured immediate prefilling), in milliseconds. */ + MVKPerformanceTracker submitCommandBuffers; /** Submit and encode all VkCommandBuffers in a vkQueueSubmit() operation to MTLCommandBuffers (including both prefilled and deferred encoding), in milliseconds. */ + MVKPerformanceTracker mtlCommandBufferExecution; /** Execute a MTLCommandBuffer on the GPU, from commit to completion callback, in milliseconds. */ + MVKPerformanceTracker retrieveCAMetalDrawable; /** Retrieve next CAMetalDrawable from a CAMetalLayer, in milliseconds. */ + MVKPerformanceTracker presentSwapchains; /** Present the swapchains in a vkQueuePresentKHR() on the GPU, from commit to presentation callback, in milliseconds. */ + MVKPerformanceTracker frameInterval; /** Frame presentation interval (1000/FPS), in milliseconds. */ } MVKQueuePerformance; /** MoltenVK performance of device activities. */ typedef struct { - MVKPerformanceTracker gpuMemoryAllocated; /** GPU memory allocated (in KB). */ + MVKPerformanceTracker gpuMemoryAllocated; /** GPU memory allocated, in kilobytes. */ } MVKDevicePerformance; /** diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm index 4e0af414..8ac91c26 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm @@ -347,7 +347,7 @@ void MVKCommandEncoder::encode(id mtlCmdBuff, encodeCommands(_cmdBuffer->_head); endEncoding(); - mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.queue.commandBufferEncoding, startTime); + mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.queue.commandBufferEncoding, startTime); } void MVKCommandEncoder::beginEncoding(id mtlCmdBuff, MVKCommandEncodingContext* pEncodingContext) { diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm index b3003507..973db991 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm @@ -623,7 +623,7 @@ id MVKCommandResourceFactory::newFunctionNamed(const char* funcName NSString* nsFuncName = [[NSString alloc] initWithUTF8String: funcName]; // temp retained id mtlFunc = [_mtlLibrary newFunctionWithName: nsFuncName]; // retained [nsFuncName release]; // temp release - _device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime); + _device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime); return mtlFunc; } @@ -636,7 +636,7 @@ id MVKCommandResourceFactory::newMTLFunction(NSString* mslSrcCode, id mtlLib = [getMTLDevice() newLibraryWithSource: mslSrcCode options: getDevice()->getMTLCompileOptions() error: &err]; // temp retain - _device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.mslCompile, startTime); + _device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.mslCompile, startTime); if (err) { reportError(VK_ERROR_INITIALIZATION_FAILED, @@ -645,7 +645,7 @@ id MVKCommandResourceFactory::newMTLFunction(NSString* mslSrcCode, } else { startTime = _device->getPerformanceTimestamp(); mtlFunc = [mtlLib newFunctionWithName: funcName]; - _device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime); + _device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime); } [mtlLib release]; // temp release @@ -689,7 +689,7 @@ void MVKCommandResourceFactory::initMTLLibrary() { options: getDevice()->getMTLCompileOptions() error: &err]; // retained MVKAssert( !err, "Could not compile command shaders (Error code %li):\n%s", (long)err.code, err.localizedDescription.UTF8String); - _device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.mslCompile, startTime); + _device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.mslCompile, startTime); } } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index 5d4c328b..5ae7f5ec 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -689,26 +689,23 @@ public: /** * If performance is being tracked, returns a monotonic timestamp value for use performance timestamping. - * * The returned value corresponds to the number of CPU "ticks" since the app was initialized. * - * Calling this value twice, subtracting the first value from the second, and then multiplying - * the result by the value returned by mvkGetTimestampPeriod() will provide an indication of the - * number of nanoseconds between the two calls. The convenience function mvkGetElapsedMilliseconds() - * can be used to perform this calculation. + * Call this function twice, then use the functions mvkGetElapsedNanoseconds() or mvkGetElapsedMilliseconds() + * to determine the number of nanoseconds or milliseconds between the two calls. */ uint64_t getPerformanceTimestamp() { return _isPerformanceTracking ? mvkGetTimestamp() : 0; } /** - * If performance is being tracked, adds the performance for an activity with a duration - * interval between the start and end times, to the given performance statistics. + * If performance is being tracked, adds the performance for an activity with a duration interval + * between the start and end times, measured in milliseconds, to the given performance statistics. * * If endTime is zero or not supplied, the current time is used. */ - void addActivityPerformance(MVKPerformanceTracker& activityTracker, + void addPerformanceInterval(MVKPerformanceTracker& perfTracker, uint64_t startTime, uint64_t endTime = 0) { if (_isPerformanceTracking) { - updateActivityPerformance(activityTracker, mvkGetElapsedMilliseconds(startTime, endTime)); + updateActivityPerformance(perfTracker, mvkGetElapsedMilliseconds(startTime, endTime)); } }; @@ -716,12 +713,15 @@ public: * If performance is being tracked, adds the performance for an activity * with a kilobyte count, to the given performance statistics. */ - void addActivityByteCount(MVKPerformanceTracker& activityTracker, uint64_t byteCount) { + void addPerformanceByteCount(MVKPerformanceTracker& perfTracker, uint64_t byteCount) { if (_isPerformanceTracking) { - updateActivityPerformance(activityTracker, double(byteCount / KIBI)); + updateActivityPerformance(perfTracker, double(byteCount / KIBI)); } }; + /** Updates the given performance statistic. */ + void updateActivityPerformance(MVKPerformanceTracker& activity, double currentValue); + /** Populates the specified statistics structure from the current activity performance statistics. */ void getPerformanceStatistics(MVKPerformanceStatistics* pPerf); @@ -897,7 +897,6 @@ protected: void logActivityInline(MVKPerformanceTracker& activity, MVKPerformanceStatistics& perfStats); void logActivityDuration(MVKPerformanceTracker& activity, MVKPerformanceStatistics& perfStats, bool isInline = false); void logActivityByteCount(MVKPerformanceTracker& activity, MVKPerformanceStatistics& perfStats, bool isInline = false); - void updateActivityPerformance(MVKPerformanceTracker& activity, double currentValue); void getDescriptorVariableDescriptorCountLayoutSupport(const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport, VkDescriptorSetVariableDescriptorCountLayoutSupport* pVarDescSetCountSupport); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index d44e6492..1930ceed 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -3058,7 +3058,7 @@ uint64_t MVKPhysicalDevice::getVRAMSize() { // If possible, retrieve from the MTLDevice, otherwise from available memory size, or a fixed conservative estimate. uint64_t MVKPhysicalDevice::getRecommendedMaxWorkingSetSize() { -#if MVK_XCODE_14 || MVK_MACOS +#if MVK_XCODE_15 || MVK_MACOS if ( [_mtlDevice respondsToSelector: @selector(recommendedMaxWorkingSetSize)]) { return _mtlDevice.recommendedMaxWorkingSetSize; } @@ -4194,7 +4194,7 @@ void MVKDevice::updateActivityPerformance(MVKPerformanceTracker& activity, doubl double total = (activity.average * activity.count++) + currentValue; activity.average = total / activity.count; - if (mvkConfig().activityPerformanceLoggingStyle == MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_IMMEDIATE) { + if (_isPerformanceTracking && mvkConfig().activityPerformanceLoggingStyle == MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_IMMEDIATE) { logActivityInline(activity, _performanceStatistics); } } @@ -4299,8 +4299,8 @@ MVKActivityPerformanceValueType MVKDevice::getActivityPerformanceValueType(MVKPe } void MVKDevice::getPerformanceStatistics(MVKPerformanceStatistics* pPerf) { - addActivityByteCount(_performanceStatistics.device.gpuMemoryAllocated, - _physicalDevice->getCurrentAllocatedSize()); + addPerformanceByteCount(_performanceStatistics.device.gpuMemoryAllocated, + _physicalDevice->getCurrentAllocatedSize()); lock_guard lock(_perfLock); if (pPerf) { *pPerf = _performanceStatistics; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index fa87643a..b632e78b 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -1293,7 +1293,7 @@ id MVKPresentableSwapchainImage::getCAMetalDrawable() { for (uint32_t attemptIdx = 0; !_mtlDrawable && attemptIdx < attemptCnt; attemptIdx++) { uint64_t startTime = _device->getPerformanceTimestamp(); _mtlDrawable = [_swapchain->_surface->getCAMetalLayer().nextDrawable retain]; // retained - _device->addActivityPerformance(_device->_performanceStatistics.queue.retrieveCAMetalDrawable, startTime); + _device->addPerformanceInterval(_device->_performanceStatistics.queue.retrieveCAMetalDrawable, startTime); } if ( !_mtlDrawable ) { reportError(VK_ERROR_OUT_OF_POOL_MEMORY, "CAMetalDrawable could not be acquired after %d attempts.", attemptCnt); } } @@ -1398,7 +1398,7 @@ void MVKPresentableSwapchainImage::endPresentation(const MVKImagePresentInfo& pr // If I have become detached from the swapchain, it means the swapchain, and possibly the // VkDevice, have been destroyed by the time of this callback, so do not reference them. lock_guard lock(_detachmentLock); - if (_device) { _device->addActivityPerformance(_device->_performanceStatistics.queue.presentSwapchains, _presentationStartTime); } + if (_device) { _device->addPerformanceInterval(_device->_performanceStatistics.queue.presentSwapchains, _presentationStartTime); } if (_swapchain) { _swapchain->endPresentation(presentInfo, actualPresentTime); } } presentInfo.queue->endPresentation(presentInfo); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm index 13f59b6b..e3da96b3 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -2269,7 +2269,7 @@ VkResult MVKPipelineCache::writeDataImpl(size_t* pDataSize, void* pData) { // Serializes the data in this cache to a stream void MVKPipelineCache::writeData(ostream& outstream, bool isCounting) { #if MVK_USE_CEREAL - MVKPerformanceTracker& activityTracker = isCounting + MVKPerformanceTracker& perfTracker = isCounting ? _device->_performanceStatistics.pipelineCache.sizePipelineCache : _device->_performanceStatistics.pipelineCache.writePipelineCache; @@ -2297,7 +2297,7 @@ void MVKPipelineCache::writeData(ostream& outstream, bool isCounting) { writer(cacheIter.getShaderConversionConfig()); writer(cacheIter.getShaderConversionResultInfo()); writer(cacheIter.getCompressedMSL()); - _device->addActivityPerformance(activityTracker, startTime); + _device->addPerformanceInterval(perfTracker, startTime); } } @@ -2366,7 +2366,7 @@ void MVKPipelineCache::readData(const VkPipelineCacheCreateInfo* pCreateInfo) { // Add the shader library to the staging cache. MVKShaderLibraryCache* slCache = getShaderLibraryCache(smKey); - _device->addActivityPerformance(_device->_performanceStatistics.pipelineCache.readPipelineCache, startTime); + _device->addPerformanceInterval(_device->_performanceStatistics.pipelineCache.readPipelineCache, startTime); slCache->addShaderLibrary(&shaderConversionConfig, resultInfo, compressedMSL); break; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm index 293f50ef..c104deed 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm @@ -150,8 +150,9 @@ VkResult MVKQueue::waitIdle(MVKCommandUse cmdUse) { // few frames for that to happen. If there are still swapchain presentations that haven't completed, // log a warning, and force them to end presentation, so the images and drawables will be released. void MVKQueue::waitSwapchainPresentations(MVKCommandUse cmdUse) { - auto waitFrames = _device->_pMetalFeatures->maxSwapchainImageCount + 2; - if (_presentationCompletionBlocker.wait((waitFrames/60.0) * 1e9)) { return; } + uint32_t waitFrames = _device->_pMetalFeatures->maxSwapchainImageCount + 2; + uint64_t waitNanos = waitFrames * _device->_performanceStatistics.queue.frameInterval.average * 1e6; + if (_presentationCompletionBlocker.wait(waitNanos)) { return; } auto imgCnt = _presentationCompletionBlocker.getReservationCount(); MVKPresentableSwapchainImage* images[imgCnt]; @@ -173,7 +174,7 @@ void MVKQueue::waitSwapchainPresentations(MVKCommandUse cmdUse) { // Wait for forced presentation completions. If we still have unfinished swapchain image // presentations, log a warning, and force each image to end, so that it can be released. - if ( !_presentationCompletionBlocker.wait((waitFrames/60.0) * 1e9) ) { + if ( !_presentationCompletionBlocker.wait(waitNanos) ) { reportWarning(VK_TIMEOUT, "%s timed out after %d frames while awaiting %d swapchain image presentations to complete.", mvkVkCommandName(cmdUse), waitFrames * 2, _presentationCompletionBlocker.getReservationCount()); for (size_t imgIdx = 0; imgIdx < imgCnt; imgIdx++) { @@ -203,7 +204,7 @@ id MVKQueue::getMTLCommandBuffer(MVKCommandUse cmdUse, bool re } else { mtlCmdBuff = [_mtlQueue commandBufferWithUnretainedReferences]; } - mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.queue.retrieveMTLCommandBuffer, startTime); + mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.queue.retrieveMTLCommandBuffer, startTime); NSString* mtlCmdBuffLabel = getMTLCommandBufferLabel(cmdUse); setLabelIfNotNil(mtlCmdBuff, mtlCmdBuffLabel); [mtlCmdBuff addCompletedHandler: ^(id mtlCB) { handleMTLCommandBufferError(mtlCB); }]; @@ -496,7 +497,7 @@ VkResult MVKQueueCommandBufferSubmission::commitActiveMTLCommandBuffer(bool sign MVKDevice* mvkDev = getDevice(); uint64_t startTime = mvkDev->getPerformanceTimestamp(); [mtlCmdBuff addCompletedHandler: ^(id mtlCB) { - mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.queue.mtlCommandBufferExecution, startTime); + mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.queue.mtlCommandBufferExecution, startTime); if (signalCompletion) { this->finish(); } // Must be the last thing the completetion callback does. }]; @@ -592,7 +593,7 @@ void MVKQueueFullCommandBufferSubmission::submitCommandBuffers() { for (auto& cb : _cmdBuffers) { cb->submit(this, &_encodingContext); } - mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.queue.submitCommandBuffers, startTime); + mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.queue.submitCommandBuffers, startTime); } template @@ -602,7 +603,6 @@ MVKQueueFullCommandBufferSubmission::MVKQueueFullCommandBufferSubmission(MVKQ MVKCommandUse cmdUse) : MVKQueueCommandBufferSubmission(queue, pSubmit, fence, cmdUse) { - // pSubmit can be null if just tracking the fence alone if (pSubmit) { uint32_t cbCnt = pSubmit->commandBufferCount; _cmdBuffers.reserve(cbCnt); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm index a47a65b7..90831498 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm @@ -80,7 +80,7 @@ MVKMTLFunction MVKShaderLibrary::getMTLFunction(const VkSpecializationInfo* pSpe uint64_t startTime = pShaderFeedback ? mvkGetTimestamp() : mvkDev->getPerformanceTimestamp(); id mtlFunc = [[_mtlLibrary newFunctionWithName: mtlFuncName] autorelease]; - mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.functionRetrieval, startTime); + mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.shaderCompilation.functionRetrieval, startTime); if (pShaderFeedback) { if (mtlFunc) { mvkEnableFlags(pShaderFeedback->flags, VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT); @@ -156,7 +156,7 @@ void MVKShaderLibrary::compressMSL(const string& msl) { MVKDevice* mvkDev = _owner->getDevice(); uint64_t startTime = mvkDev->getPerformanceTimestamp(); _compressedMSL.compress(msl, mvkConfig().shaderSourceCompressionAlgorithm); - mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.mslCompress, startTime); + mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.shaderCompilation.mslCompress, startTime); } // Decompresses the cached MSL into the string. @@ -164,7 +164,7 @@ void MVKShaderLibrary::decompressMSL(string& msl) { MVKDevice* mvkDev = _owner->getDevice(); uint64_t startTime = mvkDev->getPerformanceTimestamp(); _compressedMSL.decompress(msl); - mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.mslDecompress, startTime); + mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.shaderCompilation.mslDecompress, startTime); } MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner, @@ -207,7 +207,7 @@ MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner, handleCompilationError(err, "Compiled shader module creation"); [shdrData release]; } - mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.mslLoad, startTime); + mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.shaderCompilation.mslLoad, startTime); } MVKShaderLibrary::MVKShaderLibrary(const MVKShaderLibrary& other) { @@ -283,7 +283,7 @@ MVKShaderLibrary* MVKShaderLibraryCache::findShaderLibrary(SPIRVToMSLConversionC if (slPair.first.matches(*pShaderConfig)) { pShaderConfig->alignWith(slPair.first); MVKDevice* mvkDev = _owner->getDevice(); - mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.shaderLibraryFromCache, startTime); + mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.shaderCompilation.shaderLibraryFromCache, startTime); if (pShaderFeedback) { pShaderFeedback->duration += mvkGetElapsedNanoseconds(startTime); } @@ -363,7 +363,7 @@ bool MVKShaderModule::convert(SPIRVToMSLConversionConfiguration* pShaderConfig, GLSLToSPIRVConversionResult glslConversionResult; uint64_t startTime = _device->getPerformanceTimestamp(); bool wasConverted = _glslConverter.convert(getMVKGLSLConversionShaderStage(pShaderConfig), glslConversionResult, shouldLogCode, false); - _device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.glslToSPRIV, startTime); + _device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.glslToSPRIV, startTime); if (wasConverted) { if (shouldLogCode) { MVKLogInfo("%s", glslConversionResult.resultLog.c_str()); } @@ -376,7 +376,7 @@ bool MVKShaderModule::convert(SPIRVToMSLConversionConfiguration* pShaderConfig, uint64_t startTime = _device->getPerformanceTimestamp(); bool wasConverted = _spvConverter.convert(*pShaderConfig, conversionResult, shouldLogCode, shouldLogCode, shouldLogEstimatedGLSL); - _device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.spirvToMSL, startTime); + _device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.spirvToMSL, startTime); if (wasConverted) { if (shouldLogCode) { MVKLogInfo("%s", conversionResult.resultLog.c_str()); } @@ -436,7 +436,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device, uint64_t startTime = _device->getPerformanceTimestamp(); codeHash = mvkHash(pCreateInfo->pCode, spvCount); - _device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime); + _device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime); _spvConverter.setSPIRV(pCreateInfo->pCode, spvCount); @@ -450,7 +450,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device, uint64_t startTime = _device->getPerformanceTimestamp(); codeHash = mvkHash(&magicNum); codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash); - _device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime); + _device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime); SPIRVToMSLConversionResult conversionResult; conversionResult.msl = pMSLCode; @@ -466,7 +466,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device, uint64_t startTime = _device->getPerformanceTimestamp(); codeHash = mvkHash(&magicNum); codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash); - _device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime); + _device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime); _directMSLLibrary = new MVKShaderLibrary(this, (void*)(pMSLCode), mslCodeLen); @@ -479,7 +479,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device, uint64_t startTime = _device->getPerformanceTimestamp(); codeHash = mvkHash(pGLSL, codeSize); - _device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime); + _device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime); _glslConverter.setGLSL(pGLSL, glslLen); } else { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm index f326f82e..159c2edf 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm @@ -159,13 +159,14 @@ void MVKSwapchain::renderWatermark(id mtlTexture, idgetPerformanceTimestamp(); + _lastFrameTime = mvkGetTimestamp(); if (prevFrameTime == 0) { return; } // First frame starts at first presentation - _device->addActivityPerformance(_device->_performanceStatistics.queue.frameInterval, prevFrameTime, _lastFrameTime); + _device->updateActivityPerformance(_device->_performanceStatistics.queue.frameInterval, mvkGetElapsedMilliseconds(prevFrameTime, _lastFrameTime)); auto& mvkCfg = mvkConfig(); bool shouldLogOnFrames = mvkCfg.performanceTracking && mvkCfg.activityPerformanceLoggingStyle == MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_FRAME_COUNT; @@ -244,10 +245,9 @@ VkResult MVKSwapchain::getPastPresentationTiming(uint32_t *pCount, VkPastPresent void MVKSwapchain::beginPresentation(const MVKImagePresentInfo& presentInfo) {} void MVKSwapchain::endPresentation(const MVKImagePresentInfo& presentInfo, uint64_t actualPresentTime) { + std::lock_guard lock(_presentHistoryLock); markFrameInterval(); - - std::lock_guard lock(_presentHistoryLock); if (_presentHistoryCount < kMaxPresentationHistory) { _presentHistoryCount++; } else { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm index fb1e0190..b7a4a64d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm @@ -588,7 +588,7 @@ void MVKMetalCompiler::compile(unique_lock& lock, dispatch_block_t block) if (_compileError) { handleError(); } - mvkDev->addActivityPerformance(*_pPerformanceTracker, _startTime); + mvkDev->addPerformanceInterval(*_pPerformanceTracker, _startTime); } void MVKMetalCompiler::handleError() {