From c205c53ad9a1e400d90d25b42c6fd9465a32b69f Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Fri, 3 Mar 2023 10:39:26 -0500 Subject: [PATCH] Reduce memory footprint of retained MSL source code. - Add MVKCompressor template class, and mvkCompress() & mvkDecompress() functions to support general data compression. - Add MVKConfiguration::shaderSourceCompressionAlgorithm and env var MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM to support compressing MSL shader source code held in a pipeline cache. - Add MVKShaderCompilationPerformance::mslCompress and mslDecompress to allow performance of MSL compression to be tracked and queried. - Add support for logging performance stats accumulated in a VkDevice, when it is destroyed. Good for CTS testing. - Change MVKConfiguration::logActivityPerformanceInline boolean to activityPerformanceLoggingStyle enumeration value. - Add MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE environment variable and build setting to set MVKConfiguration::activityPerformanceLoggingStyle value. --- Docs/Whats_New.md | 11 ++- MoltenVK/MoltenVK.xcodeproj/project.pbxproj | 16 ++-- MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h | 60 ++++++++++--- MoltenVK/MoltenVK/GPUObjects/MVKDevice.h | 6 +- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 52 ++++++----- MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm | 21 +++-- .../MoltenVK/GPUObjects/MVKShaderModule.h | 23 +++-- .../MoltenVK/GPUObjects/MVKShaderModule.mm | 63 ++++++++++--- MoltenVK/MoltenVK/Layers/MVKLayers.mm | 1 - MoltenVK/MoltenVK/Utility/MVKCodec.h | 88 ++++++++++++++++++- .../Utility/{MVKCodec.cpp => MVKCodec.mm} | 75 +++++++++++++++- MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp | 14 ++- MoltenVK/MoltenVK/Utility/MVKEnvironment.h | 12 ++- .../SPIRVToMSLConverter.h | 2 +- Scripts/runcts | 14 +-- 15 files changed, 370 insertions(+), 88 deletions(-) rename MoltenVK/MoltenVK/Utility/{MVKCodec.cpp => MVKCodec.mm} (53%) diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 7591865f..4c0d1174 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -32,8 +32,17 @@ Released TBA - Change rounding of surface size provided by Metal from truncation to rounding-with-half-to-even. - Queue submissions retain wait semaphores until `MTLCommandBuffer` finishes. - Use a different visibility buffer for each `MTLCommandBuffer` in a queue submit. -- Reduce memory footprint of retained MSL source code. - Work around problems with using explicit LoD with arrayed depth images on Apple Silicon. +- Reduce memory footprint of MSL source code retained in pipeline cache. +- Add `MVKConfiguration::shaderSourceCompressionAlgorithm` and + env var `MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM` to support + compressing MSL shader source code held in a pipeline cache. +- Add `MVKShaderCompilationPerformance::mslCompress` and `mslDecompress` + to allow performance of MSL compression to be tracked and queried. +- Add support for logging performance stats accumulated in a `VkDevice`, when it is destroyed. +- Change `MVKConfiguration::logActivityPerformanceInline` boolean to `activityPerformanceLoggingStyle` enumeration value. +- Add `MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE` environment variable and + build setting to set `MVKConfiguration::activityPerformanceLoggingStyle` value. - Update `VK_MVK_MOLTENVK_SPEC_VERSION` to version `37`. diff --git a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj index 88783912..2c4b87eb 100644 --- a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj +++ b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj @@ -112,7 +112,7 @@ 2FEA0AAA24902F9F00EEF3AD /* MVKOSExtensions.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9B51BD2225E986A00AC74D2 /* MVKOSExtensions.mm */; }; 2FEA0AAB24902F9F00EEF3AD /* MVKShaderModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7981C7DFB4800632CA3 /* MVKShaderModule.mm */; }; 2FEA0AAC24902F9F00EEF3AD /* MVKSync.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB79E1C7DFB4800632CA3 /* MVKSync.mm */; }; - 2FEA0AAD24902F9F00EEF3AD /* MVKCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45557A4D21C9EFF3008868BD /* MVKCodec.cpp */; }; + 2FEA0AAD24902F9F00EEF3AD /* MVKCodec.mm in Sources */ = {isa = PBXBuildFile; fileRef = 45557A4D21C9EFF3008868BD /* MVKCodec.mm */; }; 2FEA0AAE24902F9F00EEF3AD /* MVKCmdPipeline.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB76F1C7DFB4800632CA3 /* MVKCmdPipeline.mm */; }; 2FEA0AAF24902F9F00EEF3AD /* MVKLayers.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7A11C7DFB4800632CA3 /* MVKLayers.mm */; }; 2FEA0AB024902F9F00EEF3AD /* MVKFramebuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7881C7DFB4800632CA3 /* MVKFramebuffer.mm */; }; @@ -136,8 +136,8 @@ 4553AEFC2251617100E8EBCD /* MVKBlockObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 4553AEF62251617100E8EBCD /* MVKBlockObserver.m */; }; 4553AEFD2251617100E8EBCD /* MVKBlockObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4553AEFA2251617100E8EBCD /* MVKBlockObserver.h */; }; 4553AEFE2251617100E8EBCD /* MVKBlockObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4553AEFA2251617100E8EBCD /* MVKBlockObserver.h */; }; - 45557A5221C9EFF3008868BD /* MVKCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45557A4D21C9EFF3008868BD /* MVKCodec.cpp */; }; - 45557A5321C9EFF3008868BD /* MVKCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45557A4D21C9EFF3008868BD /* MVKCodec.cpp */; }; + 45557A5221C9EFF3008868BD /* MVKCodec.mm in Sources */ = {isa = PBXBuildFile; fileRef = 45557A4D21C9EFF3008868BD /* MVKCodec.mm */; }; + 45557A5321C9EFF3008868BD /* MVKCodec.mm in Sources */ = {isa = PBXBuildFile; fileRef = 45557A4D21C9EFF3008868BD /* MVKCodec.mm */; }; 45557A5421C9EFF3008868BD /* MVKCodec.h in Headers */ = {isa = PBXBuildFile; fileRef = 45557A5121C9EFF3008868BD /* MVKCodec.h */; }; 45557A5521C9EFF3008868BD /* MVKCodec.h in Headers */ = {isa = PBXBuildFile; fileRef = 45557A5121C9EFF3008868BD /* MVKCodec.h */; }; A9096E5E1F81E16300DFBEA6 /* MVKCmdDispatch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9096E5D1F81E16300DFBEA6 /* MVKCmdDispatch.mm */; }; @@ -428,7 +428,7 @@ 453638312508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h"; sourceTree = ""; }; 4553AEF62251617100E8EBCD /* MVKBlockObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVKBlockObserver.m; sourceTree = ""; }; 4553AEFA2251617100E8EBCD /* MVKBlockObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKBlockObserver.h; sourceTree = ""; }; - 45557A4D21C9EFF3008868BD /* MVKCodec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MVKCodec.cpp; sourceTree = ""; }; + 45557A4D21C9EFF3008868BD /* MVKCodec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKCodec.mm; sourceTree = ""; }; 45557A5121C9EFF3008868BD /* MVKCodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCodec.h; sourceTree = ""; }; 45557A5721CD83C3008868BD /* MVKDXTnCodec.def */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = MVKDXTnCodec.def; sourceTree = ""; }; A9096E5C1F81E16300DFBEA6 /* MVKCmdDispatch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVKCmdDispatch.h; sourceTree = ""; }; @@ -691,8 +691,8 @@ A9D7104E25CDE05E00E38106 /* MVKBitArray.h */, 4553AEFA2251617100E8EBCD /* MVKBlockObserver.h */, 4553AEF62251617100E8EBCD /* MVKBlockObserver.m */, - 45557A4D21C9EFF3008868BD /* MVKCodec.cpp */, 45557A5121C9EFF3008868BD /* MVKCodec.h */, + 45557A4D21C9EFF3008868BD /* MVKCodec.mm */, 45557A5721CD83C3008868BD /* MVKDXTnCodec.def */, A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */, A98149431FB6A3F7005F00B4 /* MVKEnvironment.h */, @@ -1368,7 +1368,7 @@ 2FEA0AAA24902F9F00EEF3AD /* MVKOSExtensions.mm in Sources */, 2FEA0AAB24902F9F00EEF3AD /* MVKShaderModule.mm in Sources */, 2FEA0AAC24902F9F00EEF3AD /* MVKSync.mm in Sources */, - 2FEA0AAD24902F9F00EEF3AD /* MVKCodec.cpp in Sources */, + 2FEA0AAD24902F9F00EEF3AD /* MVKCodec.mm in Sources */, 2FEA0AAE24902F9F00EEF3AD /* MVKCmdPipeline.mm in Sources */, 2FEA0AAF24902F9F00EEF3AD /* MVKLayers.mm in Sources */, 2FEA0AB024902F9F00EEF3AD /* MVKFramebuffer.mm in Sources */, @@ -1427,7 +1427,7 @@ A9B51BD7225E986A00AC74D2 /* MVKOSExtensions.mm in Sources */, A94FB80E1C7DFB4800632CA3 /* MVKShaderModule.mm in Sources */, A94FB81A1C7DFB4800632CA3 /* MVKSync.mm in Sources */, - 45557A5221C9EFF3008868BD /* MVKCodec.cpp in Sources */, + 45557A5221C9EFF3008868BD /* MVKCodec.mm in Sources */, A94FB7BE1C7DFB4800632CA3 /* MVKCmdPipeline.mm in Sources */, A94FB81E1C7DFB4800632CA3 /* MVKLayers.mm in Sources */, A94FB7EE1C7DFB4800632CA3 /* MVKFramebuffer.mm in Sources */, @@ -1487,7 +1487,7 @@ A9B51BD8225E986A00AC74D2 /* MVKOSExtensions.mm in Sources */, A94FB80F1C7DFB4800632CA3 /* MVKShaderModule.mm in Sources */, A94FB81B1C7DFB4800632CA3 /* MVKSync.mm in Sources */, - 45557A5321C9EFF3008868BD /* MVKCodec.cpp in Sources */, + 45557A5321C9EFF3008868BD /* MVKCodec.mm in Sources */, A94FB7BF1C7DFB4800632CA3 /* MVKCmdPipeline.mm in Sources */, A94FB81F1C7DFB4800632CA3 /* MVKLayers.mm in Sources */, A94FB7EF1C7DFB4800632CA3 /* MVKFramebuffer.mm in Sources */, diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h index a6b4803f..7377f05f 100644 --- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h +++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h @@ -130,6 +130,24 @@ typedef enum MVKConfigFastMath { MVK_CONFIG_FAST_MATH_MAX_ENUM = 0x7FFFFFFF } MVKConfigFastMath; +/** Identifies available system data compression algorithms. */ +typedef enum MVKConfigCompressionAlgorithm { + MVK_CONFIG_COMPRESSION_ALGORITHM_NONE = 0, /**< No compression. */ + MVK_CONFIG_COMPRESSION_ALGORITHM_LZFSE = 1, /**< Apple proprietary. Good balance of high performance and small compression size, particularly for larger data content. */ + MVK_CONFIG_COMPRESSION_ALGORITHM_ZLIB = 2, /**< Open cross-platform ZLib format. For smaller data content, has better performance and smaller size than LZFSE. */ + MVK_CONFIG_COMPRESSION_ALGORITHM_LZ4 = 3, /**< Fastest performance. Largest compression size. */ + MVK_CONFIG_COMPRESSION_ALGORITHM_LZMA = 4, /**< Slowest performance. Smallest compression size, particular with larger content. */ + MVK_CONFIG_COMPRESSION_ALGORITHM_MAX_ENUM = 0x7FFFFFFF, +} MVKConfigCompressionAlgorithm; + +/** Identifies the style of activity performance logging to use. */ +typedef enum MVKConfigActivityPerformanceLoggingStyle { + MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_FRAME_COUNT = 0, /**< Repeatedly log performance after a configured number of frames. */ + MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_IMMEDIATE = 1, /**< Log immediately after each performance measurement. */ + MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_DEVICE_LIFETIME = 2, /**< Log at the end of the VkDevice lifetime. This is useful for one-shot apps such as testing frameworks. */ + MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_MAX_ENUM = 0x7FFFFFFF, +} MVKConfigActivityPerformanceLoggingStyle; + /** * MoltenVK configuration settings. * @@ -361,8 +379,8 @@ typedef struct { * If enabled, performance statistics, as defined by the MVKPerformanceStatistics structure, * are collected, and can be retrieved via the vkGetPerformanceStatisticsMVK() function. * - * You can also use the performanceLoggingFrameCount or logActivityPerformanceInline - * parameters to automatically log the performance statistics collected by this parameter. + * You can also use the activityPerformanceLoggingStyle and performanceLoggingFrameCount + * parameters to configure when to log the performance statistics collected by this parameter. * * The value of this parameter must be changed before creating a VkDevice, * for the change to take effect. @@ -770,21 +788,20 @@ typedef struct { VkBool32 useMTLHeap; /** - * Controls whether MoltenVK should log the performance of individual activities as they happen. - * If this setting is enabled, activity performance will be logged when each activity happens. - * If this setting is disabled, activity performance will be logged when frame peformance is - * logged as determined by the performanceLoggingFrameCount value. + * Controls when MoltenVK should log activity performance events. * * The value of this parameter must be changed before creating a VkDevice, * for the change to take effect. * * The initial value or this parameter is set by the - * MVK_CONFIG_PERFORMANCE_LOGGING_INLINE + * MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, this setting is disabled by default, and activity - * performance will be logged only when frame activity is logged. + * If neither is set, this setting is set to + * MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_FRAME_COUNT by default, + * and activity performance will be logged when frame activity is logged. */ - VkBool32 logActivityPerformanceInline; + MVKConfigActivityPerformanceLoggingStyle activityPerformanceLoggingStyle; +#define logActivityPerformanceInline activityPerformanceLoggingStyle /** * Controls the Vulkan API version that MoltenVK should advertise in vkEnumerateInstanceVersion(). @@ -877,6 +894,27 @@ typedef struct { */ MVKUseMetalArgumentBuffers useMetalArgumentBuffers; + /** + * Controls the type of compression to use on the MSL source code that is stored in memory + * for use in a pipeline cache. After being converted from SPIR-V, or loaded directly into + * a VkShaderModule, and then compiled into a MTLLibrary, the MSL source code is no longer + * needed for operation, but it is retained so it can be written out as part of a pipeline + * cache export. When a large number of shaders are loaded, this can consume significant + * memory. In such a case, this parameter can be used to compress the MSL source code that + * is awaiting export as part of a pipeline cache. + * + * The value of this parameter can be changed at any time, and will affect the size of + * the cached MSL from subsequent shader compilations. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, this setting is set to + * MVK_CONFIG_COMPRESSION_ALGORITHM_NONE by default, + * and MoltenVK will not compress the MSL source code after compilation into a MTLLibrary. + */ + MVKConfigCompressionAlgorithm shaderSourceCompressionAlgorithm; + } MVKConfiguration; /** Identifies the type of rounding Metal uses for float to integer conversions in particular calculatons. */ @@ -999,6 +1037,8 @@ typedef struct { 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. */ diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index f58d9ee3..c9b0e97e 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -686,7 +686,9 @@ public: // Log call not locked. Very minor chance that the tracker data will be updated during log call, // resulting in an inconsistent report. Not worth taking lock perf hit for rare inline reporting. - if (_logActivityPerformanceInline) { logActivityPerformance(activityTracker, _performanceStatistics, true); } + if (_activityPerformanceLoggingStyle == MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_IMMEDIATE) { + logActivityPerformance(activityTracker, _performanceStatistics, true); + } } }; @@ -891,7 +893,7 @@ protected: id _defaultMTLSamplerState = nil; id _dummyBlitMTLBuffer = nil; uint32_t _globalVisibilityQueryCount = 0; - bool _logActivityPerformanceInline = false; + MVKConfigActivityPerformanceLoggingStyle _activityPerformanceLoggingStyle = MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_FRAME_COUNT; bool _isPerformanceTracking = false; bool _isCurrentlyAutoGPUCapturing = false; bool _isUsingMetalArgumentBuffers = false; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 11ab9443..60bb270d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -4000,7 +4000,7 @@ void MVKDevice::logActivityPerformance(MVKPerformanceTracker& activity, MVKPerfo } void MVKDevice::logPerformanceSummary() { - if (_logActivityPerformanceInline) { return; } + if (_activityPerformanceLoggingStyle == MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_IMMEDIATE) { return; } // Get a copy to minimize time under lock MVKPerformanceStatistics perfStats; @@ -4014,6 +4014,8 @@ void MVKDevice::logPerformanceSummary() { logActivityPerformance(perfStats.shaderCompilation.spirvToMSL, perfStats); logActivityPerformance(perfStats.shaderCompilation.mslCompile, perfStats); logActivityPerformance(perfStats.shaderCompilation.mslLoad, perfStats); + logActivityPerformance(perfStats.shaderCompilation.mslCompress, perfStats); + logActivityPerformance(perfStats.shaderCompilation.mslDecompress, perfStats); logActivityPerformance(perfStats.shaderCompilation.shaderLibraryFromCache, perfStats); logActivityPerformance(perfStats.shaderCompilation.functionRetrieval, perfStats); logActivityPerformance(perfStats.shaderCompilation.functionSpecialization, perfStats); @@ -4028,6 +4030,8 @@ const char* MVKDevice::getActivityPerformanceDescription(MVKPerformanceTracker& if (&activity == &perfStats.shaderCompilation.spirvToMSL) { return "Convert SPIR-V to MSL source code"; } if (&activity == &perfStats.shaderCompilation.mslCompile) { return "Compile MSL source code into a MTLLibrary"; } if (&activity == &perfStats.shaderCompilation.mslLoad) { return "Load pre-compiled MSL code into a MTLLibrary"; } + if (&activity == &perfStats.shaderCompilation.mslCompress) { return "Compress MSL source code after compiling a MTLLibrary"; } + if (&activity == &perfStats.shaderCompilation.mslDecompress) { return "Decompress MSL source code during pipeline cache write"; } if (&activity == &perfStats.shaderCompilation.shaderLibraryFromCache) { return "Retrieve shader library from the cache"; } if (&activity == &perfStats.shaderCompilation.functionRetrieval) { return "Retrieve a MTLFunction from a MTLLibrary"; } if (&activity == &perfStats.shaderCompilation.functionSpecialization) { return "Specialize a retrieved MTLFunction"; } @@ -4377,29 +4381,25 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo void MVKDevice::initPerformanceTracking() { _isPerformanceTracking = mvkConfig().performanceTracking; - _logActivityPerformanceInline = mvkConfig().logActivityPerformanceInline; + _activityPerformanceLoggingStyle = mvkConfig().activityPerformanceLoggingStyle; - MVKPerformanceTracker initPerf; - initPerf.count = 0; - initPerf.averageDuration = 0.0; - initPerf.minimumDuration = 0.0; - initPerf.maximumDuration = 0.0; - - _performanceStatistics.shaderCompilation.hashShaderCode = initPerf; - _performanceStatistics.shaderCompilation.spirvToMSL = initPerf; - _performanceStatistics.shaderCompilation.mslCompile = initPerf; - _performanceStatistics.shaderCompilation.mslLoad = initPerf; - _performanceStatistics.shaderCompilation.shaderLibraryFromCache = initPerf; - _performanceStatistics.shaderCompilation.functionRetrieval = initPerf; - _performanceStatistics.shaderCompilation.functionSpecialization = initPerf; - _performanceStatistics.shaderCompilation.pipelineCompile = initPerf; - _performanceStatistics.pipelineCache.sizePipelineCache = initPerf; - _performanceStatistics.pipelineCache.writePipelineCache = initPerf; - _performanceStatistics.pipelineCache.readPipelineCache = initPerf; - _performanceStatistics.queue.mtlQueueAccess = initPerf; - _performanceStatistics.queue.mtlCommandBufferCompletion = initPerf; - _performanceStatistics.queue.nextCAMetalDrawable = initPerf; - _performanceStatistics.queue.frameInterval = initPerf; + _performanceStatistics.shaderCompilation.hashShaderCode = {}; + _performanceStatistics.shaderCompilation.spirvToMSL = {}; + _performanceStatistics.shaderCompilation.mslCompile = {}; + _performanceStatistics.shaderCompilation.mslLoad = {}; + _performanceStatistics.shaderCompilation.mslCompress = {}; + _performanceStatistics.shaderCompilation.mslDecompress = {}; + _performanceStatistics.shaderCompilation.shaderLibraryFromCache = {}; + _performanceStatistics.shaderCompilation.functionRetrieval = {}; + _performanceStatistics.shaderCompilation.functionSpecialization = {}; + _performanceStatistics.shaderCompilation.pipelineCompile = {}; + _performanceStatistics.pipelineCache.sizePipelineCache = {}; + _performanceStatistics.pipelineCache.writePipelineCache = {}; + _performanceStatistics.pipelineCache.readPipelineCache = {}; + _performanceStatistics.queue.mtlQueueAccess = {}; + _performanceStatistics.queue.mtlCommandBufferCompletion = {}; + _performanceStatistics.queue.nextCAMetalDrawable = {}; + _performanceStatistics.queue.frameInterval = {}; } void MVKDevice::initPhysicalDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo* pCreateInfo) { @@ -4666,9 +4666,15 @@ void MVKDevice::reservePrivateData(const VkDeviceCreateInfo* pCreateInfo) { } MVKDevice::~MVKDevice() { + if (_activityPerformanceLoggingStyle == MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_DEVICE_LIFETIME) { + MVKLogInfo("Device activity performance summary:"); + logPerformanceSummary(); + } + for (auto& queues : _queuesByQueueFamilyIndex) { mvkDestroyContainerContents(queues); } + if (_commandResourceFactory) { _commandResourceFactory->destroy(); } [_globalVisibilityResultMTLBuffer release]; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm index 59230540..426d1182 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -2004,7 +2004,7 @@ protected: bool next() { return (++_index < (_pSLCache ? _pSLCache->_shaderLibraries.size() : 0)); } SPIRVToMSLConversionConfiguration& getShaderConversionConfig() { return _pSLCache->_shaderLibraries[_index].first; } - std::string& getMSL() { return _pSLCache->_shaderLibraries[_index].second->_msl; } + MVKCompressor& getCompressedMSL() { return _pSLCache->_shaderLibraries[_index].second->getCompressedMSL(); } SPIRVToMSLConversionResultInfo& getShaderConversionResultInfo() { return _pSLCache->_shaderLibraries[_index].second->_shaderConversionResultInfo; } MVKShaderCacheIterator(MVKShaderLibraryCache* pSLCache) : _pSLCache(pSLCache) {} @@ -2087,7 +2087,7 @@ void MVKPipelineCache::writeData(ostream& outstream, bool isCounting) { writer(smKey); writer(cacheIter.getShaderConversionConfig()); writer(cacheIter.getShaderConversionResultInfo()); - writer(cacheIter.getMSL()); + writer(cacheIter.getCompressedMSL()); _device->addActivityPerformance(activityTracker, startTime); } } @@ -2149,14 +2149,16 @@ void MVKPipelineCache::readData(const VkPipelineCacheCreateInfo* pCreateInfo) { SPIRVToMSLConversionConfiguration shaderConversionConfig; reader(shaderConversionConfig); - SPIRVToMSLConversionResult shaderConversionResult; - reader(shaderConversionResult.resultInfo); - reader(shaderConversionResult.msl); + SPIRVToMSLConversionResultInfo resultInfo; + reader(resultInfo); + + MVKCompressor compressedMSL; + reader(compressedMSL); // Add the shader library to the staging cache. MVKShaderLibraryCache* slCache = getShaderLibraryCache(smKey); _device->addActivityPerformance(_device->_performanceStatistics.pipelineCache.readPipelineCache, startTime); - slCache->addShaderLibrary(&shaderConversionConfig, shaderConversionResult); + slCache->addShaderLibrary(&shaderConversionConfig, resultInfo, compressedMSL); break; } @@ -2394,6 +2396,13 @@ void serialize(Archive & archive, MVKShaderModuleKey& k) { k.codeHash); } +template +void serialize(Archive & archive, MVKCompressor& comp) { + archive(comp._compressed, + comp._uncompressedSize, + comp._algorithm); +} + #pragma mark Construction diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h index 3d7e3e4f..02969927 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h @@ -20,6 +20,7 @@ #include "MVKDevice.h" #include "MVKSync.h" +#include "MVKCodec.h" #include "MVKSmallVector.h" #include #include @@ -84,10 +85,13 @@ public: */ void setWorkgroupSize(uint32_t x, uint32_t y, uint32_t z); - /** Constructs an instance from the specified MSL source code. */ - MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner, const SPIRVToMSLConversionResult& conversionResult); + MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner, + const SPIRVToMSLConversionResult& conversionResult); + + MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner, + const SPIRVToMSLConversionResultInfo& resultInfo, + const MVKCompressor compressedMSL); - /** Constructs an instance from the specified compiled MSL code data. */ MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner, const void* mslCompiledCodeData, size_t mslCompiledCodeLength); @@ -106,11 +110,15 @@ protected: MVKMTLFunction getMTLFunction(const VkSpecializationInfo* pSpecializationInfo, MVKShaderModule* shaderModule); void handleCompilationError(NSError* err, const char* opDesc); MTLFunctionConstant* getFunctionConstant(NSArray* mtlFCs, NSUInteger mtlFCID); + void compileLibrary(const std::string& msl); + void compressMSL(const std::string& msl); + void decompressMSL(std::string& msl); + MVKCompressor& getCompressedMSL() { return _compressedMSL; } MVKVulkanAPIDeviceObject* _owner; id _mtlLibrary; + MVKCompressor _compressedMSL; SPIRVToMSLConversionResultInfo _shaderConversionResultInfo; - std::string _msl; }; @@ -146,8 +154,11 @@ protected: friend MVKShaderModule; MVKShaderLibrary* findShaderLibrary(SPIRVToMSLConversionConfiguration* pShaderConfig); - MVKShaderLibrary* addShaderLibrary(SPIRVToMSLConversionConfiguration* pShaderConfig, - SPIRVToMSLConversionResult& conversionResult); + MVKShaderLibrary* addShaderLibrary(const SPIRVToMSLConversionConfiguration* pShaderConfig, + const SPIRVToMSLConversionResult& conversionResult); + MVKShaderLibrary* addShaderLibrary(const SPIRVToMSLConversionConfiguration* pShaderConfig, + const SPIRVToMSLConversionResultInfo& resultInfo, + const MVKCompressor compressedMSL); void merge(MVKShaderLibraryCache* other); MVKVulkanAPIDeviceObject* _owner; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm index ce2e9975..7d7f6db2 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm @@ -19,7 +19,6 @@ #include "MVKShaderModule.h" #include "MVKPipeline.h" #include "MVKFoundation.h" -#include using namespace std; @@ -140,18 +139,45 @@ void MVKShaderLibrary::setWorkgroupSize(uint32_t x, uint32_t y, uint32_t z) { wgSize.depth.size = z; } +// Sets the cached MSL source code, after first compressing it. +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); +} + +// Decompresses the cached MSL into the string. +void MVKShaderLibrary::decompressMSL(string& msl) { + MVKDevice* mvkDev = _owner->getDevice(); + uint64_t startTime = mvkDev->getPerformanceTimestamp(); + _compressedMSL.decompress(msl); + mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.mslDecompress, startTime); +} + MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner, const SPIRVToMSLConversionResult& conversionResult) : _owner(owner) { - MVKShaderLibraryCompiler* slc = new MVKShaderLibraryCompiler(_owner); - - NSString* nsSrc = [[NSString alloc] initWithUTF8String: conversionResult.msl.c_str()]; // temp retained - _mtlLibrary = slc->newMTLLibrary(nsSrc, conversionResult.resultInfo); // retained - [nsSrc release]; // release temp string - - slc->destroy(); - _shaderConversionResultInfo = conversionResult.resultInfo; - _msl = conversionResult.msl; + compressMSL(conversionResult.msl); + compileLibrary(conversionResult.msl); +} + +MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner, + const SPIRVToMSLConversionResultInfo& resultInfo, + const MVKCompressor compressedMSL) : _owner(owner) { + _shaderConversionResultInfo = resultInfo; + _compressedMSL = compressedMSL; + string msl; + decompressMSL(msl); + compileLibrary(msl); +} + +void MVKShaderLibrary::compileLibrary(const string& msl) { + MVKShaderLibraryCompiler* slc = new MVKShaderLibraryCompiler(_owner); + NSString* nsSrc = [[NSString alloc] initWithUTF8String: msl.c_str()]; // temp retained + _mtlLibrary = slc->newMTLLibrary(nsSrc, _shaderConversionResultInfo); // retained + [nsSrc release]; // release temp string + slc->destroy(); } MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner, @@ -176,7 +202,7 @@ MVKShaderLibrary::MVKShaderLibrary(const MVKShaderLibrary& other) { _owner = other._owner; _mtlLibrary = [other._mtlLibrary retain]; _shaderConversionResultInfo = other._shaderConversionResultInfo; - _msl = other._msl; + _compressedMSL = other._compressedMSL; } MVKShaderLibrary& MVKShaderLibrary::operator=(const MVKShaderLibrary& other) { @@ -186,7 +212,7 @@ MVKShaderLibrary& MVKShaderLibrary::operator=(const MVKShaderLibrary& other) { } _owner = other._owner; _shaderConversionResultInfo = other._shaderConversionResultInfo; - _msl = other._msl; + _compressedMSL = other._compressedMSL; return *this; } @@ -245,13 +271,22 @@ MVKShaderLibrary* MVKShaderLibraryCache::findShaderLibrary(SPIRVToMSLConversionC } // Adds and returns a new shader library configured from the specified conversion configuration. -MVKShaderLibrary* MVKShaderLibraryCache::addShaderLibrary(SPIRVToMSLConversionConfiguration* pShaderConfig, - SPIRVToMSLConversionResult& conversionResult) { +MVKShaderLibrary* MVKShaderLibraryCache::addShaderLibrary(const SPIRVToMSLConversionConfiguration* pShaderConfig, + const SPIRVToMSLConversionResult& conversionResult) { MVKShaderLibrary* shLib = new MVKShaderLibrary(_owner, conversionResult); _shaderLibraries.emplace_back(*pShaderConfig, shLib); return shLib; } +// Adds and returns a new shader library configured from contents read from a pipeline cache. +MVKShaderLibrary* MVKShaderLibraryCache::addShaderLibrary(const SPIRVToMSLConversionConfiguration* pShaderConfig, + const SPIRVToMSLConversionResultInfo& resultInfo, + const MVKCompressor compressedMSL) { + MVKShaderLibrary* shLib = new MVKShaderLibrary(_owner, resultInfo, compressedMSL); + _shaderLibraries.emplace_back(*pShaderConfig, shLib); + return shLib; +} + // Merge another shader library cache with this one. Handle null input. void MVKShaderLibraryCache::merge(MVKShaderLibraryCache* other) { if ( !other ) { return; } diff --git a/MoltenVK/MoltenVK/Layers/MVKLayers.mm b/MoltenVK/MoltenVK/Layers/MVKLayers.mm index 3405a56e..040712b3 100644 --- a/MoltenVK/MoltenVK/Layers/MVKLayers.mm +++ b/MoltenVK/MoltenVK/Layers/MVKLayers.mm @@ -19,7 +19,6 @@ #include "MVKLayers.h" #include "MVKEnvironment.h" #include "MVKFoundation.h" -#include "vk_mvk_moltenvk.h" #include using namespace std; diff --git a/MoltenVK/MoltenVK/Utility/MVKCodec.h b/MoltenVK/MoltenVK/Utility/MVKCodec.h index 136f4204..595a50fa 100644 --- a/MoltenVK/MoltenVK/Utility/MVKCodec.h +++ b/MoltenVK/MoltenVK/Utility/MVKCodec.h @@ -19,17 +19,18 @@ #pragma once -#include "MVKFoundation.h" +#include "MVKEnvironment.h" +#include #include +#pragma mark - #pragma mark Texture data codecs /** * This is the base class implemented by all codecs supported by MoltenVK. - * Objects of this class are used to decompress texture data for upload to a - * 3D texture. + * Objects of this class are used to decompress texture data for upload to a 3D texture. */ class MVKCodec { @@ -43,8 +44,89 @@ public: }; + +#pragma mark - +#pragma mark General data compressor + +/** + * Holds compressed data, along with information allowing it to be decompressed again. + * The template class C must support the basic data container methods data(), size() and resize(). + * + * THIS CLASS IS STREAMED OUT AS PART OF THE PIEPLINE CACHE. + * STURCTURAL CHANGES TO THIS CLASS MUST BE CAPTURED IN THE STREAMING LOGIC OF THE PIPELINE CACHE. + */ +template +class MVKCompressor { + +public: + + /** + * Compresses the content in the data container using the algorithm, and retains + * the compressed content. If an error occurs, or if the compressed data is actually + * larger (which can happen with some compression algorithms if the source is small), + * the uncompressed content is retained. Returns true if the content was successfully + * compressed, or returns false if the content was retained as uncompressed, + */ + bool compress(const C& uncompressed, MVKConfigCompressionAlgorithm algorithm) { + + _uncompressedSize = uncompressed.size(); + _compressed.resize(_uncompressedSize); + _algorithm = algorithm; + size_t compSize = mvkCompress((uint8_t*)uncompressed.data(), uncompressed.size(), + _compressed.data(), _compressed.size(), + _algorithm); + + bool wasCompressed = (compSize > 0); + if ( !wasCompressed ) { + _algorithm = MVK_CONFIG_COMPRESSION_ALGORITHM_NONE; + compSize = mvkCompress((uint8_t*)uncompressed.data(), uncompressed.size(), + _compressed.data(), _compressed.size(), + _algorithm); + } + + _compressed.resize(compSize); + _compressed.shrink_to_fit(); + + return wasCompressed; + } + + /** Decompress the retained compressed content into the data container. */ + void decompress(C& uncompressed) { + uncompressed.resize(_uncompressedSize); + mvkDecompress(_compressed.data(), _compressed.size(), + (uint8_t*)uncompressed.data(), uncompressed.size(), + _algorithm); + } + + std::vector _compressed; + size_t _uncompressedSize = 0; + MVKConfigCompressionAlgorithm _algorithm = MVK_CONFIG_COMPRESSION_ALGORITHM_NONE; +}; + + +#pragma mark - +#pragma mark Support functions + /** Returns an appropriate codec for the given format, or nullptr if the format is not supported. */ std::unique_ptr mvkCreateCodec(VkFormat format); /** Returns whether or not the given format can be decompressed. */ bool mvkCanDecodeFormat(VkFormat format); + +/** + * Compresses the source bytes into the destination bytes using a compression algorithm, + * and returns the number of bytes written to dstBytes. If an error occurs, or the compressed + * data is larger than dstSize, no data is copied to dstBytes, and zero is returned. + */ +size_t mvkCompress(const uint8_t* srcBytes, size_t srcSize, + uint8_t* dstBytes, size_t dstSize, + MVKConfigCompressionAlgorithm compAlgo); + +/** + * Decompresses the source bytes into the destination bytes using a compression algorithm, + * and returns the number of bytes written to dstBytes. If an error occurs, or the decompressed + * data is larger than dstSize, no data is copied to dstBytes, and zero is returned. + */ +size_t mvkDecompress(const uint8_t* srcBytes, size_t srcSize, + uint8_t* dstBytes, size_t dstSize, + MVKConfigCompressionAlgorithm compAlgo); diff --git a/MoltenVK/MoltenVK/Utility/MVKCodec.cpp b/MoltenVK/MoltenVK/Utility/MVKCodec.mm similarity index 53% rename from MoltenVK/MoltenVK/Utility/MVKCodec.cpp rename to MoltenVK/MoltenVK/Utility/MVKCodec.mm index 09669e49..7c07d6af 100644 --- a/MoltenVK/MoltenVK/Utility/MVKCodec.cpp +++ b/MoltenVK/MoltenVK/Utility/MVKCodec.mm @@ -18,10 +18,13 @@ #include "MVKCodec.h" +#include "MVKBaseObject.h" +#include "MVKFoundation.h" #include #include +using namespace std; using simd::float3; using simd::float4; @@ -62,8 +65,8 @@ public: for (uint32_t y = 0; y < extent.height; y += 4) { for (uint32_t x = 0; x < extent.width; x += 4) { VkExtent2D blockExtent; - blockExtent.width = std::min(extent.width - x, 4u); - blockExtent.height = std::min(extent.height - y, 4u); + blockExtent.width = min(extent.width - x, 4u); + blockExtent.height = min(extent.height - y, 4u); decompressDXTnBlock(pSrcRow + x * (blockByteCount / 4), pDestRow + x * 4, blockExtent, destLayout.rowPitch, _format); } @@ -90,7 +93,11 @@ private: VkFormat _format; }; -std::unique_ptr mvkCreateCodec(VkFormat format) { + +#pragma mark - +#pragma mark Support functions + +unique_ptr mvkCreateCodec(VkFormat format) { switch (format) { case VK_FORMAT_BC1_RGB_UNORM_BLOCK: case VK_FORMAT_BC1_RGB_SRGB_BLOCK: @@ -100,7 +107,7 @@ std::unique_ptr mvkCreateCodec(VkFormat format) { case VK_FORMAT_BC2_SRGB_BLOCK: case VK_FORMAT_BC3_UNORM_BLOCK: case VK_FORMAT_BC3_SRGB_BLOCK: - return std::unique_ptr(new MVKDXTnCodec(format)); + return unique_ptr(new MVKDXTnCodec(format)); default: return nullptr; @@ -123,3 +130,63 @@ bool mvkCanDecodeFormat(VkFormat format) { return false; } } + +static NSDataCompressionAlgorithm getSystemCompressionAlgo(MVKConfigCompressionAlgorithm compAlgo) { + switch (compAlgo) { + case MVK_CONFIG_COMPRESSION_ALGORITHM_NONE: return NSDataCompressionAlgorithmLZFSE; + case MVK_CONFIG_COMPRESSION_ALGORITHM_LZFSE: return NSDataCompressionAlgorithmLZFSE; + case MVK_CONFIG_COMPRESSION_ALGORITHM_LZ4: return NSDataCompressionAlgorithmLZ4; + case MVK_CONFIG_COMPRESSION_ALGORITHM_LZMA: return NSDataCompressionAlgorithmLZMA; + case MVK_CONFIG_COMPRESSION_ALGORITHM_ZLIB: return NSDataCompressionAlgorithmZlib; + default: return NSDataCompressionAlgorithmLZFSE; + } +} + +// Only copy into the dstBytes if it can fit, otherwise the data will be corrupted +static size_t mvkCompressDecompress(const uint8_t* srcBytes, size_t srcSize, + uint8_t* dstBytes, size_t dstSize, + MVKConfigCompressionAlgorithm compAlgo, + bool isCompressing) { + size_t dstByteCount = 0; + if (compAlgo != MVK_CONFIG_COMPRESSION_ALGORITHM_NONE) { + @autoreleasepool { + NSDataCompressionAlgorithm sysCompAlgo = getSystemCompressionAlgo(compAlgo); + NSData* srcData = [NSData dataWithBytesNoCopy: (void*)srcBytes length: srcSize freeWhenDone: NO]; + + NSError* err = nil; + NSData* dstData = (isCompressing + ? [srcData compressedDataUsingAlgorithm: sysCompAlgo error: &err] + : [srcData decompressedDataUsingAlgorithm: sysCompAlgo error: &err]); + if ( !err ) { + size_t dataLen = dstData.length; + if (dstSize >= dataLen) { + [dstData getBytes: dstBytes length: dstSize]; + dstByteCount = dataLen; + } + } else { + MVKBaseObject::reportError(nullptr, VK_ERROR_FORMAT_NOT_SUPPORTED, + "Could not %scompress data (Error code %li):\n%s", + (isCompressing ? "" : "de"), + (long)err.code, err.localizedDescription.UTF8String); + } + } + } else if (dstSize >= srcSize) { + mvkCopy(dstBytes, srcBytes, srcSize); + dstByteCount = srcSize; + } + return dstByteCount; +} + +size_t mvkCompress(const uint8_t* srcBytes, size_t srcSize, + uint8_t* dstBytes, size_t dstSize, + MVKConfigCompressionAlgorithm compAlgo) { + + return mvkCompressDecompress(srcBytes, srcSize, dstBytes, dstSize, compAlgo, true); +} + +size_t mvkDecompress(const uint8_t* srcBytes, size_t srcSize, + uint8_t* dstBytes, size_t dstSize, + MVKConfigCompressionAlgorithm compAlgo) { + + return mvkCompressDecompress(srcBytes, srcSize, dstBytes, dstSize, compAlgo, false); +} diff --git a/MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp b/MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp index 9861a359..1381c616 100644 --- a/MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp +++ b/MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp @@ -39,7 +39,7 @@ static void mvkInitConfigFromEnvVars() { MVK_SET_FROM_ENV_OR_BUILD_INT64 (evCfg.metalCompileTimeout, MVK_CONFIG_METAL_COMPILE_TIMEOUT); MVK_SET_FROM_ENV_OR_BUILD_BOOL (evCfg.performanceTracking, MVK_CONFIG_PERFORMANCE_TRACKING); MVK_SET_FROM_ENV_OR_BUILD_INT32 (evCfg.performanceLoggingFrameCount, MVK_CONFIG_PERFORMANCE_LOGGING_FRAME_COUNT); - MVK_SET_FROM_ENV_OR_BUILD_BOOL (evCfg.logActivityPerformanceInline, MVK_CONFIG_PERFORMANCE_LOGGING_INLINE); + MVK_SET_FROM_ENV_OR_BUILD_INT32 (evCfg.activityPerformanceLoggingStyle, MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE); MVK_SET_FROM_ENV_OR_BUILD_BOOL (evCfg.displayWatermark, MVK_CONFIG_DISPLAY_WATERMARK); MVK_SET_FROM_ENV_OR_BUILD_BOOL (evCfg.specializedQueueFamilies, MVK_CONFIG_SPECIALIZED_QUEUE_FAMILIES); MVK_SET_FROM_ENV_OR_BUILD_BOOL (evCfg.switchSystemGPU, MVK_CONFIG_SWITCH_SYSTEM_GPU); @@ -62,6 +62,7 @@ static void mvkInitConfigFromEnvVars() { MVK_SET_FROM_ENV_OR_BUILD_INT32 (evCfg.advertiseExtensions, MVK_CONFIG_ADVERTISE_EXTENSIONS); MVK_SET_FROM_ENV_OR_BUILD_BOOL (evCfg.resumeLostDevice, MVK_CONFIG_RESUME_LOST_DEVICE); MVK_SET_FROM_ENV_OR_BUILD_INT32 (evCfg.useMetalArgumentBuffers, MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS); + MVK_SET_FROM_ENV_OR_BUILD_INT32 (evCfg.shaderSourceCompressionAlgorithm, MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM); // Deprected legacy VkSemaphore MVK_ALLOW_METAL_FENCES and MVK_ALLOW_METAL_EVENTS config. // Legacy MVK_ALLOW_METAL_EVENTS is covered by MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE, @@ -75,6 +76,17 @@ static void mvkInitConfigFromEnvVars() { evCfg.semaphoreUseMTLEvent = (MVKVkSemaphoreSupportStyle)false; // Disabled. Also semaphoreSupportStyle MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_SINGLE_QUEUE. } + // Deprecated legacy env var MVK_CONFIG_PERFORMANCE_LOGGING_INLINE config. If legacy + // MVK_CONFIG_PERFORMANCE_LOGGING_INLINE env var was used, and activityPerformanceLoggingStyle + // was not already set by MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE, set + // activityPerformanceLoggingStyle to MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_IMMEDIATE. + bool logPerfInline; + MVK_SET_FROM_ENV_OR_BUILD_BOOL(logPerfInline, MVK_CONFIG_PERFORMANCE_LOGGING_INLINE); + if (logPerfInline && evCfg.activityPerformanceLoggingStyle == MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_FRAME_COUNT) { + evCfg.activityPerformanceLoggingStyle = MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_IMMEDIATE; + } + + mvkSetConfig(evCfg); } diff --git a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h index 16833d08..cec1740e 100644 --- a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h +++ b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h @@ -151,8 +151,11 @@ void mvkSetConfig(const MVKConfiguration& mvkConfig); # define MVK_CONFIG_PERFORMANCE_LOGGING_FRAME_COUNT 0 #endif -/** Log activity performance every time an activity occurs. Disabled by default. */ -# ifndef MVK_CONFIG_PERFORMANCE_LOGGING_INLINE +/** Activity performance logging style. Default is to log after a configured number of frames. */ +# ifndef MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE +# define MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_FRAME_COUNT +# endif +# ifndef MVK_CONFIG_PERFORMANCE_LOGGING_INLINE // Deprecated # define MVK_CONFIG_PERFORMANCE_LOGGING_INLINE 0 # endif @@ -286,3 +289,8 @@ void mvkSetConfig(const MVKConfiguration& mvkConfig); #ifndef MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS # define MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_NEVER #endif + +/** Compress MSL shader source code in a pipeline cache. Defaults to no compression. */ +#ifndef MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM +# define MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM MVK_CONFIG_COMPRESSION_ALGORITHM_NONE +#endif diff --git a/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.h b/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.h index 34c02b28..765e110f 100644 --- a/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.h +++ b/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.h @@ -279,7 +279,7 @@ namespace mvk { bool hasSPIRV() { return !_spirv.empty(); } /** - * Converts SPIR-V code, set using setSPIRV() to MSL code, which can be retrieved using getMSL(). + * Converts SPIR-V code, set using setSPIRV() to MSL code. * * The boolean flags indicate whether the original SPIR-V code, the resulting MSL code, * and optionally, the original GLSL (as converted from the SPIR_V), should be logged diff --git a/Scripts/runcts b/Scripts/runcts index 4cc33e78..2349e75d 100755 --- a/Scripts/runcts +++ b/Scripts/runcts @@ -94,22 +94,24 @@ if [ "${is_portability}" != "" ]; then export MVK_CONFIG_ADVERTISE_EXTENSIONS=0xA fi +# ----- Metal validation settings ------ export METAL_DEVICE_WRAPPER_TYPE=1 export METAL_ERROR_MODE=3 export METAL_DEBUG_ERROR_MODE=3 # ----- MoltenVK config settings ------ -export MVK_CONFIG_LOG_LEVEL=1 +export MVK_CONFIG_LOG_LEVEL=1 #(1 = Errors only, 3 = Info) export MVK_DEBUG=0 -# Additional MoltenVK configuration can be set here by -# editing below, or can be set before calling this script. +# Additional MoltenVK configuration can be set here by editing below. export MVK_CONFIG_RESUME_LOST_DEVICE=1 export MVK_CONFIG_FAST_MATH_ENABLED=1 -export MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=0 #(2 = VK_EXT_descriptor_indexing enabled) export MVK_CONFIG_FORCE_LOW_POWER_GPU=0 -export MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE=2 #(2 = MTLEvents always) - +export MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=0 #(2 = VK_EXT_descriptor_indexing enabled) +export MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE=2 #(2 = MTLEvents always) +export MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM=0 #(2 = ZLIB, 3 = LZ4) +export MVK_CONFIG_PERFORMANCE_TRACKING=0 +export MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE=2 #(2 = Device lifetime) # -------------- Operation --------------------