Disable depth and/or stencil testing if corresponding attachment is missing.

MVKDepthStencilCommandEncoderState track whether depth and
stencil attachements exist, and modify testing accordingly.
Add MVKMTLDepthStencilDescriptorData::disable() function.
MoltenVK_Runtime_UserGuide.md remove VkEvent as known limitation.
This commit is contained in:
Bill Hollings 2019-08-15 13:39:34 -04:00
parent e2ce1a6329
commit 25acafdb3f
5 changed files with 57 additions and 34 deletions

View File

@ -512,8 +512,6 @@ This section documents the known limitations in this version of **MoltenVK**.
In order to use Vulkan layers such as the validation layers, use the Vulkan loader and layers from the In order to use Vulkan layers such as the validation layers, use the Vulkan loader and layers from the
[LunarG Vulkan SDK](https://vulkan.lunarg.com). [LunarG Vulkan SDK](https://vulkan.lunarg.com).
- `VkEvents` are not supported.
- Application-controlled memory allocations using `VkAllocationCallbacks` are ignored. - Application-controlled memory allocations using `VkAllocationCallbacks` are ignored.
- Pipeline statistics query pool using `VK_QUERY_TYPE_PIPELINE_STATISTICS` is not supported. - Pipeline statistics query pool using `VK_QUERY_TYPE_PIPELINE_STATISTICS` is not supported.

View File

@ -23,6 +23,7 @@ Released TBD
- Add support for `VkEvent`, using either native `MTLEvent` or emulation when `MTLEvent` not available. - Add support for `VkEvent`, using either native `MTLEvent` or emulation when `MTLEvent` not available.
- `vkInvalidateMappedMemoryRanges()` synchronizes managed device memory to CPU. - `vkInvalidateMappedMemoryRanges()` synchronizes managed device memory to CPU.
- Revert to supporting host-coherent memory for linear images on macOS. - Revert to supporting host-coherent memory for linear images on macOS.
- Disable depth and/or stencil testing if corresponding attachment is missing.
- Ensure Vulkan loader magic number is set every time before returning any dispatchable Vulkan handle. - Ensure Vulkan loader magic number is set every time before returning any dispatchable Vulkan handle.
- Fix crash when `VkDeviceCreateInfo` specifies queue families out of numerical order. - Fix crash when `VkDeviceCreateInfo` specifies queue families out of numerical order.
- Fix crash in `vkDestroyPipelineLayout()`. - Fix crash in `vkDestroyPipelineLayout()`.

View File

@ -62,7 +62,7 @@ public:
* will be encoded to Metal, otherwise it is marked as clean, so the contents will NOT * will be encoded to Metal, otherwise it is marked as clean, so the contents will NOT
* be encoded. Default state can be left unencoded on a new Metal encoder. * be encoded. Default state can be left unencoded on a new Metal encoder.
*/ */
void beginMetalRenderPass() { if (_isModified) { markDirty(); } } virtual void beginMetalRenderPass() { if (_isModified) { markDirty(); } }
/** /**
* If the content of this instance is dirty, marks this instance as no longer dirty * If the content of this instance is dirty, marks this instance as no longer dirty
@ -237,6 +237,8 @@ public:
*/ */
void setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t stencilWriteMask); void setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t stencilWriteMask);
void beginMetalRenderPass() override;
/** Constructs this instance for the specified command encoder. */ /** Constructs this instance for the specified command encoder. */
MVKDepthStencilCommandEncoderState(MVKCommandEncoder* cmdEncoder) MVKDepthStencilCommandEncoderState(MVKCommandEncoder* cmdEncoder)
: MVKCommandEncoderState(cmdEncoder) {} : MVKCommandEncoderState(cmdEncoder) {}
@ -248,7 +250,9 @@ protected:
const VkStencilOpState& vkStencil, const VkStencilOpState& vkStencil,
bool enabled); bool enabled);
MVKMTLDepthStencilDescriptorData _depthStencilData; MVKMTLDepthStencilDescriptorData _depthStencilData = kMVKMTLDepthStencilDescriptorDataDefault;
bool _hasDepthAttachment = false;
bool _hasStencilAttachment = false;
}; };

View File

