From deaaab8effa2aab01c69b5446e1f8e077511d1a1 Mon Sep 17 00:00:00 2001 From: Chip Davis Date: Fri, 6 Sep 2019 12:27:40 -0500 Subject: [PATCH] Support the VK_EXT_fragment_shader_interlock extension. This extension allows fragment shaders to delineate critical sections where pairs of invocations may not execute simultaneously. In Metal, the nearest equivalent functionality is raster order groups. This implementation is thus implemented on top of them. Update SPIRV-Cross to pull in SPIR-V support for this new extension. --- Docs/MoltenVK_Runtime_UserGuide.md | 1 + Docs/Whats_New.md | 21 +++++++++++++ ExternalRevisions/SPIRV-Cross_repo_revision | 2 +- MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h | 1 + MoltenVK/MoltenVK/GPUObjects/MVKDevice.h | 1 + MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 30 ++++++++++++++++++- MoltenVK/MoltenVK/Layers/MVKExtensions.def | 1 + MoltenVK/MoltenVK/Layers/MVKExtensions.mm | 6 ++++ .../SPIRVToMSLConverter.cpp | 2 +- 9 files changed, 62 insertions(+), 3 deletions(-) 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 513252fa1..372724b62 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; } @@ -1648,6 +1660,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; } @@ -2291,6 +2306,7 @@ _enabledF16I8Features(), _enabledUBOLayoutFeatures(), _enabledVarPtrFeatures(), + _enabledInterlockFeatures(), _enabledHostQryResetFeatures(), _enabledScalarLayoutFeatures(), _enabledTexelBuffAlignFeatures(), @@ -2405,6 +2421,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)); @@ -2432,9 +2449,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; @@ -2510,6 +2531,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; }