From 60a429f353ebb694faa15172a836922191bee3f8 Mon Sep 17 00:00:00 2001 From: Chip Davis Date: Mon, 19 Oct 2020 03:55:20 -0500 Subject: [PATCH] Support the depth bounds test. This isn't even a regular SPI. It's not even present in the Metal framework. It's exposed by the driver. Only AMD drivers support the method we need for now. --- Docs/Whats_New.md | 1 + MoltenVK/MoltenVK/Commands/MVKCmdRendering.h | 35 +++++++++++++++++++ MoltenVK/MoltenVK/Commands/MVKCmdRendering.mm | 24 +++++++++++++ .../Commands/MVKCommandEncoderState.h | 9 +++++ .../Commands/MVKCommandEncoderState.mm | 33 +++++++++++++++++ .../MoltenVK/Commands/MVKCommandTypePools.def | 2 ++ MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 7 ++++ MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm | 3 ++ MoltenVK/MoltenVK/Vulkan/vulkan.mm | 2 ++ README.md | 1 + 10 files changed, 117 insertions(+) diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index b2570f10..fc72286a 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -21,6 +21,7 @@ Released TBD - Add `MVK_USE_METAL_PRIVATE_API` build setting to allow **MoltenVK** to be built with access to _Metal_ private API calls. - Add support for `VkPhysicalDeviceFeatures::wideLines` feature when `MVK_USE_METAL_PRIVATE_API` is enabled in a **MoltenVK** build. - Add support for the `VkPhysicalDeviceFeatures::logicOp` feature when `MVK_USE_METAL_PRIVATE_API` is enabled in a **MoltenVK** build. +- Add support for the `VkPhysicalDeviceFeatures::depthBounds` feature on AMD GPUs when `MVK_USE_METAL_PRIVATE_API` is enabled in a **MoltenVK** build. - Add support for the `VkPhysicalDevicePortabilitySubsetFeaturesKHR::samplerMipLodBias` feature when `MVK_USE_METAL_PRIVATE_API` is enabled in a **MoltenVK** build. - Add support for Metal native pipeline sample masks when `MVK_USE_METAL_PRIVATE_API` is enabled in a **MoltenVK** build. - Fix potential crash when using multi-planar images. diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRendering.h b/MoltenVK/MoltenVK/Commands/MVKCmdRendering.h index 4b5dadcb..1f6d2559 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRendering.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRendering.h @@ -375,6 +375,41 @@ protected: }; +#pragma mark - +#pragma mark MVKCmdSetDepthBounds + +/** Vulkan command to set depth bounds. */ +class MVKCmdSetDepthBounds : public MVKCommand { + +public: + VkResult setContent(MVKCommandBuffer* cmdBuff, + float minDepthBounds, + float maxDepthBounds); + + void encode(MVKCommandEncoder* cmdEncoder) override; + +protected: + MVKCommandTypePool* getTypePool(MVKCommandPool* cmdPool) override; + + float _minDepthBounds; + float _maxDepthBounds; +}; + + +#pragma mark - +#pragma mark MVKCmdSetDepthBoundsTestEnable + +/** Vulkan command to enable depth bounds testing. */ +class MVKCmdSetDepthBoundsTestEnable : public MVKSingleValueCommand { + +public: + void encode(MVKCommandEncoder* cmdEncoder) override; + +protected: + MVKCommandTypePool* getTypePool(MVKCommandPool* cmdPool) override; +}; + + #pragma mark - #pragma mark MVKCmdSetStencilTestEnable diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRendering.mm b/MoltenVK/MoltenVK/Commands/MVKCmdRendering.mm index 132f0927..0c9d8ed9 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRendering.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRendering.mm @@ -327,6 +327,30 @@ void MVKCmdSetDepthCompareOp::encode(MVKCommandEncoder* cmdEncoder) { } +#pragma mark - +#pragma mark MVKCmdSetDepthBounds + +VkResult MVKCmdSetDepthBounds::setContent(MVKCommandBuffer* cmdBuff, + float minDepthBounds, + float maxDepthBounds) { + _minDepthBounds = minDepthBounds; + _maxDepthBounds = maxDepthBounds; + return VK_SUCCESS; +} + +void MVKCmdSetDepthBounds::encode(MVKCommandEncoder* cmdEncoder) { + cmdEncoder->_renderingState.setDepthBounds(_minDepthBounds, _maxDepthBounds, true); +} + + +#pragma mark - +#pragma mark MVKCmdSetDepthBoundsTestEnable + +void MVKCmdSetDepthBoundsTestEnable::encode(MVKCommandEncoder* cmdEncoder) { + cmdEncoder->_renderingState.setDepthBoundsTestEnable(_value, true); +} + + #pragma mark - #pragma mark MVKCmdSetStencilTestEnable diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h index f90ecf8e..125a8db5 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h @@ -239,6 +239,11 @@ struct MVKDepthBias { float depthBiasClamp; }; +struct MVKDepthBounds { + float minDepthBound; + float maxDepthBound; +}; + struct MVKStencilReference { uint32_t frontFaceValue; uint32_t backFaceValue; @@ -272,6 +277,8 @@ public: void setDepthBiasEnable(VkBool32 depthBiasEnable); void setDepthClipEnable(bool depthClip, bool isDynamic); + void setDepthBounds(float minDepthBounds, float maxDepthBounds, bool isDynamic); + void setDepthBoundsTestEnable(VkBool32 depthBoundsTestEnable, bool isDynamic); void setStencilReferenceValues(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo); void setStencilReferenceValues(VkStencilFaceFlags faceMask, uint32_t stencilReference); @@ -318,6 +325,7 @@ protected: MVKMTLScissors _mtlScissors[StateScope::Count] = {}; MVKColor32 _mtlBlendConstants[StateScope::Count] = {}; MVKDepthBias _mtlDepthBias[StateScope::Count] = {}; + MVKDepthBounds _mtlDepthBounds[StateScope::Count] = {}; MVKStencilReference _mtlStencilReference[StateScope::Count] = {}; MTLCullMode _mtlCullMode[StateScope::Count] = { MTLCullModeNone, MTLCullModeNone }; MTLWinding _mtlFrontFace[StateScope::Count] = { MTLWindingClockwise, MTLWindingClockwise }; @@ -332,6 +340,7 @@ protected: bool _mtlDepthBiasEnable[StateScope::Count] = {}; bool _mtlPrimitiveRestartEnable[StateScope::Count] = {}; bool _mtlRasterizerDiscardEnable[StateScope::Count] = {}; + bool _mtlDepthBoundsTestEnable[StateScope::Count] = {}; bool _cullBothFaces[StateScope::Count] = {}; bool _isPolygonModePoint[StateScope::Count] = {}; }; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm index 71135a6e..8df4dde9 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm @@ -369,6 +369,16 @@ void MVKRenderingCommandEncoderState::setDepthClipEnable(bool depthClip, bool is setMTLContent(DepthClipEnable); } +void MVKRenderingCommandEncoderState::setDepthBounds(float minDepthBounds, float maxDepthBounds, bool isDynamic) { + MVKDepthBounds mtlDepthBounds = { minDepthBounds, maxDepthBounds }; + setMTLContent(DepthBounds); +} + +void MVKRenderingCommandEncoderState::setDepthBoundsTestEnable(VkBool32 depthBoundsTestEnable, bool isDynamic) { + auto mtlDepthBoundsTestEnable = static_cast(depthBoundsTestEnable); + setMTLContent(DepthBoundsTestEnable); +} + void MVKRenderingCommandEncoderState::setStencilReferenceValues(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo) { bool isDynamic = false; MVKStencilReference mtlStencilReference = { @@ -545,6 +555,14 @@ bool MVKRenderingCommandEncoderState::needsMetalRenderPassRestart() { // An extension of the MTLRenderCommandEncoder protocol to declare the setLineWidth: method. @protocol MVKMTLRenderCommandEncoderLineWidth -(void) setLineWidth: (float) width; +@end + +// An extension of the MTLRenderCommandEncoder protocol containing a declaration of the +// -setDepthBoundsTestAMD:minDepth:maxDepth: method. +@protocol MVKMTLRenderCommandEncoderDepthBoundsAMD + +- (void)setDepthBoundsTestAMD:(BOOL)enable minDepth:(float)minDepth maxDepth:(float)maxDepth; + @end #endif @@ -584,6 +602,21 @@ void MVKRenderingCommandEncoderState::encodeImpl(uint32_t stage) { [rendEnc setDepthClipMode: getMTLContent(DepthClipEnable)]; } +#if MVK_USE_METAL_PRIVATE_API + if (getMVKConfig().useMetalPrivateAPI && (isDirty(DepthBoundsTestEnable) || isDirty(DepthBounds)) && + _cmdEncoder->_pDeviceFeatures->depthBounds) { + if (getMTLContent(DepthBoundsTestEnable)) { + auto& db = getMTLContent(DepthBounds); + [(id)_cmdEncoder->_mtlRenderEncoder setDepthBoundsTestAMD: YES + minDepth: db.minDepthBound + maxDepth: db.maxDepthBound]; + } else { + [(id)_cmdEncoder->_mtlRenderEncoder setDepthBoundsTestAMD: NO + minDepth: 0.0f + maxDepth: 1.0f]; + } + } +#endif if (isDirty(StencilReference)) { auto& sr = getMTLContent(StencilReference); [rendEnc setStencilFrontReferenceValue: sr.frontFaceValue backReferenceValue: sr.backFaceValue]; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def b/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def index d6495857..a79fd199 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def +++ b/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def @@ -90,6 +90,8 @@ MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(SetScissor, 1) MVK_CMD_TYPE_POOL(SetBlendConstants) MVK_CMD_TYPE_POOL(SetDepthBias) MVK_CMD_TYPE_POOL(SetDepthBiasEnable) +MVK_CMD_TYPE_POOL(SetDepthBounds) +MVK_CMD_TYPE_POOL(SetDepthBoundsTestEnable) MVK_CMD_TYPE_POOL(SetDepthTestEnable) MVK_CMD_TYPE_POOL(SetDepthWriteEnable) MVK_CMD_TYPE_POOL(SetDepthClipEnable) diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index cbb8d566..ef7fbcbe 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -2443,6 +2443,13 @@ void MVKPhysicalDevice::initFeatures() { _features.shaderStorageImageArrayDynamicIndexing = _metalFeatures.arrayOfTextures; +#if MVK_USE_METAL_PRIVATE_API + if (getMVKConfig().useMetalPrivateAPI && _properties.vendorID == kAMDVendorId) { + // Only AMD drivers have the method we need for now. + _features.depthBounds = true; + } +#endif + if (supportsMTLFeatureSet(macOS_GPUFamily1_v2)) { _features.tessellationShader = true; _features.dualSrcBlend = true; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm index 5717a089..34929aed 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -307,6 +307,9 @@ void MVKGraphicsPipeline::encode(MVKCommandEncoder* cmdEncoder, uint32_t stage) cmdEncoder->_renderingState.setPrimitiveTopology(_vkPrimitiveTopology, false); cmdEncoder->_renderingState.setPrimitiveRestartEnable(_primitiveRestartEnable, false); cmdEncoder->_renderingState.setBlendConstants(_blendConstants, false); + if (_device->_enabledFeatures.depthBounds) { + cmdEncoder->_renderingState.setDepthBounds(_depthStencilInfo.minDepthBounds, _depthStencilInfo.maxDepthBounds, false); + } cmdEncoder->_renderingState.setStencilReferenceValues(_depthStencilInfo); cmdEncoder->_renderingState.setViewports(_viewports.contents(), 0, false); cmdEncoder->_renderingState.setScissors(_scissors.contents(), 0, false); diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm index ad048e80..4da6afcd 100644 --- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm +++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm @@ -1498,6 +1498,7 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetDepthBounds( float maxDepthBounds) { MVKTraceVulkanCallStart(); + MVKAddCmd(SetDepthBounds, commandBuffer, minDepthBounds, maxDepthBounds); MVKTraceVulkanCallEnd(); } @@ -2653,6 +2654,7 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetDepthBoundsTestEnable( VkBool32 depthBoundsTestEnable) { MVKTraceVulkanCallStart(); + MVKAddCmd(SetDepthBoundsTestEnable, commandBuffer, depthBoundsTestEnable); MVKTraceVulkanCallEnd(); } diff --git a/README.md b/README.md index 81dd446e..b172c77b 100644 --- a/README.md +++ b/README.md @@ -329,6 +329,7 @@ included in any of the `make` command-line build commands [mentioned above](#com Functionality added with `MVK_USE_METAL_PRIVATE_API` enabled includes: - `VkPhysicalDeviceFeatures::wideLines` - `VkPhysicalDeviceFeatures::logicOp` +- `VkPhysicalDeviceFeatures::depthBounds` *(requires an AMD GPU)* - `VkPhysicalDevicePortabilitySubsetFeaturesKHR::samplerMipLodBias` - `VkGraphicsPipelineRasterizationCreateInfo::sampleMask`, using `MTLRenderPipelineDescriptor.sampleMask` instead of emulating it in the fragment shader