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:
parent
9f64faadbc
commit
a28437d8f2
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user