Merge pull request #1309 from billhollings/fix-memoryless-load-store

In a renderpass, don't load or store memoryless attachments.
This commit is contained in:
Bill Hollings 2021-03-11 14:11:42 -05:00 committed by GitHub
commit 20b5067ee5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 26 deletions

View File

@ -19,7 +19,9 @@ MoltenVK 1.1.3
Released TBD Released TBD
- Add support for `HDR10` colorspace via `VK_COLOR_SPACE_HDR10_HLG_EXT` and `VK_COLOR_SPACE_HDR10_ST2084_EXT`. - Add support for `HDR10` colorspace via `VK_COLOR_SPACE_HDR10_HLG_EXT` and `VK_COLOR_SPACE_HDR10_ST2084_EXT`.
- Always explicitly set `CAMetalLayer` colorspace property based on _Vulkan_ parameters, and don't rely on _Metal_ default values. - Always explicitly set `CAMetalLayer` colorspace property based on _Vulkan_ parameters,
and don't rely on _Metal_ default values.
- Avoid use of _Metal_ renderpass load and store actions on memoryless attachments.
- Remove project qualifiers from references to `SPIRV-Cross` header files. - Remove project qualifiers from references to `SPIRV-Cross` header files.
- Add `MVKConfiguration::apiVersionToAdvertise` and `MVK_CONFIG_API_VERSION_TO_ADVERTISE` - Add `MVKConfiguration::apiVersionToAdvertise` and `MVK_CONFIG_API_VERSION_TO_ADVERTISE`
env var to configure **MoltenVK** to advertise a particular _Vulkan_ version. env var to configure **MoltenVK** to advertise a particular _Vulkan_ version.

View File