@ -312,26 +312,43 @@ void MVKDepthStencilCommandEncoderState::setStencilWriteMask(VkStencilFaceFlags
markDirty(); markDirty();
} }
void MVKDepthStencilCommandEncoderState::beginMetalRenderPass() {
MVKRenderSubpass* mvkSubpass = _cmdEncoder->getSubpass();
MTLPixelFormat mtlDSFormat = _cmdEncoder->getMTLPixelFormatFromVkFormat(mvkSubpass->getDepthStencilFormat());
bool prevHasDepthAttachment = _hasDepthAttachment;
_hasDepthAttachment = mvkMTLPixelFormatIsDepthFormat(mtlDSFormat);
if (_hasDepthAttachment != prevHasDepthAttachment) { markDirty(); }
bool prevHasStencilAttachment = _hasStencilAttachment;
_hasStencilAttachment = mvkMTLPixelFormatIsStencilFormat(mtlDSFormat);
if (_hasStencilAttachment != prevHasStencilAttachment) { markDirty(); }
}
void MVKDepthStencilCommandEncoderState::encodeImpl(uint32_t stage) { void MVKDepthStencilCommandEncoderState::encodeImpl(uint32_t stage) {
if (stage != kMVKGraphicsStageRasterization && stage != kMVKGraphicsStageVertex) { return; } auto cmdEncPool = _cmdEncoder->getCommandEncodingPool();
MVKRenderSubpass *subpass = _cmdEncoder->getSubpass(); switch (stage) {
id<MTLDepthStencilState> mtlDSS = nil; case kMVKGraphicsStageRasterization: {
if (stage != kMVKGraphicsStageVertex && subpass->getDepthStencilFormat() != VK_FORMAT_UNDEFINED) { // If renderpass does not have a depth or a stencil attachment, disable corresponding test
mtlDSS = _cmdEncoder->getCommandEncodingPool()->getMTLDepthStencilState(_depthStencilData); MVKMTLDepthStencilDescriptorData adjustedDSData = _depthStencilData;
} else { adjustedDSData.disable(!_hasDepthAttachment, !_hasStencilAttachment);
// If there is no depth attachment but the depth/stencil state contains a non-always depth [_cmdEncoder->_mtlRenderEncoder setDepthStencilState: cmdEncPool->getMTLDepthStencilState(adjustedDSData)];
// test, Metal Validation will give the following error: break;
// "validateDepthStencilState:3657: failed assertion `MTLDepthStencilDescriptor sets }
// depth test but MTLRenderPassDescriptor has a nil depthAttachment texture'" case kMVKGraphicsStageVertex: {
// Check the subpass to see if there is a depth/stencil attachment, and if not use // Vertex stage of tessellation pipeline requires depth/stencil testing be disabled
// a depth/stencil state with depth test always, depth write disabled, and no stencil state. [_cmdEncoder->_mtlRenderEncoder setDepthStencilState: cmdEncPool->getMTLDepthStencilState(false, false)];
mtlDSS = _cmdEncoder->getCommandEncodingPool()->getMTLDepthStencilState(false, false); break;
}
default: // Do nothing on other stages
break;
} }
[_cmdEncoder->_mtlRenderEncoder setDepthStencilState: mtlDSS];
} }
void MVKDepthStencilCommandEncoderState::resetImpl() { void MVKDepthStencilCommandEncoderState::resetImpl() {
_depthStencilData = kMVKMTLDepthStencilDescriptorDataDefault; _depthStencilData = kMVKMTLDepthStencilDescriptorDataDefault;
_hasDepthAttachment = false;
_hasStencilAttachment = false;
} }

View File

@ -207,17 +207,23 @@ typedef struct MVKMTLDepthStencilDescriptorData_t {
return mvkHash((uint64_t*)this, sizeof(*this) / sizeof(uint64_t)); return mvkHash((uint64_t*)this, sizeof(*this) / sizeof(uint64_t));
} }
MVKMTLDepthStencilDescriptorData_t() { /** Disable depth and/or stencil testing. */
void disable(bool disableDepth, bool disableStencil) {
if (disableDepth) {
depthCompareFunction = MTLCompareFunctionAlways;
depthWriteEnabled = false;
}
if (disableStencil) {
frontFaceStencilData = kMVKMTLStencilDescriptorDataDefault;
backFaceStencilData = kMVKMTLStencilDescriptorDataDefault;
}
}
MVKMTLDepthStencilDescriptorData_t() {
// Start with all zeros to ensure memory comparisons will work, // Start with all zeros to ensure memory comparisons will work,
// even if the structure contains alignment gaps. // even if the structure contains alignment gaps.
memset(this, 0, sizeof(*this)); memset(this, 0, sizeof(*this));
disable(true, true);
depthCompareFunction = MTLCompareFunctionAlways;
depthWriteEnabled = false;
frontFaceStencilData = kMVKMTLStencilDescriptorDataDefault;
backFaceStencilData = kMVKMTLStencilDescriptorDataDefault;
} }
} __attribute__((aligned(sizeof(uint64_t)))) MVKMTLDepthStencilDescriptorData; } __attribute__((aligned(sizeof(uint64_t)))) MVKMTLDepthStencilDescriptorData;
@ -345,10 +351,7 @@ public:
id<MTLRenderPipelineState> newCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey, id<MTLRenderPipelineState> newCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey,
MVKVulkanAPIDeviceObject* owner); MVKVulkanAPIDeviceObject* owner);
/** /** Returns a new MTLDepthStencilState that always writes to the depth and/or stencil attachments. */
* Returns a new MTLDepthStencilState dedicated to rendering to several
* attachments to support clearing regions of those attachments.
*/
id<MTLDepthStencilState> newMTLDepthStencilState(bool useDepth, bool useStencil); id<MTLDepthStencilState> newMTLDepthStencilState(bool useDepth, bool useStencil);
/** /**