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.
diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md
index e735323..8fc20af 100644
--- a/Docs/MoltenVK_Runtime_UserGuide.md
+++ b/Docs/MoltenVK_Runtime_UserGuide.md
@@ -512,8 +512,6 @@
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).
-- `VkEvents` are not supported.
-
- Application-controlled memory allocations using `VkAllocationCallbacks` are ignored.
- Pipeline statistics query pool using `VK_QUERY_TYPE_PIPELINE_STATISTICS` is not supported.
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index 6440f77..b47e4ac 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -23,6 +23,7 @@
- Add support for `VkEvent`, using either native `MTLEvent` or emulation when `MTLEvent` not available.
- `vkInvalidateMappedMemoryRanges()` synchronizes managed device memory to CPU.
- 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.
- Fix crash when `VkDeviceCreateInfo` specifies queue families out of numerical order.
- Fix crash in `vkDestroyPipelineLayout()`.
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
index 9af8197..7fd30e8 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
@@ -62,7 +62,7 @@
* 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.
*/
- 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
@@ -237,6 +237,8 @@
*/
void setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t stencilWriteMask);
+ void beginMetalRenderPass() override;
+
/** Constructs this instance for the specified command encoder. */
MVKDepthStencilCommandEncoderState(MVKCommandEncoder* cmdEncoder)
: MVKCommandEncoderState(cmdEncoder) {}
@@ -248,7 +250,9 @@
const VkStencilOpState& vkStencil,
bool enabled);
- MVKMTLDepthStencilDescriptorData _depthStencilData;
+ MVKMTLDepthStencilDescriptorData _depthStencilData = kMVKMTLDepthStencilDescriptorDataDefault;
+ bool _hasDepthAttachment = false;
+ bool _hasStencilAttachment = false;
};
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
index 641832e..4d44d4c 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
@@ -312,26 +312,43 @@
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) {
- if (stage != kMVKGraphicsStageRasterization && stage != kMVKGraphicsStageVertex) { return; }
- MVKRenderSubpass *subpass = _cmdEncoder->getSubpass();
- id<MTLDepthStencilState> mtlDSS = nil;
- if (stage != kMVKGraphicsStageVertex && subpass->getDepthStencilFormat() != VK_FORMAT_UNDEFINED) {
- mtlDSS = _cmdEncoder->getCommandEncodingPool()->getMTLDepthStencilState(_depthStencilData);
- } else {
- // If there is no depth attachment but the depth/stencil state contains a non-always depth
- // test, Metal Validation will give the following error:
- // "validateDepthStencilState:3657: failed assertion `MTLDepthStencilDescriptor sets
- // depth test but MTLRenderPassDescriptor has a nil depthAttachment texture'"
- // Check the subpass to see if there is a depth/stencil attachment, and if not use
- // a depth/stencil state with depth test always, depth write disabled, and no stencil state.
- mtlDSS = _cmdEncoder->getCommandEncodingPool()->getMTLDepthStencilState(false, false);
- }
- [_cmdEncoder->_mtlRenderEncoder setDepthStencilState: mtlDSS];
+ auto cmdEncPool = _cmdEncoder->getCommandEncodingPool();
+ switch (stage) {
+ case kMVKGraphicsStageRasterization: {
+ // If renderpass does not have a depth or a stencil attachment, disable corresponding test
+ MVKMTLDepthStencilDescriptorData adjustedDSData = _depthStencilData;
+ adjustedDSData.disable(!_hasDepthAttachment, !_hasStencilAttachment);
+ [_cmdEncoder->_mtlRenderEncoder setDepthStencilState: cmdEncPool->getMTLDepthStencilState(adjustedDSData)];
+ break;
+ }
+ case kMVKGraphicsStageVertex: {
+ // Vertex stage of tessellation pipeline requires depth/stencil testing be disabled
+ [_cmdEncoder->_mtlRenderEncoder setDepthStencilState: cmdEncPool->getMTLDepthStencilState(false, false)];
+ break;
+ }
+ default: // Do nothing on other stages
+ break;
+ }
}
void MVKDepthStencilCommandEncoderState::resetImpl() {
_depthStencilData = kMVKMTLDepthStencilDescriptorDataDefault;
+ _hasDepthAttachment = false;
+ _hasStencilAttachment = false;
}
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h
index a14e2de..46e0fb5 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h
@@ -207,18 +207,24 @@
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;
+ }
+ }
- // Start with all zeros to ensure memory comparisons will work,
- // even if the structure contains alignment gaps.
- memset(this, 0, sizeof(*this));
-
- depthCompareFunction = MTLCompareFunctionAlways;
- depthWriteEnabled = false;
-
- frontFaceStencilData = kMVKMTLStencilDescriptorDataDefault;
- backFaceStencilData = kMVKMTLStencilDescriptorDataDefault;
- }
+ MVKMTLDepthStencilDescriptorData_t() {
+ // Start with all zeros to ensure memory comparisons will work,
+ // even if the structure contains alignment gaps.
+ memset(this, 0, sizeof(*this));
+ disable(true, true);
+ }
} __attribute__((aligned(sizeof(uint64_t)))) MVKMTLDepthStencilDescriptorData;
@@ -345,10 +351,7 @@
id<MTLRenderPipelineState> newCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey,
MVKVulkanAPIDeviceObject* owner);
- /**
- * Returns a new MTLDepthStencilState dedicated to rendering to several
- * attachments to support clearing regions of those attachments.
- */
+ /** Returns a new MTLDepthStencilState that always writes to the depth and/or stencil attachments. */
id<MTLDepthStencilState> newMTLDepthStencilState(bool useDepth, bool useStencil);
/**