From 02ee15d927254be2bb52d5e580a6a78c73bbf619 Mon Sep 17 00:00:00 2001 From: Chris Dalton Date: Fri, 19 Jul 2024 07:44:33 -0700 Subject: [PATCH] Implement VK_EXT_rasterization_order_attachment_access Implement VK_EXT_rasterization_order_attachment_access using the "programmable blending" feature available on Apple family GPUs. --- MoltenVK/MoltenVK/API/mvk_private_api.h | 1 + MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h | 3 ++- MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm | 13 ++++++++++--- MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm | 9 ++++++--- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 8 ++++++++ MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm | 5 ++++- MoltenVK/MoltenVK/Layers/MVKExtensions.def | 2 ++ 7 files changed, 33 insertions(+), 8 deletions(-) diff --git a/MoltenVK/MoltenVK/API/mvk_private_api.h b/MoltenVK/MoltenVK/API/mvk_private_api.h index f98e101d6..d58e7058e 100644 --- a/MoltenVK/MoltenVK/API/mvk_private_api.h +++ b/MoltenVK/MoltenVK/API/mvk_private_api.h @@ -357,6 +357,7 @@ typedef struct { VkBool32 needsCubeGradWorkaround; /**< If true, sampling from cube textures with explicit gradients is broken and needs a workaround. */ VkBool32 nativeTextureAtomics; /**< If true, atomic operations on textures are supported natively. */ VkBool32 needsArgumentBufferEncoders; /**< If true, Metal argument buffer encoders are needed to populate argument buffer content. */ + VkBool32 programmableBlending; /**< If true, the Apple "programmable blending" feature is supported. */ } MVKPhysicalDeviceMetalFeatures; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h index 92e6504dc..256d83671 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h @@ -78,7 +78,8 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s uint32_t count, VkDescriptorType descType, MVKSampler* immutableSampler, - bool usingNativeTextureAtomics); + bool usingNativeTextureAtomics, + bool usingProgrammableBlending); #pragma mark - diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm index 36b075d29..99a6a4fa2 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm @@ -109,7 +109,8 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s uint32_t count, VkDescriptorType descType, MVKSampler* immutableSampler, - bool usingNativeTextureAtomics) { + bool usingNativeTextureAtomics, + bool usingProgrammableBlending) { if (count == 0) { return; } #define addResourceBinding(spvRezType) \ @@ -156,8 +157,13 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s break; } - case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + if (!usingProgrammableBlending) { + addResourceBinding(Image); + } + break; + + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: addResourceBinding(Image); break; @@ -550,7 +556,8 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s descCnt, getDescriptorType(), mvkSamp, - getMetalFeatures().nativeTextureAtomics); + getMetalFeatures().nativeTextureAtomics, + getMetalFeatures().programmableBlending); } } } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm index b98a6e74d..2556cabc8 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm @@ -236,7 +236,8 @@ static void populateAuxBuffer(mvk::SPIRVToMSLConversionConfiguration& shaderConf MVKShaderStageResourceBinding buffBinding, uint32_t descSetIndex, uint32_t descBinding, - bool usingNativeTextureAtomics) { + bool usingNativeTextureAtomics, + bool usingProgrammableBlending) { for (uint32_t stage = kMVKShaderStageVertex; stage < kMVKShaderStageCount; stage++) { mvkPopulateShaderConversionConfig(shaderConfig, buffBinding, @@ -246,7 +247,8 @@ static void populateAuxBuffer(mvk::SPIRVToMSLConversionConfiguration& shaderConf 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, nullptr, - usingNativeTextureAtomics); + usingNativeTextureAtomics, + usingProgrammableBlending); } } @@ -264,7 +266,8 @@ static void populateAuxBuffer(mvk::SPIRVToMSLConversionConfiguration& shaderConf buffBinding.bufferIndex = getBufferSizeBufferArgBuferIndex(); populateAuxBuffer(shaderConfig, buffBinding, descSetIndex, MVK_spirv_cross::kBufferSizeBufferBinding, - getMetalFeatures().nativeTextureAtomics); + getMetalFeatures().nativeTextureAtomics, + getMetalFeatures().programmableBlending); } // If the app is using argument buffers, but this descriptor set is diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 2d6525788..d4dd7a242 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -1436,6 +1436,9 @@ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + if (_metalFeatures.programmableBlending) { + surfCaps.supportedUsageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + } // Swapchain-to-surface scaling capabilities. if (pScalingCaps) { @@ -2455,6 +2458,7 @@ } #endif + _metalFeatures.programmableBlending = _isAppleGPU; } // Initializes the physical device features of this instance. @@ -3419,6 +3423,10 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope pWritableExtns->vk_IMG_format_pvrtc.enabled = false; } #endif + + if (!_metalFeatures.programmableBlending) { + pWritableExtns->vk_EXT_rasterization_order_attachment_access.enabled = false; + } } void MVKPhysicalDevice::initCounterSets() { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm index c0687b288..b88a5a1c0 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -105,7 +105,8 @@ 1, VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT, nullptr, - getMetalFeatures().nativeTextureAtomics); + getMetalFeatures().nativeTextureAtomics, + getMetalFeatures().programmableBlending); } } @@ -1821,6 +1822,8 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 shaderConfig.options.tessPatchKind = reflectData.patchKind; shaderConfig.options.numTessControlPoints = reflectData.numControlPoints; + + shaderConfig.options.mslOptions.use_framebuffer_fetch_subpasses = mtlFeats.programmableBlending; } uint32_t MVKGraphicsPipeline::getImplicitBufferIndex(MVKShaderStage stage, uint32_t bufferIndexOffset) { diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def index 5eea40932..747480068 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def @@ -145,8 +145,10 @@ MVK_EXTENSION(EXT_texel_buffer_alignment, EXT_TEXEL_BUFFER_ALIGNMENT MVK_EXTENSION(EXT_texture_compression_astc_hdr, EXT_TEXTURE_COMPRESSION_ASTC_HDR, DEVICE, 11.0, 13.0, 1.0) MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR, DEVICE, 10.11, 8.0, 1.0) MVK_EXTENSION(AMD_draw_indirect_count, AMD_DRAW_INDIRECT_COUNT, DEVICE, MVK_NA, MVK_NA, MVK_NA) + MVK_EXTENSION(AMD_gpu_shader_half_float, AMD_GPU_SHADER_HALF_FLOAT, DEVICE, 10.11, 8.0, 1.0) MVK_EXTENSION(AMD_negative_viewport_height, AMD_NEGATIVE_VIEWPORT_HEIGHT, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_rasterization_order_attachment_access, EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS, DEVICE, 10.11, 8.0, 1.0) MVK_EXTENSION(AMD_shader_image_load_store_lod, AMD_SHADER_IMAGE_LOAD_STORE_LOD, DEVICE, 11.0, 8.0, 1.0) MVK_EXTENSION(AMD_shader_trinary_minmax, AMD_SHADER_TRINARY_MINMAX, DEVICE, 10.14, 12.0, 1.0) MVK_EXTENSION(IMG_format_pvrtc, IMG_FORMAT_PVRTC, DEVICE, 11.0, 8.0, 1.0)