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.
This commit is contained in:
Bill Hollings 2023-09-05 14:56:43 -04:00
parent 9f64faadbc
commit a28437d8f2
11 changed files with 70 additions and 71 deletions

View File

@ -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;
/**

View File

@ -347,7 +347,7 @@ void MVKCommandEncoder::encode(id<MTLCommandBuffer> mtlCmdBuff,
encodeCommands(_cmdBuffer->_head);
endEncoding();
mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.queue.commandBufferEncoding, startTime);
mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.queue.commandBufferEncoding, startTime);
}
void MVKCommandEncoder::beginEncoding(id<MTLCommandBuffer> mtlCmdBuff, MVKCommandEncodingContext* pEncodingContext) {

View File

@ -623,7 +623,7 @@ id<MTLFunction> MVKCommandResourceFactory::newFunctionNamed(const char* funcName
NSString* nsFuncName = [[NSString alloc] initWithUTF8String: funcName]; // temp retained
id<MTLFunction> 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<MTLFunction> MVKCommandResourceFactory::newMTLFunction(NSString* mslSrcCode,
id<MTLLibrary> 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<MTLFunction> 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);
}
}

View File

@ -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);

View File

@ -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<mutex> lock(_perfLock);
if (pPerf) { *pPerf = _performanceStatistics; }

View File

@ -1293,7 +1293,7 @@ id<CAMetalDrawable> 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<mutex> 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);

View File

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

View File

@ -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<MTLCommandBuffer> 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<MTLCommandBuffer> mtlCB) { handleMTLCommandBufferError(mtlCB); }];
@ -496,7 +497,7 @@ VkResult MVKQueueCommandBufferSubmission::commitActiveMTLCommandBuffer(bool sign
MVKDevice* mvkDev = getDevice();
uint64_t startTime = mvkDev->getPerformanceTimestamp();
[mtlCmdBuff addCompletedHandler: ^(id<MTLCommandBuffer> 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<N>::submitCommandBuffers() {
for (auto& cb : _cmdBuffers) { cb->submit(this, &_encodingContext); }
mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.queue.submitCommandBuffers, startTime);
mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.queue.submitCommandBuffers, startTime);
}
template <size_t N>
@ -602,7 +603,6 @@ MVKQueueFullCommandBufferSubmission<N>::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);

View File

@ -80,7 +80,7 @@ MVKMTLFunction MVKShaderLibrary::getMTLFunction(const VkSpecializationInfo* pSpe
uint64_t startTime = pShaderFeedback ? mvkGetTimestamp() : mvkDev->getPerformanceTimestamp();
id<MTLFunction> 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 {

View File

@ -159,13 +159,14 @@ void MVKSwapchain::renderWatermark(id<MTLTexture> mtlTexture, id<MTLCommandBuffe
}
// Calculates and remembers the time interval between frames.
// Not threadsafe. Ensure this is called from a threadsafe environment.
void MVKSwapchain::markFrameInterval() {
uint64_t prevFrameTime = _lastFrameTime;
_lastFrameTime = _device->getPerformanceTimestamp();
_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<std::mutex> lock(_presentHistoryLock);
markFrameInterval();
std::lock_guard<std::mutex> lock(_presentHistoryLock);
if (_presentHistoryCount < kMaxPresentationHistory) {
_presentHistoryCount++;
} else {

View File

@ -588,7 +588,7 @@ void MVKMetalCompiler::compile(unique_lock<mutex>& lock, dispatch_block_t block)
if (_compileError) { handleError(); }
mvkDev->addActivityPerformance(*_pPerformanceTracker, _startTime);
mvkDev->addPerformanceInterval(*_pPerformanceTracker, _startTime);
}
void MVKMetalCompiler::handleError() {