Don't attempt to store the depth component of a stencil-only renderpass attachment.

For a combined depth-stencil format in a MVKImageView attachment with
VK_IMAGE_ASPECT_STENCIL_BIT, the attachment format may have been swizzled
to a stencil-only format. In this case, we want to guard against an attempt
to store the non-existent depth component.

Pass MVKImageView attachment to MVKRenderPassAttachment::encodeStoreAction()
and MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor() to
check attachment depth format component.

Consolidate calls to MVKImageView::populateMTLRenderPassAttachmentDescriptor() by calling
it from within MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor().
This commit is contained in:
Bill Hollings 2022-02-24 11:42:12 -05:00
parent a6f5841b91
commit e42b33e593
3 changed files with 47 additions and 43 deletions

View File

@ -19,7 +19,8 @@ MoltenVK 1.1.9
Released TBD
- Update *glslang* version, to use `python3` in *glslang* scripts, to replace missing `python` on *macOS 12.3*.
- Fix alignment between outputs and inputs between shader stages when using nested structures.
- Fix alignment between outputs and inputs between shader stages when using nested structures.
- Fix issue where the depth component of a stencil-only renderpass attachment was incorrectly attempting to be stored.

View File

@ -190,8 +190,8 @@ public:
*/
bool populateMTLRenderPassAttachmentDescriptor(MTLRenderPassAttachmentDescriptor* mtlAttDesc,
MVKRenderSubpass* subpass,
MVKImageView* attachment,
bool isRenderingEntireAttachment,
bool isMemorylessAttachment,
bool hasResolveAttachment,
bool canResolveFormat,
bool isStencil,
@ -200,8 +200,8 @@ public:
/** If a render encoder is active, sets the store action for this attachment to it. */
void encodeStoreAction(MVKCommandEncoder* cmdEncoder,
MVKRenderSubpass* subpass,
MVKImageView* attachment,
bool isRenderingEntireAttachment,
bool isMemorylessAttachment,
bool hasResolveAttachment,
bool canResolveFormat,
uint32_t caIdx,

View File

@ -237,13 +237,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
// Configure the color attachment
MVKRenderPassAttachment* clrMVKRPAtt = &_renderPass->_attachments[clrRPAttIdx];
attachments[clrRPAttIdx]->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc);
bool isMemorylessAttachment = false;
#if MVK_APPLE_SILICON
isMemorylessAttachment = attachments[clrRPAttIdx]->getMTLTexture(0).storageMode == MTLStorageModeMemoryless;
#endif
if (clrMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc, this,
isRenderingEntireAttachment, isMemorylessAttachment,
if (clrMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc, this, attachments[clrRPAttIdx],
isRenderingEntireAttachment,
hasResolveAttachment, canResolveFormat,
false, loadOverride)) {
mtlColorAttDesc.clearColor = pixFmts->getMTLClearColor(clearValues[clrRPAttIdx], clrMVKRPAtt->getFormat());
@ -281,13 +276,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
mtlDepthAttDesc.resolveSlice += getFirstViewIndexInMetalPass(passIdx);
}
}
dsImage->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc);
bool isMemorylessAttachment = false;
#if MVK_APPLE_SILICON
isMemorylessAttachment = dsImage->getMTLTexture(0).storageMode == MTLStorageModeMemoryless;
#endif
if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc, this,
isRenderingEntireAttachment, isMemorylessAttachment,
if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc, this, dsImage,
isRenderingEntireAttachment,
hasResolveAttachment, true,
false, loadOverride)) {
mtlDepthAttDesc.clearDepth = pixFmts->getMTLClearDepthValue(clearValues[dsRPAttIdx]);
@ -308,13 +298,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
mtlStencilAttDesc.resolveSlice += getFirstViewIndexInMetalPass(passIdx);
}
}
dsImage->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc);
bool isMemorylessAttachment = false;
#if MVK_APPLE_SILICON
isMemorylessAttachment = dsImage->getMTLTexture(0).storageMode == MTLStorageModeMemoryless;
#endif
if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc, this,
isRenderingEntireAttachment, isMemorylessAttachment,
if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc, this, dsImage,
isRenderingEntireAttachment,
hasResolveAttachment, true,
true, loadOverride)) {
mtlStencilAttDesc.clearStencil = pixFmts->getMTLClearStencilValue(clearValues[dsRPAttIdx]);
@ -359,11 +344,7 @@ void MVKRenderSubpass::encodeStoreActions(MVKCommandEncoder* cmdEncoder,
uint32_t rslvRPAttIdx = _resolveAttachments.empty() ? VK_ATTACHMENT_UNUSED : _resolveAttachments[caIdx].attachment;
bool hasResolveAttachment = (rslvRPAttIdx != VK_ATTACHMENT_UNUSED);
bool canResolveFormat = hasResolveAttachment && mvkAreAllFlagsEnabled(pixFmts->getCapabilities(attachments[rslvRPAttIdx]->getMTLPixelFormat()), kMVKMTLFmtCapsResolve);
bool isMemorylessAttachment = false;
#if MVK_APPLE_SILICON
isMemorylessAttachment = attachments[clrRPAttIdx]->getMTLTexture(0).storageMode == MTLStorageModeMemoryless;
#endif
_renderPass->_attachments[clrRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, canResolveFormat, caIdx, false, storeOverride);
_renderPass->_attachments[clrRPAttIdx].encodeStoreAction(cmdEncoder, this, attachments[clrRPAttIdx], isRenderingEntireAttachment, hasResolveAttachment, canResolveFormat, caIdx, false, storeOverride);
}
}
uint32_t dsRPAttIdx = _depthStencilAttachment.attachment;
@ -372,12 +353,8 @@ void MVKRenderSubpass::encodeStoreActions(MVKCommandEncoder* cmdEncoder,
bool hasDepthResolveAttachment = hasResolveAttachment && _depthResolveMode != VK_RESOLVE_MODE_NONE;
bool hasStencilResolveAttachment = hasResolveAttachment && _stencilResolveMode != VK_RESOLVE_MODE_NONE;
bool canResolveFormat = true;
bool isMemorylessAttachment = false;
#if MVK_APPLE_SILICON
isMemorylessAttachment = attachments[dsRPAttIdx]->getMTLTexture(0).storageMode == MTLStorageModeMemoryless;
#endif
_renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, isMemorylessAttachment, hasDepthResolveAttachment, canResolveFormat, 0, false, storeOverride);
_renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, isMemorylessAttachment, hasStencilResolveAttachment, canResolveFormat, 0, true, storeOverride);
_renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, attachments[dsRPAttIdx], isRenderingEntireAttachment, hasDepthResolveAttachment, canResolveFormat, 0, false, storeOverride);
_renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, attachments[dsRPAttIdx], isRenderingEntireAttachment, hasStencilResolveAttachment, canResolveFormat, 0, true, storeOverride);
}
}
@ -610,13 +587,21 @@ VkSampleCountFlagBits MVKRenderPassAttachment::getSampleCount() { return _info.s
bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRenderPassAttachmentDescriptor* mtlAttDesc,
MVKRenderSubpass* subpass,
MVKImageView* attachment,
bool isRenderingEntireAttachment,
bool isMemorylessAttachment,
bool hasResolveAttachment,
bool canResolveFormat,
bool isStencil,
bool loadOverride) {
// Only allow clearing of entire attachment if we're actually
// Populate from the attachment image view
attachment->populateMTLRenderPassAttachmentDescriptor(mtlAttDesc);
bool isMemorylessAttachment = false;
#if MVK_APPLE_SILICON
isMemorylessAttachment = attachment->getMTLTexture().storageMode == MTLStorageModeMemoryless;
#endif
// Only allow clearing of entire attachment if we're actually
// rendering to the entire attachment AND we're in the first subpass.
MTLLoadAction mtlLA;
if (loadOverride || !isRenderingEntireAttachment || !isFirstUseOfAttachment(subpass)) {
@ -637,28 +622,46 @@ bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRende
if ( _renderPass->getDevice()->_pMetalFeatures->deferredStoreActions ) {
mtlAttDesc.storeAction = MTLStoreActionUnknown;
} else {
mtlAttDesc.storeAction = getMTLStoreAction(subpass, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, canResolveFormat, isStencil, false);
// For a combined depth-stencil format in an attachment with VK_IMAGE_ASPECT_STENCIL_BIT,
// the attachment format may have been swizzled to a stencil-only format. In this case,
// we want to guard against an attempt to store the non-existent depth component.
MTLPixelFormat mtlFmt = attachment->getMTLPixelFormat();
MVKPixelFormats* pixFmts = _renderPass->getPixelFormats();
bool isDepthFormat = pixFmts->isDepthFormat(mtlFmt);
bool isStencilFormat = pixFmts->isStencilFormat(mtlFmt);
if (isStencilFormat && !isStencil && !isDepthFormat) {
mtlAttDesc.storeAction = MTLStoreActionDontCare;
} else {
mtlAttDesc.storeAction = getMTLStoreAction(subpass, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, canResolveFormat, isStencil, false);
}
}
return (mtlLA == MTLLoadActionClear);
}
void MVKRenderPassAttachment::encodeStoreAction(MVKCommandEncoder* cmdEncoder,
MVKRenderSubpass* subpass,
MVKImageView* attachment,
bool isRenderingEntireAttachment,
bool isMemorylessAttachment,
bool hasResolveAttachment,
bool canResolveFormat,
uint32_t caIdx,
bool isStencil,
bool storeOverride) {
MTLStoreAction storeAction = getMTLStoreAction(subpass, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, canResolveFormat, isStencil, storeOverride);
MVKPixelFormats* pixFmts = _renderPass->getPixelFormats();
MTLPixelFormat mtlFmt = pixFmts->getMTLPixelFormat(_info.format);
// For a combined depth-stencil format in an attachment with VK_IMAGE_ASPECT_STENCIL_BIT,
// the attachment format may have been swizzled to a stencil-only format. In this case,
// we want to guard against an attempt to store the non-existent depth component.
MTLPixelFormat mtlFmt = attachment->getMTLPixelFormat();
MVKPixelFormats* pixFmts = _renderPass->getPixelFormats();
bool isDepthFormat = pixFmts->isDepthFormat(mtlFmt);
bool isStencilFormat = pixFmts->isStencilFormat(mtlFmt);
bool isColorFormat = !(isDepthFormat || isStencilFormat);
bool isMemorylessAttachment = false;
#if MVK_APPLE_SILICON
isMemorylessAttachment = attachment->getMTLTexture().storageMode == MTLStorageModeMemoryless;
#endif
MTLStoreAction storeAction = getMTLStoreAction(subpass, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, canResolveFormat, isStencil, storeOverride);
if (isColorFormat) {
[cmdEncoder->_mtlRenderEncoder setColorStoreAction: storeAction atIndex: caIdx];
} else if (isDepthFormat && !isStencil) {