@ -600,21 +600,21 @@ bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRende
bool hasResolveAttachment, bool hasResolveAttachment,
bool isStencil, bool isStencil,
bool loadOverride) { bool loadOverride) {
// Only allow clearing of entire attachment if we're actually
bool willClear = false; // Assume the attachment won't be cleared // rendering to the entire attachment AND we're in the first subpass.
MTLLoadAction mtlLA;
// Only allow clearing of entire attachment if we're actually rendering to the entire if (loadOverride || !isRenderingEntireAttachment || !isFirstUseOfAttachment(subpass)) {
// attachment AND we're in the first subpass. mtlLA = MTLLoadActionLoad;
if ( loadOverride && !isMemorylessAttachment ) {
mtlAttDesc.loadAction = MTLLoadActionLoad;
} else if ( isMemorylessAttachment || (isRenderingEntireAttachment && isFirstUseOfAttachment(subpass)) ) {
VkAttachmentLoadOp loadOp = isStencil ? _info.stencilLoadOp : _info.loadOp;
mtlAttDesc.loadAction = mvkMTLLoadActionFromVkAttachmentLoadOp(loadOp);
willClear = (loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);
} else { } else {
mtlAttDesc.loadAction = MTLLoadActionLoad; VkAttachmentLoadOp loadOp = isStencil ? _info.stencilLoadOp : _info.loadOp;
mtlLA = mvkMTLLoadActionFromVkAttachmentLoadOp(loadOp);
} }
// Memoryless can be cleared, but can't be loaded, so force load to don't care.
if (isMemorylessAttachment && mtlLA == MTLLoadActionLoad) { mtlLA = MTLLoadActionDontCare; }
mtlAttDesc.loadAction = mtlLA;
// If the device supports late-specified store actions, we'll use those, and then set them later. // If the device supports late-specified store actions, we'll use those, and then set them later.
// That way, if we wind up doing a tessellated draw, we can set the store action to store then, // That way, if we wind up doing a tessellated draw, we can set the store action to store then,
// and then when the render pass actually ends, we can use the true store action. // and then when the render pass actually ends, we can use the true store action.
@ -623,7 +623,7 @@ bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRende
} else { } else {
mtlAttDesc.storeAction = getMTLStoreAction(subpass, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, isStencil, false); mtlAttDesc.storeAction = getMTLStoreAction(subpass, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, isStencil, false);
} }
return willClear; return (mtlLA == MTLLoadActionClear);
} }
void MVKRenderPassAttachment::encodeStoreAction(MVKCommandEncoder* cmdEncoder, void MVKRenderPassAttachment::encodeStoreAction(MVKCommandEncoder* cmdEncoder,
@ -687,19 +687,21 @@ MTLStoreAction MVKRenderPassAttachment::getMTLStoreAction(MVKRenderSubpass* subp
bool isStencil, bool isStencil,
bool storeOverride) { bool storeOverride) {
// If a resolve attachment exists, this attachment must resolve once complete. // If a resolve attachment exists, this attachment must resolve once complete.
// Otherwise only allow the attachment to be discarded if we're actually rendering
// to the entire attachment and we're in the last subpass.
if (hasResolveAttachment && !_renderPass->getDevice()->_pMetalFeatures->combinedStoreResolveAction) { if (hasResolveAttachment && !_renderPass->getDevice()->_pMetalFeatures->combinedStoreResolveAction) {
return MTLStoreActionMultisampleResolve; return MTLStoreActionMultisampleResolve;
} }
if ( storeOverride && !isMemorylessAttachment ) { // Memoryless can't be stored.
return hasResolveAttachment ? MTLStoreActionStoreAndMultisampleResolve : MTLStoreActionStore; if (isMemorylessAttachment) {
} return hasResolveAttachment ? MTLStoreActionMultisampleResolve : MTLStoreActionDontCare;
if ( isMemorylessAttachment || (isRenderingEntireAttachment && isLastUseOfAttachment(subpass)) ) { }
VkAttachmentStoreOp storeOp = isStencil ? _info.stencilStoreOp : _info.storeOp;
return mvkMTLStoreActionFromVkAttachmentStoreOp(storeOp, hasResolveAttachment); // Only allow the attachment to be discarded if we're actually
} // rendering to the entire attachment and we're in the last subpass.
return hasResolveAttachment ? MTLStoreActionStoreAndMultisampleResolve : MTLStoreActionStore; if (storeOverride || !isRenderingEntireAttachment || !isLastUseOfAttachment(subpass)) {
return hasResolveAttachment ? MTLStoreActionStoreAndMultisampleResolve : MTLStoreActionStore;
}
VkAttachmentStoreOp storeOp = isStencil ? _info.stencilStoreOp : _info.storeOp;
return mvkMTLStoreActionFromVkAttachmentStoreOp(storeOp, hasResolveAttachment);
} }
bool MVKRenderPassAttachment::shouldUseClearAttachment(MVKRenderSubpass* subpass) { bool MVKRenderPassAttachment::shouldUseClearAttachment(MVKRenderSubpass* subpass) {

View File

@ -734,10 +734,9 @@ MVK_PUBLIC_SYMBOL MTLBarrierScope mvkMTLBarrierScopeFromVkAccessFlags(VkAccessFl
MVK_PUBLIC_SYMBOL MTLStorageMode mvkMTLStorageModeFromVkMemoryPropertyFlags(VkMemoryPropertyFlags vkFlags) { MVK_PUBLIC_SYMBOL MTLStorageMode mvkMTLStorageModeFromVkMemoryPropertyFlags(VkMemoryPropertyFlags vkFlags) {
// If not visible to the host: Private // If not visible to the host, use Private, or Memoryless if available and lazily allocated.
if ( !mvkAreAllFlagsEnabled(vkFlags, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ) { if ( !mvkAreAllFlagsEnabled(vkFlags, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ) {
#if MVK_APPLE_SILICON #if MVK_APPLE_SILICON
// iOS: If lazily allocated, Memoryless
if (mvkAreAllFlagsEnabled(vkFlags, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)) { if (mvkAreAllFlagsEnabled(vkFlags, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)) {
return MTLStorageModeMemoryless; return MTLStorageModeMemoryless;
} }