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.
This commit is contained in:
Chip Davis 2020-10-19 03:55:20 -05:00 committed by Chip Davis
parent f8b974371b
commit 60a429f353
10 changed files with 117 additions and 0 deletions

View File

@ -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.

View File

@ -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<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
float _minDepthBounds;
float _maxDepthBounds;
};
#pragma mark -
#pragma mark MVKCmdSetDepthBoundsTestEnable
/** Vulkan command to enable depth bounds testing. */
class MVKCmdSetDepthBoundsTestEnable : public MVKSingleValueCommand<VkBool32> {
public:
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
};
#pragma mark -
#pragma mark MVKCmdSetStencilTestEnable

View File

@ -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

View File

@ -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] = {};
};

View File

@ -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<bool>(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 <MTLRenderCommandEncoder>
-(void) setLineWidth: (float) width;
@end
// An extension of the MTLRenderCommandEncoder protocol containing a declaration of the
// -setDepthBoundsTestAMD:minDepth:maxDepth: method.
@protocol MVKMTLRenderCommandEncoderDepthBoundsAMD <MTLRenderCommandEncoder>
- (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<MVKMTLRenderCommandEncoderDepthBoundsAMD>)_cmdEncoder->_mtlRenderEncoder setDepthBoundsTestAMD: YES
minDepth: db.minDepthBound
maxDepth: db.maxDepthBound];
} else {
[(id<MVKMTLRenderCommandEncoderDepthBoundsAMD>)_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];

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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();
}

View File

@ -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