diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md index 8fc20afb3..9bd6595a3 100644 --- a/Docs/MoltenVK_Runtime_UserGuide.md +++ b/Docs/MoltenVK_Runtime_UserGuide.md @@ -254,6 +254,7 @@ In addition to the core *Vulkan* API, **MoltenVK** also supports the following - `VK_EXT_debug_marker` - `VK_EXT_debug_report` - `VK_EXT_debug_utils` +- `VK_EXT_fragment_shader_interlock` *(requires Metal 2.0 and Raster Order Groups)* - `VK_EXT_host_query_reset` - `VK_EXT_memory_budget` *(requires Metal 2.0)* - `VK_EXT_metal_surface` diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 6ad084335..ad000f4c9 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -20,6 +20,7 @@ Released TBD - Add support for extensions: - `VK_KHR_device_group` + - `VK_EXT_fragment_shader_interlock` - Add support for `VkEvent`, using either native `MTLEvent` or emulation when `MTLEvent` not available. - `vkInvalidateMappedMemoryRanges()` synchronizes managed device memory to CPU. - Track supported instance and device extensions correctly. @@ -44,7 +45,27 @@ Released TBD `MVKConfiguration::presentWithCommandBuffer` is now obsolete. - Don't use `MTLCommandBuffer push/popDebugGroup` if not available. - Add ability to automatically cause an *Xcode* GPU capture without developer intervention. +- On macOS, limit uniform buffer bindings to 64k. - Update `VK_MVK_MOLTENVK_SPEC_VERSION` to version 22. +- Update to latest SPIRV-Cross version: + - MSL: Deal with array copies from and to threadgroup. + - MSL: Inline all emitted functions. + - MSL: Inline all non-entry-point functions. + - MSL: Add `{Base,}{Vertex,Instance}{,Index}` to `bitcast_from_builtin_load`. + - MSL: Add support for sampler Y'CbCr conversion. + - MSL: Force storage images on iOS to use discrete descriptors. + - MSL: Support dynamic offsets for buffers in argument buffers. + - Support the `SPV_EXT_fragment_shader_interlock` extension. + - Fix variable scope when switch block exits multiple times. + - Deal correctly with sign on bitfield operations. + - Elide branches to continue block when continue block is also a merge. + - Move branchless analysis to CFG. + - Deal with `ldexp` taking `uint` input. + - Do not allow base expressions for non-native row-major matrices. + - GLSL: Assume image and sampler can be `RelaxedPrecision`. + - GLSL: Fix post-depth coverage for ESSL. + - Fix `ParsedIR::mark_used_as_array_length(uint32_t id)`. + - Refactor into stronger types in public API. diff --git a/ExternalRevisions/SPIRV-Cross_repo_revision b/ExternalRevisions/SPIRV-Cross_repo_revision index fc4d9ebe9..999ffa716 100644 --- a/ExternalRevisions/SPIRV-Cross_repo_revision +++ b/ExternalRevisions/SPIRV-Cross_repo_revision @@ -1 +1 @@ -4ce04480ec5469fe7ebbdd66c3016090a704d81b +2082e7e80189843a52d9a79bc17787af93b517de diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h index fbd797805..3b5af9242 100644 --- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h +++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h @@ -547,6 +547,7 @@ typedef struct { VkBool32 textureBuffers; /**< If true, textures of type MTLTextureTypeBuffer are supported. */ VkBool32 postDepthCoverage; /**< If true, coverage masks in fragment shaders post-depth-test are supported. */ VkBool32 fences; /**< If true, Metal synchronization fences (MTLFence) are supported. */ + VkBool32 rasterOrderGroups; /**< If true, Raster order groups in fragment shaders are supported. */ } MVKPhysicalDeviceMetalFeatures; /** diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index 6649ba0e5..adbc3b236 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -638,6 +638,7 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { const VkPhysicalDeviceFloat16Int8FeaturesKHR _enabledF16I8Features; const VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR _enabledUBOLayoutFeatures; const VkPhysicalDeviceVariablePointerFeatures _enabledVarPtrFeatures; + const VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT _enabledInterlockFeatures; const VkPhysicalDeviceHostQueryResetFeaturesEXT _enabledHostQryResetFeatures; const VkPhysicalDeviceScalarBlockLayoutFeaturesEXT _enabledScalarLayoutFeatures; const VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT _enabledTexelBuffAlignFeatures; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index bc89164c1..2456bfa0c 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -102,6 +102,13 @@ varPtrFeatures->variablePointers = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: { + auto* interlockFeatures = (VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT*)next; + interlockFeatures->fragmentShaderSampleInterlock = _metalFeatures.rasterOrderGroups; + interlockFeatures->fragmentShaderPixelInterlock = _metalFeatures.rasterOrderGroups; + interlockFeatures->fragmentShaderShadingRateInterlock = false; // Requires variable rate shading; not supported yet in Metal + break; + } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT: { auto* hostQueryResetFeatures = (VkPhysicalDeviceHostQueryResetFeaturesEXT*)next; hostQueryResetFeatures->hostQueryReset = true; @@ -861,6 +868,11 @@ #endif + // Note the selector name, which is different from the property name. + if ( [_mtlDevice respondsToSelector: @selector(areRasterOrderGroupsSupported)] ) { + _metalFeatures.rasterOrderGroups = _mtlDevice.rasterOrderGroupsSupported; + } + if ( [_mtlDevice respondsToSelector: @selector(maxBufferLength)] ) { _metalFeatures.maxMTLBufferSize = _mtlDevice.maxBufferLength; } @@ -1652,6 +1664,9 @@ MVKExtensionList* pWritableExtns = (MVKExtensionList*)&_supportedExtensions; pWritableExtns->disableAllButEnabledDeviceExtensions(); + if (!_metalFeatures.rasterOrderGroups) { + pWritableExtns->vk_EXT_fragment_shader_interlock.enabled = false; + } if (!_metalFeatures.postDepthCoverage) { pWritableExtns->vk_EXT_post_depth_coverage.enabled = false; } @@ -2295,6 +2310,7 @@ _enabledF16I8Features(), _enabledUBOLayoutFeatures(), _enabledVarPtrFeatures(), + _enabledInterlockFeatures(), _enabledHostQryResetFeatures(), _enabledScalarLayoutFeatures(), _enabledTexelBuffAlignFeatures(), @@ -2409,6 +2425,7 @@ memset((void*)&_enabledF16I8Features, 0, sizeof(_enabledF16I8Features)); memset((void*)&_enabledUBOLayoutFeatures, 0, sizeof(_enabledUBOLayoutFeatures)); memset((void*)&_enabledVarPtrFeatures, 0, sizeof(_enabledVarPtrFeatures)); + memset((void*)&_enabledInterlockFeatures, 0, sizeof(_enabledInterlockFeatures)); memset((void*)&_enabledHostQryResetFeatures, 0, sizeof(_enabledHostQryResetFeatures)); memset((void*)&_enabledScalarLayoutFeatures, 0, sizeof(_enabledScalarLayoutFeatures)); memset((void*)&_enabledTexelBuffAlignFeatures, 0, sizeof(_enabledTexelBuffAlignFeatures)); @@ -2436,9 +2453,13 @@ pdHostQryResetFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT; pdHostQryResetFeatures.pNext = &pdScalarLayoutFeatures; + VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT pdInterlockFeatures; + pdInterlockFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT; + pdInterlockFeatures.pNext = &pdHostQryResetFeatures; + VkPhysicalDeviceVariablePointerFeatures pdVarPtrFeatures; pdVarPtrFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES; - pdVarPtrFeatures.pNext = &pdHostQryResetFeatures; + pdVarPtrFeatures.pNext = &pdInterlockFeatures; VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR pdUBOLayoutFeatures; pdUBOLayoutFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR; @@ -2514,6 +2535,13 @@ &pdVarPtrFeatures.variablePointersStorageBuffer, 2); break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: { + auto* requestedFeatures = (VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT*)next; + enableFeatures(&_enabledInterlockFeatures.fragmentShaderSampleInterlock, + &requestedFeatures->fragmentShaderSampleInterlock, + &pdInterlockFeatures.fragmentShaderSampleInterlock, 3); + break; + } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT: { auto* requestedFeatures = (VkPhysicalDeviceHostQueryResetFeaturesEXT*)next; enableFeatures(&_enabledHostQryResetFeatures.hostQueryReset, diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def index 8f8ab0366..9a2a3203c 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def @@ -67,6 +67,7 @@ MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS, MVK_EXTENSION_DEVICE MVK_EXTENSION(EXT_debug_marker, EXT_DEBUG_MARKER, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT, MVK_EXTENSION_INSTANCE) MVK_EXTENSION(EXT_debug_utils, EXT_DEBUG_UTILS, MVK_EXTENSION_INSTANCE) +MVK_EXTENSION(EXT_fragment_shader_interlock, EXT_FRAGMENT_SHADER_INTERLOCK, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE, MVK_EXTENSION_INSTANCE) diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.mm b/MoltenVK/MoltenVK/Layers/MVKExtensions.mm index 1a670eead..7d069b8a1 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.mm +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.mm @@ -47,6 +47,9 @@ static VkExtensionProperties mvkMakeExtProps(const char* extensionName, uint32_t // Returns whether the specified properties are valid for this platform static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) { #if MVK_MACOS + if (pProperties == &kVkExtProps_EXT_FRAGMENT_SHADER_INTERLOCK) { + return mvkOSVersion() >= 10.13; + } if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) { return mvkOSVersion() >= 10.13; } @@ -66,6 +69,9 @@ static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) { #endif #if MVK_IOS if (pProperties == &kVkExtProps_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE) { return false; } + if (pProperties == &kVkExtProps_EXT_FRAGMENT_SHADER_INTERLOCK) { + return mvkOSVersion() >= 11.0; + } if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) { return mvkOSVersion() >= 11.0; } diff --git a/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.cpp b/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.cpp index e33148699..59790c327 100644 --- a/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.cpp +++ b/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.cpp @@ -425,7 +425,7 @@ void SPIRVToMSLConverter::populateWorkgroupDimension(SPIRVWorkgroupSizeDimension uint32_t size, SPIRV_CROSS_NAMESPACE::SpecializationConstant& spvSpecConst) { wgDim.size = max(size, 1u); - wgDim.isSpecialized = (spvSpecConst.id != 0); + wgDim.isSpecialized = (uint32_t(spvSpecConst.id) != 0); wgDim.specializationID = spvSpecConst.constant_id; }