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);
     }