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. */
|
/** MoltenVK performance of shader compilation activities. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MVKPerformanceTracker hashShaderCode; /** Create a hash from the incoming shader code. */
|
MVKPerformanceTracker hashShaderCode; /** Create a hash from the incoming shader code, in milliseconds. */
|
||||||
MVKPerformanceTracker spirvToMSL; /** Convert SPIR-V to MSL source code. */
|
MVKPerformanceTracker spirvToMSL; /** Convert SPIR-V to MSL source code, in milliseconds. */
|
||||||
MVKPerformanceTracker mslCompile; /** Compile MSL source code into a MTLLibrary. */
|
MVKPerformanceTracker mslCompile; /** Compile MSL source code into a MTLLibrary, in milliseconds. */
|
||||||
MVKPerformanceTracker mslLoad; /** Load pre-compiled MSL code into a MTLLibrary. */
|
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. */
|
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. */
|
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. */
|
MVKPerformanceTracker shaderLibraryFromCache; /** Retrieve a shader library from the cache, lazily creating it if needed, in milliseconds. */
|
||||||
MVKPerformanceTracker functionRetrieval; /** Retrieve a MTLFunction from a MTLLibrary. */
|
MVKPerformanceTracker functionRetrieval; /** Retrieve a MTLFunction from a MTLLibrary, in milliseconds. */
|
||||||
MVKPerformanceTracker functionSpecialization; /** Specialize a retrieved MTLFunction. */
|
MVKPerformanceTracker functionSpecialization; /** Specialize a retrieved MTLFunction, in milliseconds. */
|
||||||
MVKPerformanceTracker pipelineCompile; /** Compile MTLFunctions into a pipeline. */
|
MVKPerformanceTracker pipelineCompile; /** Compile MTLFunctions into a pipeline, in milliseconds. */
|
||||||
MVKPerformanceTracker glslToSPRIV; /** Convert GLSL to SPIR-V code. */
|
MVKPerformanceTracker glslToSPRIV; /** Convert GLSL to SPIR-V code, in milliseconds. */
|
||||||
} MVKShaderCompilationPerformance;
|
} MVKShaderCompilationPerformance;
|
||||||
|
|
||||||
/** MoltenVK performance of pipeline cache activities. */
|
/** MoltenVK performance of pipeline cache activities. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MVKPerformanceTracker sizePipelineCache; /** Calculate the size of cache data required to write MSL to 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. */
|
MVKPerformanceTracker writePipelineCache; /** Write MSL to pipeline cache data stream, in milliseconds. */
|
||||||
MVKPerformanceTracker readPipelineCache; /** Read MSL from pipeline cache data stream. */
|
MVKPerformanceTracker readPipelineCache; /** Read MSL from pipeline cache data stream, in milliseconds. */
|
||||||
} MVKPipelineCachePerformance;
|
} MVKPipelineCachePerformance;
|
||||||
|
|
||||||
/** MoltenVK performance of queue activities. */
|
/** MoltenVK performance of queue activities. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MVKPerformanceTracker retrieveMTLCommandBuffer; /** Retrieve a MTLCommandBuffer from a MTLQueue. */
|
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). */
|
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). */
|
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. */
|
MVKPerformanceTracker mtlCommandBufferExecution; /** Execute a MTLCommandBuffer on the GPU, from commit to completion callback, in milliseconds. */
|
||||||
MVKPerformanceTracker retrieveCAMetalDrawable; /** Retrieve next CAMetalDrawable from a CAMetalLayer. */
|
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. */
|
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). */
|
MVKPerformanceTracker frameInterval; /** Frame presentation interval (1000/FPS), in milliseconds. */
|
||||||
} MVKQueuePerformance;
|
} MVKQueuePerformance;
|
||||||
|
|
||||||
/** MoltenVK performance of device activities. */
|
/** MoltenVK performance of device activities. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MVKPerformanceTracker gpuMemoryAllocated; /** GPU memory allocated (in KB). */
|
MVKPerformanceTracker gpuMemoryAllocated; /** GPU memory allocated, in kilobytes. */
|
||||||
} MVKDevicePerformance;
|
} MVKDevicePerformance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -347,7 +347,7 @@ void MVKCommandEncoder::encode(id<MTLCommandBuffer> mtlCmdBuff,
|
|||||||
encodeCommands(_cmdBuffer->_head);
|
encodeCommands(_cmdBuffer->_head);
|
||||||
endEncoding();
|
endEncoding();
|
||||||
|
|
||||||
mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.queue.commandBufferEncoding, startTime);
|
mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.queue.commandBufferEncoding, startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKCommandEncoder::beginEncoding(id<MTLCommandBuffer> mtlCmdBuff, MVKCommandEncodingContext* pEncodingContext) {
|
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
|
NSString* nsFuncName = [[NSString alloc] initWithUTF8String: funcName]; // temp retained
|
||||||
id<MTLFunction> mtlFunc = [_mtlLibrary newFunctionWithName: nsFuncName]; // retained
|
id<MTLFunction> mtlFunc = [_mtlLibrary newFunctionWithName: nsFuncName]; // retained
|
||||||
[nsFuncName release]; // temp release
|
[nsFuncName release]; // temp release
|
||||||
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
|
_device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
|
||||||
return mtlFunc;
|
return mtlFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,7 +636,7 @@ id<MTLFunction> MVKCommandResourceFactory::newMTLFunction(NSString* mslSrcCode,
|
|||||||
id<MTLLibrary> mtlLib = [getMTLDevice() newLibraryWithSource: mslSrcCode
|
id<MTLLibrary> mtlLib = [getMTLDevice() newLibraryWithSource: mslSrcCode
|
||||||
options: getDevice()->getMTLCompileOptions()
|
options: getDevice()->getMTLCompileOptions()
|
||||||
error: &err]; // temp retain
|
error: &err]; // temp retain
|
||||||
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.mslCompile, startTime);
|
_device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.mslCompile, startTime);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
reportError(VK_ERROR_INITIALIZATION_FAILED,
|
reportError(VK_ERROR_INITIALIZATION_FAILED,
|
||||||
@ -645,7 +645,7 @@ id<MTLFunction> MVKCommandResourceFactory::newMTLFunction(NSString* mslSrcCode,
|
|||||||
} else {
|
} else {
|
||||||
startTime = _device->getPerformanceTimestamp();
|
startTime = _device->getPerformanceTimestamp();
|
||||||
mtlFunc = [mtlLib newFunctionWithName: funcName];
|
mtlFunc = [mtlLib newFunctionWithName: funcName];
|
||||||
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
|
_device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
[mtlLib release]; // temp release
|
[mtlLib release]; // temp release
|
||||||
@ -689,7 +689,7 @@ void MVKCommandResourceFactory::initMTLLibrary() {
|
|||||||
options: getDevice()->getMTLCompileOptions()
|
options: getDevice()->getMTLCompileOptions()
|
||||||
error: &err]; // retained
|
error: &err]; // retained
|
||||||
MVKAssert( !err, "Could not compile command shaders (Error code %li):\n%s", (long)err.code, err.localizedDescription.UTF8String);
|
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.
|
* 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.
|
* 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
|
* Call this function twice, then use the functions mvkGetElapsedNanoseconds() or mvkGetElapsedMilliseconds()
|
||||||
* the result by the value returned by mvkGetTimestampPeriod() will provide an indication of the
|
* to determine the number of nanoseconds or milliseconds between the two calls.
|
||||||
* number of nanoseconds between the two calls. The convenience function mvkGetElapsedMilliseconds()
|
|
||||||
* can be used to perform this calculation.
|
|
||||||
*/
|
*/
|
||||||
uint64_t getPerformanceTimestamp() { return _isPerformanceTracking ? mvkGetTimestamp() : 0; }
|
uint64_t getPerformanceTimestamp() { return _isPerformanceTracking ? mvkGetTimestamp() : 0; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If performance is being tracked, adds the performance for an activity with a duration
|
* If performance is being tracked, adds the performance for an activity with a duration interval
|
||||||
* interval between the start and end times, to the given performance statistics.
|
* 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.
|
* 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) {
|
uint64_t startTime, uint64_t endTime = 0) {
|
||||||
if (_isPerformanceTracking) {
|
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
|
* If performance is being tracked, adds the performance for an activity
|
||||||
* with a kilobyte count, to the given performance statistics.
|
* 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) {
|
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. */
|
/** Populates the specified statistics structure from the current activity performance statistics. */
|
||||||
void getPerformanceStatistics(MVKPerformanceStatistics* pPerf);
|
void getPerformanceStatistics(MVKPerformanceStatistics* pPerf);
|
||||||
|
|
||||||
@ -897,7 +897,6 @@ protected:
|
|||||||
void logActivityInline(MVKPerformanceTracker& activity, MVKPerformanceStatistics& perfStats);
|
void logActivityInline(MVKPerformanceTracker& activity, MVKPerformanceStatistics& perfStats);
|
||||||
void logActivityDuration(MVKPerformanceTracker& activity, MVKPerformanceStatistics& perfStats, bool isInline = false);
|
void logActivityDuration(MVKPerformanceTracker& activity, MVKPerformanceStatistics& perfStats, bool isInline = false);
|
||||||
void logActivityByteCount(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,
|
void getDescriptorVariableDescriptorCountLayoutSupport(const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
|
||||||
VkDescriptorSetLayoutSupport* pSupport,
|
VkDescriptorSetLayoutSupport* pSupport,
|
||||||
VkDescriptorSetVariableDescriptorCountLayoutSupport* pVarDescSetCountSupport);
|
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.
|
// If possible, retrieve from the MTLDevice, otherwise from available memory size, or a fixed conservative estimate.
|
||||||
uint64_t MVKPhysicalDevice::getRecommendedMaxWorkingSetSize() {
|
uint64_t MVKPhysicalDevice::getRecommendedMaxWorkingSetSize() {
|
||||||
#if MVK_XCODE_14 || MVK_MACOS
|
#if MVK_XCODE_15 || MVK_MACOS
|
||||||
if ( [_mtlDevice respondsToSelector: @selector(recommendedMaxWorkingSetSize)]) {
|
if ( [_mtlDevice respondsToSelector: @selector(recommendedMaxWorkingSetSize)]) {
|
||||||
return _mtlDevice.recommendedMaxWorkingSetSize;
|
return _mtlDevice.recommendedMaxWorkingSetSize;
|
||||||
}
|
}
|
||||||
@ -4194,7 +4194,7 @@ void MVKDevice::updateActivityPerformance(MVKPerformanceTracker& activity, doubl
|
|||||||
double total = (activity.average * activity.count++) + currentValue;
|
double total = (activity.average * activity.count++) + currentValue;
|
||||||
activity.average = total / activity.count;
|
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);
|
logActivityInline(activity, _performanceStatistics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4299,8 +4299,8 @@ MVKActivityPerformanceValueType MVKDevice::getActivityPerformanceValueType(MVKPe
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MVKDevice::getPerformanceStatistics(MVKPerformanceStatistics* pPerf) {
|
void MVKDevice::getPerformanceStatistics(MVKPerformanceStatistics* pPerf) {
|
||||||
addActivityByteCount(_performanceStatistics.device.gpuMemoryAllocated,
|
addPerformanceByteCount(_performanceStatistics.device.gpuMemoryAllocated,
|
||||||
_physicalDevice->getCurrentAllocatedSize());
|
_physicalDevice->getCurrentAllocatedSize());
|
||||||
|
|
||||||
lock_guard<mutex> lock(_perfLock);
|
lock_guard<mutex> lock(_perfLock);
|
||||||
if (pPerf) { *pPerf = _performanceStatistics; }
|
if (pPerf) { *pPerf = _performanceStatistics; }
|
||||||
|
@ -1293,7 +1293,7 @@ id<CAMetalDrawable> MVKPresentableSwapchainImage::getCAMetalDrawable() {
|
|||||||
for (uint32_t attemptIdx = 0; !_mtlDrawable && attemptIdx < attemptCnt; attemptIdx++) {
|
for (uint32_t attemptIdx = 0; !_mtlDrawable && attemptIdx < attemptCnt; attemptIdx++) {
|
||||||
uint64_t startTime = _device->getPerformanceTimestamp();
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
_mtlDrawable = [_swapchain->_surface->getCAMetalLayer().nextDrawable retain]; // retained
|
_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); }
|
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
|
// 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.
|
// VkDevice, have been destroyed by the time of this callback, so do not reference them.
|
||||||
lock_guard<mutex> lock(_detachmentLock);
|
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); }
|
if (_swapchain) { _swapchain->endPresentation(presentInfo, actualPresentTime); }
|
||||||
}
|
}
|
||||||
presentInfo.queue->endPresentation(presentInfo);
|
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
|
// Serializes the data in this cache to a stream
|
||||||
void MVKPipelineCache::writeData(ostream& outstream, bool isCounting) {
|
void MVKPipelineCache::writeData(ostream& outstream, bool isCounting) {
|
||||||
#if MVK_USE_CEREAL
|
#if MVK_USE_CEREAL
|
||||||
MVKPerformanceTracker& activityTracker = isCounting
|
MVKPerformanceTracker& perfTracker = isCounting
|
||||||
? _device->_performanceStatistics.pipelineCache.sizePipelineCache
|
? _device->_performanceStatistics.pipelineCache.sizePipelineCache
|
||||||
: _device->_performanceStatistics.pipelineCache.writePipelineCache;
|
: _device->_performanceStatistics.pipelineCache.writePipelineCache;
|
||||||
|
|
||||||
@ -2297,7 +2297,7 @@ void MVKPipelineCache::writeData(ostream& outstream, bool isCounting) {
|
|||||||
writer(cacheIter.getShaderConversionConfig());
|
writer(cacheIter.getShaderConversionConfig());
|
||||||
writer(cacheIter.getShaderConversionResultInfo());
|
writer(cacheIter.getShaderConversionResultInfo());
|
||||||
writer(cacheIter.getCompressedMSL());
|
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.
|
// Add the shader library to the staging cache.
|
||||||
MVKShaderLibraryCache* slCache = getShaderLibraryCache(smKey);
|
MVKShaderLibraryCache* slCache = getShaderLibraryCache(smKey);
|
||||||
_device->addActivityPerformance(_device->_performanceStatistics.pipelineCache.readPipelineCache, startTime);
|
_device->addPerformanceInterval(_device->_performanceStatistics.pipelineCache.readPipelineCache, startTime);
|
||||||
slCache->addShaderLibrary(&shaderConversionConfig, resultInfo, compressedMSL);
|
slCache->addShaderLibrary(&shaderConversionConfig, resultInfo, compressedMSL);
|
||||||
|
|
||||||
break;
|
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,
|
// 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.
|
// log a warning, and force them to end presentation, so the images and drawables will be released.
|
||||||
void MVKQueue::waitSwapchainPresentations(MVKCommandUse cmdUse) {
|
void MVKQueue::waitSwapchainPresentations(MVKCommandUse cmdUse) {
|
||||||
auto waitFrames = _device->_pMetalFeatures->maxSwapchainImageCount + 2;
|
uint32_t waitFrames = _device->_pMetalFeatures->maxSwapchainImageCount + 2;
|
||||||
if (_presentationCompletionBlocker.wait((waitFrames/60.0) * 1e9)) { return; }
|
uint64_t waitNanos = waitFrames * _device->_performanceStatistics.queue.frameInterval.average * 1e6;
|
||||||
|
if (_presentationCompletionBlocker.wait(waitNanos)) { return; }
|
||||||
|
|
||||||
auto imgCnt = _presentationCompletionBlocker.getReservationCount();
|
auto imgCnt = _presentationCompletionBlocker.getReservationCount();
|
||||||
MVKPresentableSwapchainImage* images[imgCnt];
|
MVKPresentableSwapchainImage* images[imgCnt];
|
||||||
@ -173,7 +174,7 @@ void MVKQueue::waitSwapchainPresentations(MVKCommandUse cmdUse) {
|
|||||||
|
|
||||||
// Wait for forced presentation completions. If we still have unfinished swapchain image
|
// 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.
|
// 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.",
|
reportWarning(VK_TIMEOUT, "%s timed out after %d frames while awaiting %d swapchain image presentations to complete.",
|
||||||
mvkVkCommandName(cmdUse), waitFrames * 2, _presentationCompletionBlocker.getReservationCount());
|
mvkVkCommandName(cmdUse), waitFrames * 2, _presentationCompletionBlocker.getReservationCount());
|
||||||
for (size_t imgIdx = 0; imgIdx < imgCnt; imgIdx++) {
|
for (size_t imgIdx = 0; imgIdx < imgCnt; imgIdx++) {
|
||||||
@ -203,7 +204,7 @@ id<MTLCommandBuffer> MVKQueue::getMTLCommandBuffer(MVKCommandUse cmdUse, bool re
|
|||||||
} else {
|
} else {
|
||||||
mtlCmdBuff = [_mtlQueue commandBufferWithUnretainedReferences];
|
mtlCmdBuff = [_mtlQueue commandBufferWithUnretainedReferences];
|
||||||
}
|
}
|
||||||
mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.queue.retrieveMTLCommandBuffer, startTime);
|
mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.queue.retrieveMTLCommandBuffer, startTime);
|
||||||
NSString* mtlCmdBuffLabel = getMTLCommandBufferLabel(cmdUse);
|
NSString* mtlCmdBuffLabel = getMTLCommandBufferLabel(cmdUse);
|
||||||
setLabelIfNotNil(mtlCmdBuff, mtlCmdBuffLabel);
|
setLabelIfNotNil(mtlCmdBuff, mtlCmdBuffLabel);
|
||||||
[mtlCmdBuff addCompletedHandler: ^(id<MTLCommandBuffer> mtlCB) { handleMTLCommandBufferError(mtlCB); }];
|
[mtlCmdBuff addCompletedHandler: ^(id<MTLCommandBuffer> mtlCB) { handleMTLCommandBufferError(mtlCB); }];
|
||||||
@ -496,7 +497,7 @@ VkResult MVKQueueCommandBufferSubmission::commitActiveMTLCommandBuffer(bool sign
|
|||||||
MVKDevice* mvkDev = getDevice();
|
MVKDevice* mvkDev = getDevice();
|
||||||
uint64_t startTime = mvkDev->getPerformanceTimestamp();
|
uint64_t startTime = mvkDev->getPerformanceTimestamp();
|
||||||
[mtlCmdBuff addCompletedHandler: ^(id<MTLCommandBuffer> mtlCB) {
|
[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.
|
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); }
|
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>
|
template <size_t N>
|
||||||
@ -602,7 +603,6 @@ MVKQueueFullCommandBufferSubmission<N>::MVKQueueFullCommandBufferSubmission(MVKQ
|
|||||||
MVKCommandUse cmdUse)
|
MVKCommandUse cmdUse)
|
||||||
: MVKQueueCommandBufferSubmission(queue, pSubmit, fence, cmdUse) {
|
: MVKQueueCommandBufferSubmission(queue, pSubmit, fence, cmdUse) {
|
||||||
|
|
||||||
// pSubmit can be null if just tracking the fence alone
|
|
||||||
if (pSubmit) {
|
if (pSubmit) {
|
||||||
uint32_t cbCnt = pSubmit->commandBufferCount;
|
uint32_t cbCnt = pSubmit->commandBufferCount;
|
||||||
_cmdBuffers.reserve(cbCnt);
|
_cmdBuffers.reserve(cbCnt);
|
||||||
|
@ -80,7 +80,7 @@ MVKMTLFunction MVKShaderLibrary::getMTLFunction(const VkSpecializationInfo* pSpe
|
|||||||
|
|
||||||
uint64_t startTime = pShaderFeedback ? mvkGetTimestamp() : mvkDev->getPerformanceTimestamp();
|
uint64_t startTime = pShaderFeedback ? mvkGetTimestamp() : mvkDev->getPerformanceTimestamp();
|
||||||
id<MTLFunction> mtlFunc = [[_mtlLibrary newFunctionWithName: mtlFuncName] autorelease];
|
id<MTLFunction> mtlFunc = [[_mtlLibrary newFunctionWithName: mtlFuncName] autorelease];
|
||||||
mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
|
mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
|
||||||
if (pShaderFeedback) {
|
if (pShaderFeedback) {
|
||||||
if (mtlFunc) {
|
if (mtlFunc) {
|
||||||
mvkEnableFlags(pShaderFeedback->flags, VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT);
|
mvkEnableFlags(pShaderFeedback->flags, VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT);
|
||||||
@ -156,7 +156,7 @@ void MVKShaderLibrary::compressMSL(const string& msl) {
|
|||||||
MVKDevice* mvkDev = _owner->getDevice();
|
MVKDevice* mvkDev = _owner->getDevice();
|
||||||
uint64_t startTime = mvkDev->getPerformanceTimestamp();
|
uint64_t startTime = mvkDev->getPerformanceTimestamp();
|
||||||
_compressedMSL.compress(msl, mvkConfig().shaderSourceCompressionAlgorithm);
|
_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.
|
// Decompresses the cached MSL into the string.
|
||||||
@ -164,7 +164,7 @@ void MVKShaderLibrary::decompressMSL(string& msl) {
|
|||||||
MVKDevice* mvkDev = _owner->getDevice();
|
MVKDevice* mvkDev = _owner->getDevice();
|
||||||
uint64_t startTime = mvkDev->getPerformanceTimestamp();
|
uint64_t startTime = mvkDev->getPerformanceTimestamp();
|
||||||
_compressedMSL.decompress(msl);
|
_compressedMSL.decompress(msl);
|
||||||
mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.mslDecompress, startTime);
|
mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.shaderCompilation.mslDecompress, startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner,
|
MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner,
|
||||||
@ -207,7 +207,7 @@ MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner,
|
|||||||
handleCompilationError(err, "Compiled shader module creation");
|
handleCompilationError(err, "Compiled shader module creation");
|
||||||
[shdrData release];
|
[shdrData release];
|
||||||
}
|
}
|
||||||
mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.mslLoad, startTime);
|
mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.shaderCompilation.mslLoad, startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKShaderLibrary::MVKShaderLibrary(const MVKShaderLibrary& other) {
|
MVKShaderLibrary::MVKShaderLibrary(const MVKShaderLibrary& other) {
|
||||||
@ -283,7 +283,7 @@ MVKShaderLibrary* MVKShaderLibraryCache::findShaderLibrary(SPIRVToMSLConversionC
|
|||||||
if (slPair.first.matches(*pShaderConfig)) {
|
if (slPair.first.matches(*pShaderConfig)) {
|
||||||
pShaderConfig->alignWith(slPair.first);
|
pShaderConfig->alignWith(slPair.first);
|
||||||
MVKDevice* mvkDev = _owner->getDevice();
|
MVKDevice* mvkDev = _owner->getDevice();
|
||||||
mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.shaderLibraryFromCache, startTime);
|
mvkDev->addPerformanceInterval(mvkDev->_performanceStatistics.shaderCompilation.shaderLibraryFromCache, startTime);
|
||||||
if (pShaderFeedback) {
|
if (pShaderFeedback) {
|
||||||
pShaderFeedback->duration += mvkGetElapsedNanoseconds(startTime);
|
pShaderFeedback->duration += mvkGetElapsedNanoseconds(startTime);
|
||||||
}
|
}
|
||||||
@ -363,7 +363,7 @@ bool MVKShaderModule::convert(SPIRVToMSLConversionConfiguration* pShaderConfig,
|
|||||||
GLSLToSPIRVConversionResult glslConversionResult;
|
GLSLToSPIRVConversionResult glslConversionResult;
|
||||||
uint64_t startTime = _device->getPerformanceTimestamp();
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
bool wasConverted = _glslConverter.convert(getMVKGLSLConversionShaderStage(pShaderConfig), glslConversionResult, shouldLogCode, false);
|
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 (wasConverted) {
|
||||||
if (shouldLogCode) { MVKLogInfo("%s", glslConversionResult.resultLog.c_str()); }
|
if (shouldLogCode) { MVKLogInfo("%s", glslConversionResult.resultLog.c_str()); }
|
||||||
@ -376,7 +376,7 @@ bool MVKShaderModule::convert(SPIRVToMSLConversionConfiguration* pShaderConfig,
|
|||||||
|
|
||||||
uint64_t startTime = _device->getPerformanceTimestamp();
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
bool wasConverted = _spvConverter.convert(*pShaderConfig, conversionResult, shouldLogCode, shouldLogCode, shouldLogEstimatedGLSL);
|
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 (wasConverted) {
|
||||||
if (shouldLogCode) { MVKLogInfo("%s", conversionResult.resultLog.c_str()); }
|
if (shouldLogCode) { MVKLogInfo("%s", conversionResult.resultLog.c_str()); }
|
||||||
@ -436,7 +436,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
|
|||||||
|
|
||||||
uint64_t startTime = _device->getPerformanceTimestamp();
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
codeHash = mvkHash(pCreateInfo->pCode, spvCount);
|
codeHash = mvkHash(pCreateInfo->pCode, spvCount);
|
||||||
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
|
_device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
|
||||||
|
|
||||||
_spvConverter.setSPIRV(pCreateInfo->pCode, spvCount);
|
_spvConverter.setSPIRV(pCreateInfo->pCode, spvCount);
|
||||||
|
|
||||||
@ -450,7 +450,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
|
|||||||
uint64_t startTime = _device->getPerformanceTimestamp();
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
codeHash = mvkHash(&magicNum);
|
codeHash = mvkHash(&magicNum);
|
||||||
codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash);
|
codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash);
|
||||||
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
|
_device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
|
||||||
|
|
||||||
SPIRVToMSLConversionResult conversionResult;
|
SPIRVToMSLConversionResult conversionResult;
|
||||||
conversionResult.msl = pMSLCode;
|
conversionResult.msl = pMSLCode;
|
||||||
@ -466,7 +466,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
|
|||||||
uint64_t startTime = _device->getPerformanceTimestamp();
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
codeHash = mvkHash(&magicNum);
|
codeHash = mvkHash(&magicNum);
|
||||||
codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash);
|
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);
|
_directMSLLibrary = new MVKShaderLibrary(this, (void*)(pMSLCode), mslCodeLen);
|
||||||
|
|
||||||
@ -479,7 +479,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
|
|||||||
|
|
||||||
uint64_t startTime = _device->getPerformanceTimestamp();
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
codeHash = mvkHash(pGLSL, codeSize);
|
codeHash = mvkHash(pGLSL, codeSize);
|
||||||
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
|
_device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
|
||||||
|
|
||||||
_glslConverter.setGLSL(pGLSL, glslLen);
|
_glslConverter.setGLSL(pGLSL, glslLen);
|
||||||
} else {
|
} else {
|
||||||
|
@ -159,13 +159,14 @@ void MVKSwapchain::renderWatermark(id<MTLTexture> mtlTexture, id<MTLCommandBuffe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculates and remembers the time interval between frames.
|
// Calculates and remembers the time interval between frames.
|
||||||
|
// Not threadsafe. Ensure this is called from a threadsafe environment.
|
||||||
void MVKSwapchain::markFrameInterval() {
|
void MVKSwapchain::markFrameInterval() {
|
||||||
uint64_t prevFrameTime = _lastFrameTime;
|
uint64_t prevFrameTime = _lastFrameTime;
|
||||||
_lastFrameTime = _device->getPerformanceTimestamp();
|
_lastFrameTime = mvkGetTimestamp();
|
||||||
|
|
||||||
if (prevFrameTime == 0) { return; } // First frame starts at first presentation
|
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();
|
auto& mvkCfg = mvkConfig();
|
||||||
bool shouldLogOnFrames = mvkCfg.performanceTracking && mvkCfg.activityPerformanceLoggingStyle == MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_FRAME_COUNT;
|
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::beginPresentation(const MVKImagePresentInfo& presentInfo) {}
|
||||||
|
|
||||||
void MVKSwapchain::endPresentation(const MVKImagePresentInfo& presentInfo, uint64_t actualPresentTime) {
|
void MVKSwapchain::endPresentation(const MVKImagePresentInfo& presentInfo, uint64_t actualPresentTime) {
|
||||||
|
std::lock_guard<std::mutex> lock(_presentHistoryLock);
|
||||||
|
|
||||||
markFrameInterval();
|
markFrameInterval();
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(_presentHistoryLock);
|
|
||||||
if (_presentHistoryCount < kMaxPresentationHistory) {
|
if (_presentHistoryCount < kMaxPresentationHistory) {
|
||||||
_presentHistoryCount++;
|
_presentHistoryCount++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -588,7 +588,7 @@ void MVKMetalCompiler::compile(unique_lock<mutex>& lock, dispatch_block_t block)
|
|||||||
|
|
||||||
if (_compileError) { handleError(); }
|
if (_compileError) { handleError(); }
|
||||||
|
|
||||||
mvkDev->addActivityPerformance(*_pPerformanceTracker, _startTime);
|
mvkDev->addPerformanceInterval(*_pPerformanceTracker, _startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKMetalCompiler::handleError() {
|
void MVKMetalCompiler::handleError() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user