Merge pull request #569 from mbarriault/master

Fix tessellation pipeline re-clearing attachments.
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm
index 6e8a7b5..52f7999 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm
@@ -194,7 +194,7 @@
                                   threadsPerThreadgroup: MTLSizeMake(std::max(inControlPointCount, outControlPointCount), 1, 1)];
                 // Running this stage prematurely ended the render pass, so we have to start it up again.
                 // TODO: On iOS, maybe we could use a tile shader to avoid this.
-                cmdEncoder->beginMetalRenderPass();
+                cmdEncoder->beginMetalRenderPass(true);
                 break;
             case kMVKGraphicsStageRasterization:
                 if (pipeline->isTessellationPipeline()) {
@@ -413,7 +413,7 @@
                                   threadsPerThreadgroup: MTLSizeMake(std::max(inControlPointCount, outControlPointCount), 1, 1)];
                 // Running this stage prematurely ended the render pass, so we have to start it up again.
                 // TODO: On iOS, maybe we could use a tile shader to avoid this.
-                cmdEncoder->beginMetalRenderPass();
+                cmdEncoder->beginMetalRenderPass(true);
                 break;
             case kMVKGraphicsStageRasterization:
                 if (pipeline->isTessellationPipeline()) {
@@ -663,7 +663,7 @@
                     mtlTCIndBuffOfst += sizeof(MTLDispatchThreadgroupsIndirectArguments);
                     // Running this stage prematurely ended the render pass, so we have to start it up again.
                     // TODO: On iOS, maybe we could use a tile shader to avoid this.
-                    cmdEncoder->beginMetalRenderPass();
+                    cmdEncoder->beginMetalRenderPass(true);
                     break;
                 case kMVKGraphicsStageRasterization:
                     if (pipeline->isTessellationPipeline()) {
@@ -909,7 +909,7 @@
                     mtlTCIndBuffOfst += sizeof(MTLDispatchThreadgroupsIndirectArguments);
                     // Running this stage prematurely ended the render pass, so we have to start it up again.
                     // TODO: On iOS, maybe we could use a tile shader to avoid this.
-                    cmdEncoder->beginMetalRenderPass();
+                    cmdEncoder->beginMetalRenderPass(true);
                     break;
                 case kMVKGraphicsStageRasterization:
                     if (pipeline->isTessellationPipeline()) {
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
index 8e4a22b..09e2854 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
@@ -246,7 +246,7 @@
 	void beginNextSubpass(VkSubpassContents renderpassContents);
 
 	/** Begins a Metal render pass for the current render subpass. */
-	void beginMetalRenderPass();
+	void beginMetalRenderPass(bool loadOverride = false);
 
 	/** Returns the render subpass that is currently active. */
 	MVKRenderSubpass* getSubpass();
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
index be4477a..4aabdd2 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
@@ -242,12 +242,12 @@
 }
 
 // Creates _mtlRenderEncoder and marks cached render state as dirty so it will be set into the _mtlRenderEncoder.
-void MVKCommandEncoder::beginMetalRenderPass() {
+void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride) {
 
     endCurrentMetalEncoding();
 
     MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor];
-    getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, _framebuffer, _clearValues, _isRenderingEntireAttachment);
+    getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, _framebuffer, _clearValues, _isRenderingEntireAttachment, loadOverride);
     mtlRPDesc.visibilityResultBuffer = _occlusionQueryState.getVisibilityResultMTLBuffer();
 
 	if (_device->_pMetalFeatures->layeredRendering) {
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h
index ad591b0..769c9fa 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h
@@ -58,7 +58,8 @@
 	void populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlRPDesc,
 										 MVKFramebuffer* framebuffer,
 										 MVKVector<VkClearValue>& clearValues,
-										 bool isRenderingEntireAttachment);
+										 bool isRenderingEntireAttachment,
+                                         bool loadOverride = false);
 
 	/**
 	 * Populates the specified vector with the attachments that need to be cleared
@@ -111,7 +112,8 @@
                                                    MVKRenderSubpass* subpass,
                                                    bool isRenderingEntireAttachment,
                                                    bool hasResolveAttachment,
-                                                   bool isStencil);
+                                                   bool isStencil,
+                                                   bool loadOverride = false);
 
     /** Returns whether this attachment should be cleared in the subpass. */
     bool shouldUseClearAttachment(MVKRenderSubpass* subpass);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm
index dc21eb8..67c2980 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm
@@ -68,7 +68,8 @@
 void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlRPDesc,
 													   MVKFramebuffer* framebuffer,
 													   MVKVector<VkClearValue>& clearValues,
-													   bool isRenderingEntireAttachment) {
+													   bool isRenderingEntireAttachment,
+                                                       bool loadOverride) {
 	// Populate the Metal color attachments
 	uint32_t caCnt = getColorAttachmentCount();
 	for (uint32_t caIdx = 0; caIdx < caCnt; caIdx++) {
@@ -89,7 +90,8 @@
 			framebuffer->getAttachment(clrRPAttIdx)->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc);
 			if (clrMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc, this,
                                                                        isRenderingEntireAttachment,
-                                                                       hasResolveAttachment, false)) {
+                                                                       hasResolveAttachment, false,
+                                                                       loadOverride)) {
 				mtlColorAttDesc.clearColor = mvkMTLClearColorFromVkClearValue(clearValues[clrRPAttIdx], clrMVKRPAtt->getFormat());
 			}
 
@@ -110,8 +112,9 @@
 			dsImage->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc);
 			if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc, this,
                                                                       isRenderingEntireAttachment,
-                                                                      false, false)) {
-				mtlDepthAttDesc.clearDepth = mvkMTLClearDepthFromVkClearValue(clearValues[dsRPAttIdx]);
+                                                                      false, false,
+                                                                      loadOverride)) {
+                mtlDepthAttDesc.clearDepth = mvkMTLClearDepthFromVkClearValue(clearValues[dsRPAttIdx]);
 			}
 		}
 		if (mvkMTLPixelFormatIsStencilFormat(mtlDSFormat)) {
@@ -119,7 +122,8 @@
 			dsImage->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc);
 			if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc, this,
                                                                       isRenderingEntireAttachment,
-                                                                      false, true)) {
+                                                                      false, true,
+                                                                      loadOverride)) {
 				mtlStencilAttDesc.clearStencil = mvkMTLClearStencilFromVkClearValue(clearValues[dsRPAttIdx]);
 			}
 		}
@@ -252,13 +256,16 @@
                                                                         MVKRenderSubpass* subpass,
                                                                         bool isRenderingEntireAttachment,
                                                                         bool hasResolveAttachment,
-                                                                        bool isStencil) {
+                                                                        bool isStencil,
+                                                                        bool loadOverride) {
 
     bool willClear = false;		// Assume the attachment won't be cleared
 
     // Only allow clearing of entire attachment if we're actually rendering to the entire
     // attachment AND we're in the first subpass.
-    if ( isRenderingEntireAttachment && (subpass->_subpassIndex == _firstUseSubpassIdx) ) {
+    if ( loadOverride ) {
+        mtlAttDesc.loadAction = MTLLoadActionLoad;
+    } else if ( isRenderingEntireAttachment && (subpass->_subpassIndex == _firstUseSubpassIdx) ) {
         VkAttachmentLoadOp loadOp = isStencil ? _info.stencilLoadOp : _info.loadOp;
         mtlAttDesc.loadAction = mvkMTLLoadActionFromVkAttachmentLoadOp(loadOp);
         willClear = (_info.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);