Merge pull request #1191 from cdavis5e/apple-gpu-barriers
Don't use barriers in render passes on Apple GPUs.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h
index c66ddb3..c445b5a 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h
@@ -52,7 +52,7 @@
/** Returns whether the memory is accessible from the host. */
inline bool isMemoryHostAccessible() {
-#if MVK_IOS
+#if MVK_IOS_OR_TVOS || MVK_MACOS_APPLE_SILICON
if (_mtlStorageMode == MTLStorageModeMemoryless)
return false;
#endif
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 16771af..4f17db6 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -338,7 +338,7 @@
if (pImgRez) { pImgRez->layoutState = barrier.newLayout; }
if (needsSync) {
#if MVK_MACOS
- [cmdEncoder->getMTLBlitEncoder(cmdUse) synchronizeTexture: _mtlTexture slice: layer level: mipLvl];
+ [cmdEncoder->getMTLBlitEncoder(cmdUse) synchronizeTexture: getMTLTexture() slice: layer level: mipLvl];
#endif
}
// Check if image content should be pulled into host-mapped device memory after
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
index 7a160fa..6fb4ec1 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
@@ -1387,7 +1387,15 @@
MTLRenderPipelineColorAttachmentDescriptor* colorDesc = plDesc.colorAttachments[caIdx];
colorDesc.pixelFormat = getPixelFormats()->getMTLPixelFormat(mvkRenderSubpass->getColorAttachmentFormat(caIdx));
- colorDesc.writeMask = mvkMTLColorWriteMaskFromVkChannelFlags(pCA->colorWriteMask);
+ if (colorDesc.pixelFormat == MTLPixelFormatRGB9E5Float) {
+ // Metal doesn't allow disabling individual channels for a RGB9E5 render target.
+ // Either all must be disabled or none must be disabled.
+ // TODO: Use framebuffer fetch to support this anyway. I don't understand why Apple doesn't
+ // support it, given that the only GPUs that support this in Metal also support framebuffer fetch.
+ colorDesc.writeMask = pCA->colorWriteMask ? MTLColorWriteMaskAll : MTLColorWriteMaskNone;
+ } else {
+ colorDesc.writeMask = mvkMTLColorWriteMaskFromVkChannelFlags(pCA->colorWriteMask);
+ }
// Don't set the blend state if we're not using this attachment.
// The pixel format will be MTLPixelFormatInvalid in that case, and
// Metal asserts if we turn on blending with that pixel format.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
index 4ca6b4f..4416b7f 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
@@ -665,7 +665,7 @@
mvkIsAnyFlagEnabled(mtlFmtCaps, (kMVKMTLFmtCapsColorAtt | kMVKMTLFmtCapsDSAtt))) {
#if MVK_MACOS
- if(!isLinear) {
+ if(!isLinear || (_physicalDevice && _physicalDevice->getMetalFeatures()->renderLinearTextures)) {
mvkEnableFlags(mtlUsage, MTLTextureUsageRenderTarget);
}
#else
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h
index 7706fd3..5b48bb7 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h
@@ -175,6 +175,7 @@
bool populateMTLRenderPassAttachmentDescriptor(MTLRenderPassAttachmentDescriptor* mtlAttDesc,
MVKRenderSubpass* subpass,
bool isRenderingEntireAttachment,
+ bool isMemorylessAttachment,
bool hasResolveAttachment,
bool isStencil,
bool loadOverride = false);
@@ -183,6 +184,7 @@
void encodeStoreAction(MVKCommandEncoder* cmdEncoder,
MVKRenderSubpass* subpass,
bool isRenderingEntireAttachment,
+ bool isMemorylessAttachment,
bool hasResolveAttachment,
uint32_t caIdx,
bool isStencil,
@@ -207,6 +209,7 @@
bool isLastUseOfAttachment(MVKRenderSubpass* subpass);
MTLStoreAction getMTLStoreAction(MVKRenderSubpass* subpass,
bool isRenderingEntireAttachment,
+ bool isMemorylessAttachment,
bool hasResolveAttachment,
bool isStencil,
bool storeOverride);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm
index 84c4997..6af3d73 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm
@@ -210,8 +210,10 @@
// Configure the color attachment
MVKRenderPassAttachment* clrMVKRPAtt = &_renderPass->_attachments[clrRPAttIdx];
framebuffer->getAttachment(clrRPAttIdx)->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc);
+ bool isMemorylessAttachment = framebuffer->getAttachment(clrRPAttIdx)->getMTLTexture(0).storageMode == MTLStorageModeMemoryless;
if (clrMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc, this,
isRenderingEntireAttachment,
+ isMemorylessAttachment,
hasResolveAttachment, false,
loadOverride)) {
mtlColorAttDesc.clearColor = pixFmts->getMTLClearColor(clearValues[clrRPAttIdx], clrMVKRPAtt->getFormat());
@@ -250,8 +252,10 @@
}
}
dsImage->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc);
+ bool isMemorylessAttachment = dsImage->getMTLTexture(0).storageMode == MTLStorageModeMemoryless;
if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc, this,
isRenderingEntireAttachment,
+ isMemorylessAttachment,
hasResolveAttachment, false,
loadOverride)) {
mtlDepthAttDesc.clearDepth = pixFmts->getMTLClearDepthValue(clearValues[dsRPAttIdx]);
@@ -273,8 +277,10 @@
}
}
dsImage->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc);
+ bool isMemorylessAttachment = dsImage->getMTLTexture(0).storageMode == MTLStorageModeMemoryless;
if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc, this,
isRenderingEntireAttachment,
+ isMemorylessAttachment,
hasResolveAttachment, true,
loadOverride)) {
mtlStencilAttDesc.clearStencil = pixFmts->getMTLClearStencilValue(clearValues[dsRPAttIdx]);
@@ -360,7 +366,8 @@
uint32_t clrRPAttIdx = _colorAttachments[caIdx].attachment;
if (clrRPAttIdx != VK_ATTACHMENT_UNUSED) {
bool hasResolveAttachment = _resolveAttachments.empty() ? false : _resolveAttachments[caIdx].attachment != VK_ATTACHMENT_UNUSED;
- _renderPass->_attachments[clrRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, hasResolveAttachment, caIdx, false, storeOverride);
+ bool isMemorylessAttachment = cmdEncoder->_framebuffer->getAttachment(clrRPAttIdx)->getMTLTexture(0).storageMode == MTLStorageModeMemoryless;
+ _renderPass->_attachments[clrRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, caIdx, false, storeOverride);
}
}
uint32_t dsRPAttIdx = _depthStencilAttachment.attachment;
@@ -368,8 +375,9 @@
bool hasResolveAttachment = _depthStencilResolveAttachment.attachment != VK_ATTACHMENT_UNUSED;
bool hasDepthResolveAttachment = hasResolveAttachment && _depthResolveMode != VK_RESOLVE_MODE_NONE;
bool hasStencilResolveAttachment = hasResolveAttachment && _stencilResolveMode != VK_RESOLVE_MODE_NONE;
- _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, hasDepthResolveAttachment, 0, false, storeOverride);
- _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, hasStencilResolveAttachment, 0, true, storeOverride);
+ bool isMemorylessAttachment = cmdEncoder->_framebuffer->getAttachment(dsRPAttIdx)->getMTLTexture(0).storageMode == MTLStorageModeMemoryless;
+ _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, isMemorylessAttachment, hasDepthResolveAttachment, 0, false, storeOverride);
+ _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, isMemorylessAttachment, hasStencilResolveAttachment, 0, true, storeOverride);
}
}
@@ -573,6 +581,7 @@
bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRenderPassAttachmentDescriptor* mtlAttDesc,
MVKRenderSubpass* subpass,
bool isRenderingEntireAttachment,
+ bool isMemorylessAttachment,
bool hasResolveAttachment,
bool isStencil,
bool loadOverride) {
@@ -581,9 +590,9 @@
// Only allow clearing of entire attachment if we're actually rendering to the entire
// attachment AND we're in the first subpass.
- if ( loadOverride ) {
+ if ( loadOverride && !isMemorylessAttachment ) {
mtlAttDesc.loadAction = MTLLoadActionLoad;
- } else if ( isRenderingEntireAttachment && isFirstUseOfAttachment(subpass) ) {
+ } else if ( isMemorylessAttachment || (isRenderingEntireAttachment && isFirstUseOfAttachment(subpass)) ) {
VkAttachmentLoadOp loadOp = isStencil ? _info.stencilLoadOp : _info.loadOp;
mtlAttDesc.loadAction = mvkMTLLoadActionFromVkAttachmentLoadOp(loadOp);
willClear = (loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);
@@ -597,7 +606,7 @@
if ( _renderPass->getDevice()->_pMetalFeatures->deferredStoreActions ) {
mtlAttDesc.storeAction = MTLStoreActionUnknown;
} else {
- mtlAttDesc.storeAction = getMTLStoreAction(subpass, isRenderingEntireAttachment, hasResolveAttachment, isStencil, false);
+ mtlAttDesc.storeAction = getMTLStoreAction(subpass, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, isStencil, false);
}
return willClear;
}
@@ -605,11 +614,12 @@
void MVKRenderPassAttachment::encodeStoreAction(MVKCommandEncoder* cmdEncoder,
MVKRenderSubpass* subpass,
bool isRenderingEntireAttachment,
+ bool isMemorylessAttachment,
bool hasResolveAttachment,
uint32_t caIdx,
bool isStencil,
bool storeOverride) {
- MTLStoreAction storeAction = getMTLStoreAction(subpass, isRenderingEntireAttachment, hasResolveAttachment, isStencil, storeOverride);
+ MTLStoreAction storeAction = getMTLStoreAction(subpass, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, isStencil, storeOverride);
MVKPixelFormats* pixFmts = _renderPass->getPixelFormats();
MTLPixelFormat mtlFmt = pixFmts->getMTLPixelFormat(_info.format);
@@ -657,6 +667,7 @@
MTLStoreAction MVKRenderPassAttachment::getMTLStoreAction(MVKRenderSubpass* subpass,
bool isRenderingEntireAttachment,
+ bool isMemorylessAttachment,
bool hasResolveAttachment,
bool isStencil,
bool storeOverride) {
@@ -666,10 +677,10 @@
if (hasResolveAttachment && !_renderPass->getDevice()->_pMetalFeatures->combinedStoreResolveAction) {
return MTLStoreActionMultisampleResolve;
}
- if ( storeOverride ) {
+ if ( storeOverride && !isMemorylessAttachment ) {
return hasResolveAttachment ? MTLStoreActionStoreAndMultisampleResolve : MTLStoreActionStore;
}
- if ( isRenderingEntireAttachment && isLastUseOfAttachment(subpass) ) {
+ if ( isMemorylessAttachment || (isRenderingEntireAttachment && isLastUseOfAttachment(subpass)) ) {
VkAttachmentStoreOp storeOp = isStencil ? _info.stencilStoreOp : _info.storeOp;
return mvkMTLStoreActionFromVkAttachmentStoreOp(storeOp, hasResolveAttachment);
}