Merge pull request #1375 from billhollings/begin-renderpass-fixes

Begin renderpass fixes
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index 08ded05..e13796b 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -18,6 +18,8 @@
 
 Released TBD
 
+- Add support for extensions:
+	- `VK_KHR_imageless_framebuffer`
 - Make `vkGetPastPresentationTimingGOOGLE()` queuing behavior compliant with Vulkan spec.
 - Expose `vkGetIOSurfaceMVK()` and `vkUseIOSurfaceMVK()` without requiring _Objective-C_.
 - Support _Xcode 12.5_ build settings, build warnings, and SDK change to availability of
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h
index 8a66785..cc9af1e 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h
@@ -40,7 +40,7 @@
 public:
 	VkResult setContent(MVKCommandBuffer* cmdBuff,
 						const VkRenderPassBeginInfo* pRenderPassBegin,
-						VkSubpassContents contents);
+						const VkSubpassBeginInfo* pSubpassBeginInfo);
 
 	inline MVKRenderPass* getRenderPass() { return _renderPass; }
 
@@ -66,10 +66,8 @@
 public:
 	VkResult setContent(MVKCommandBuffer* cmdBuff,
 						const VkRenderPassBeginInfo* pRenderPassBegin,
-						VkSubpassContents contents);
-	VkResult setContent(MVKCommandBuffer* cmdBuff,
-						const VkRenderPassBeginInfo* pRenderPassBegin,
-						const VkSubpassBeginInfo* pSubpassBeginInfo);
+						const VkSubpassBeginInfo* pSubpassBeginInfo,
+						MVKArrayRef<MVKImageView*> attachments);
 
 	void encode(MVKCommandEncoder* cmdEncoder) override;
 
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm
index 4fc1146..98ba2c1 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm
@@ -31,8 +31,8 @@
 
 VkResult MVKCmdBeginRenderPassBase::setContent(MVKCommandBuffer* cmdBuff,
 											   const VkRenderPassBeginInfo* pRenderPassBegin,
-											   VkSubpassContents contents) {
-	_contents = contents;
+											   const VkSubpassBeginInfo* pSubpassBeginInfo) {
+	_contents = pSubpassBeginInfo->contents;
 	_renderPass = (MVKRenderPass*)pRenderPassBegin->renderPass;
 	_framebuffer = (MVKFramebuffer*)pRenderPassBegin->framebuffer;
 	_renderArea = pRenderPassBegin->renderArea;
@@ -47,50 +47,18 @@
 template <size_t N_CV, size_t N_A>
 VkResult MVKCmdBeginRenderPass<N_CV, N_A>::setContent(MVKCommandBuffer* cmdBuff,
 													  const VkRenderPassBeginInfo* pRenderPassBegin,
-													  VkSubpassContents contents) {
-	MVKCmdBeginRenderPassBase::setContent(cmdBuff, pRenderPassBegin, contents);
+													  const VkSubpassBeginInfo* pSubpassBeginInfo,
+													  MVKArrayRef<MVKImageView*> attachments) {
+	MVKCmdBeginRenderPassBase::setContent(cmdBuff, pRenderPassBegin, pSubpassBeginInfo);
 
-	// Add clear values
-	uint32_t cvCnt = pRenderPassBegin->clearValueCount;
-	_clearValues.clear();	// Clear for reuse
-	_clearValues.reserve(cvCnt);
-	for (uint32_t i = 0; i < cvCnt; i++) {
-		_clearValues.push_back(pRenderPassBegin->pClearValues[i]);
-	}
-
-	bool imageless = false;
-	for (auto* next = (const VkBaseInStructure*)pRenderPassBegin->pNext; next; next = next->pNext) {
-		switch (next->sType) {
-		case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: {
-			const auto* pAttachmentBegin = (VkRenderPassAttachmentBeginInfo*)next;
-			for(uint32_t i = 0; i < pAttachmentBegin->attachmentCount; i++) {
-				_attachments.push_back((MVKImageView*)pAttachmentBegin->pAttachments[i]);
-			}
-			imageless = true;
-			break;
-		}
-		default:
-			break;
-		}
-	}
-	
-	if (!imageless) {
-		for(uint32_t i = 0; i < _framebuffer->getAttachmentCount(); i++) {
-			_attachments.push_back((MVKImageView*)_framebuffer->getAttachment(i));
-		}
-	}
+	_attachments.assign(attachments.begin(), attachments.end());
+	_clearValues.assign(pRenderPassBegin->pClearValues,
+						pRenderPassBegin->pClearValues + pRenderPassBegin->clearValueCount);
 
 	return VK_SUCCESS;
 }
 
 template <size_t N_CV, size_t N_A>
-VkResult MVKCmdBeginRenderPass<N_CV, N_A>::setContent(MVKCommandBuffer* cmdBuff,
-													  const VkRenderPassBeginInfo* pRenderPassBegin,
-													  const VkSubpassBeginInfo* pSubpassBeginInfo) {
-	return setContent(cmdBuff, pRenderPassBegin, pSubpassBeginInfo->contents);
-}
-
-template <size_t N_CV, size_t N_A>
 void MVKCmdBeginRenderPass<N_CV, N_A>::encode(MVKCommandEncoder* cmdEncoder) {
 //	MVKLogDebug("Encoding vkCmdBeginRenderPass(). Elapsed time: %.6f ms.", mvkGetElapsedMilliseconds());
 	cmdEncoder->beginRenderpass(this,
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h
index 32cd5dd..928da95 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h
@@ -37,15 +37,13 @@
 	VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT; }
 
 	/** Returns the dimensions of this framebuffer. */
-	inline VkExtent2D getExtent2D() { return _extent; }
+	VkExtent2D getExtent2D() { return _extent; }
 
 	/** Returns the layers covered by this framebuffer. */
-	inline uint32_t getLayerCount() { return _layerCount; }
+	uint32_t getLayerCount() { return _layerCount; }
 
-	/** Returns the attachment at the specified index.  */
-	inline MVKImageView* getAttachment(uint32_t index) { return _attachments[index]; }
-	
-	inline size_t getAttachmentCount() {return _attachments.size(); }
+	/** Returns the attachments.  */
+	MVKArrayRef<MVKImageView*> getAttachments() { return _attachments.contents(); }
 
 #pragma mark Construction
 
diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
index e595e7e..b8bf7be 100644
--- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm
+++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
@@ -1893,30 +1893,50 @@
 	MVKTraceVulkanCallEnd();
 }
 
-MVK_PUBLIC_SYMBOL void vkCmdBeginRenderPass(
-    VkCommandBuffer                             commandBuffer,
-    const VkRenderPassBeginInfo*                pRenderPassBegin,
-    VkSubpassContents							contents) {
-	
-	MVKTraceVulkanCallStart();
-	uint32_t attachmentCount = 0;
+// Consolidation function
+static void mvkCmdBeginRenderPass(
+	VkCommandBuffer								commandBuffer,
+	const VkRenderPassBeginInfo*				pRenderPassBegin,
+	const VkSubpassBeginInfo*					pSubpassBeginInfo) {
+
+	VkRenderPassAttachmentBeginInfo* pAttachmentBegin = nullptr;
 	for (const auto* next = (VkBaseInStructure*)pRenderPassBegin->pNext; next; next = next->pNext) {
 		switch(next->sType) {
 			case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: {
-				auto* pAttachmentBegin = (VkRenderPassAttachmentBeginInfo*)next;
-				attachmentCount = pAttachmentBegin->attachmentCount;
+				pAttachmentBegin = (VkRenderPassAttachmentBeginInfo*)next;
 				break;
 			}
 			default:
 				break;
 		}
 	}
+	auto attachments = (pAttachmentBegin
+						? MVKArrayRef<MVKImageView*>((MVKImageView**)pAttachmentBegin->pAttachments,
+													 pAttachmentBegin->attachmentCount)
+						: ((MVKFramebuffer*)pRenderPassBegin->framebuffer)->getAttachments());
+	
 	MVKAddCmdFrom5Thresholds(BeginRenderPass,
 							 pRenderPassBegin->clearValueCount, 1, 2,
-							 attachmentCount, 0, 1, 2,
+							 attachments.size, 0, 1, 2,
 							 commandBuffer,
 							 pRenderPassBegin,
-							 contents);
+							 pSubpassBeginInfo,
+							 attachments);
+}
+
+MVK_PUBLIC_SYMBOL void vkCmdBeginRenderPass(
+    VkCommandBuffer                             commandBuffer,
+    const VkRenderPassBeginInfo*                pRenderPassBegin,
+    VkSubpassContents							contents) {
+
+	MVKTraceVulkanCallStart();
+
+	VkSubpassBeginInfo spBeginInfo;
+	spBeginInfo.sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO;
+	spBeginInfo.pNext = nullptr;
+	spBeginInfo.contents = contents;
+
+	mvkCmdBeginRenderPass(commandBuffer, pRenderPassBegin, &spBeginInfo);
 	MVKTraceVulkanCallEnd();
 }
 
@@ -2330,24 +2350,7 @@
 	const VkSubpassBeginInfo*					pSubpassBeginInfo) {
 
 	MVKTraceVulkanCallStart();
-	uint32_t attachmentCount = 0;
-	for (const auto* next = (VkBaseInStructure*)pRenderPassBegin->pNext; next; next = next->pNext) {
-		switch(next->sType) {
-			case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: {
-				auto* pAttachmentBegin = (VkRenderPassAttachmentBeginInfo*)next;
-				attachmentCount = pAttachmentBegin->attachmentCount;
-				break;
-			}
-			default:
-				break;
-		}
-	}
-	MVKAddCmdFrom5Thresholds(BeginRenderPass,
-							 pRenderPassBegin->clearValueCount, 1, 2,
-							 attachmentCount, 0, 1, 2,
-							 commandBuffer,
-							 pRenderPassBegin,
-							 pSubpassBeginInfo);
+	mvkCmdBeginRenderPass(commandBuffer, pRenderPassBegin, pSubpassBeginInfo);
 	MVKTraceVulkanCallEnd();
 }