Basic RenderPass implementation

RenderPass information is required for RenderPass related commands,
like clearing attachments. This cl adds storage for attachments,
subpasses and dependencies related information in the RenderPass
objects and stores all this information in new class members.

Bug b/119620965

Change-Id: I19d8b8465c807755881de6471700a119082575f8
Reviewed-on: https://swiftshader-review.googlesource.com/c/23788
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Vulkan/VkRenderPass.cpp b/src/Vulkan/VkRenderPass.cpp
index 0b60e0c..f34b1e9 100644
--- a/src/Vulkan/VkRenderPass.cpp
+++ b/src/Vulkan/VkRenderPass.cpp
@@ -13,31 +13,140 @@
 // limitations under the License.
 
 #include "VkRenderPass.hpp"
+#include <cstring>
 
 namespace vk
 {
 
-RenderPass::RenderPass(const VkRenderPassCreateInfo* pCreateInfo, void* mem)
+RenderPass::RenderPass(const VkRenderPassCreateInfo* pCreateInfo, void* mem) :
+	attachmentCount(pCreateInfo->attachmentCount),
+	subpassCount(pCreateInfo->subpassCount),
+	dependencyCount(pCreateInfo->dependencyCount)
 {
+	char* hostMemory = reinterpret_cast<char*>(mem);
+
+	// subpassCount must be greater than 0
+	ASSERT(pCreateInfo->subpassCount > 0);
+
+	size_t subpassesSize = pCreateInfo->subpassCount * sizeof(VkSubpassDescription);
+	subpasses = reinterpret_cast<VkSubpassDescription*>(hostMemory);
+	memcpy(subpasses, pCreateInfo->pSubpasses, subpassesSize);
+	hostMemory += subpassesSize;
+
+	if(pCreateInfo->attachmentCount > 0)
+	{
+		size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription);
+		attachments = reinterpret_cast<VkAttachmentDescription*>(hostMemory);
+		memcpy(attachments, pCreateInfo->pAttachments, attachmentSize);
+		hostMemory += attachmentSize;
+	}
+
+	// Deep copy subpasses
+	for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
+	{
+		const auto& subpass = pCreateInfo->pSubpasses[i];
+		subpasses[i].pInputAttachments = nullptr;
+		subpasses[i].pColorAttachments = nullptr;
+		subpasses[i].pResolveAttachments = nullptr;
+		subpasses[i].pDepthStencilAttachment = nullptr;
+		subpasses[i].pPreserveAttachments = nullptr;
+
+		if(subpass.inputAttachmentCount > 0)
+		{
+			size_t inputAttachmentsSize = subpass.inputAttachmentCount * sizeof(VkAttachmentReference);
+			subpasses[i].pInputAttachments = reinterpret_cast<VkAttachmentReference*>(hostMemory);
+			memcpy(const_cast<VkAttachmentReference*>(subpasses[i].pInputAttachments),
+			       pCreateInfo->pSubpasses[i].pInputAttachments, inputAttachmentsSize);
+			hostMemory += inputAttachmentsSize;
+		}
+
+		if(subpass.colorAttachmentCount > 0)
+		{
+			size_t colorAttachmentsSize = subpass.colorAttachmentCount * sizeof(VkAttachmentReference);
+			subpasses[i].pColorAttachments = reinterpret_cast<VkAttachmentReference*>(hostMemory);
+			memcpy(const_cast<VkAttachmentReference*>(subpasses[i].pColorAttachments),
+			       pCreateInfo->pSubpasses[i].pColorAttachments, colorAttachmentsSize);
+			hostMemory += colorAttachmentsSize;
+
+			if(subpass.pResolveAttachments != nullptr)
+			{
+				subpasses[i].pResolveAttachments = reinterpret_cast<VkAttachmentReference*>(hostMemory);
+				memcpy(const_cast<VkAttachmentReference*>(subpasses[i].pResolveAttachments),
+				       pCreateInfo->pSubpasses[i].pResolveAttachments, colorAttachmentsSize);
+				hostMemory += colorAttachmentsSize;
+			}
+		}
+
+		if(subpass.pDepthStencilAttachment != nullptr)
+		{
+			subpasses[i].pDepthStencilAttachment = reinterpret_cast<VkAttachmentReference*>(hostMemory);
+			memcpy(const_cast<VkAttachmentReference*>(subpasses[i].pDepthStencilAttachment),
+				pCreateInfo->pSubpasses[i].pDepthStencilAttachment, sizeof(VkAttachmentReference));
+			hostMemory += sizeof(VkAttachmentReference);
+		}
+
+		if(subpass.preserveAttachmentCount > 0)
+		{
+			size_t preserveAttachmentSize = subpass.preserveAttachmentCount * sizeof(uint32_t);
+			subpasses[i].pPreserveAttachments = reinterpret_cast<uint32_t*>(hostMemory);
+			memcpy(const_cast<uint32_t*>(subpasses[i].pPreserveAttachments),
+			       pCreateInfo->pSubpasses[i].pPreserveAttachments, preserveAttachmentSize);
+			hostMemory += preserveAttachmentSize;
+		}
+	}
+
+	if(pCreateInfo->dependencyCount > 0)
+	{
+		size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency);
+		dependencies = reinterpret_cast<VkSubpassDependency*>(hostMemory);
+		memcpy(dependencies, pCreateInfo->pDependencies, dependenciesSize);
+	}
 }
 
 void RenderPass::destroy(const VkAllocationCallbacks* pAllocator)
 {
+	vk::deallocate(subpasses, pAllocator); // attachments and dependencies are in the same allocation
 }
 
 size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo* pCreateInfo)
 {
-	return 0;
+	size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription);
+	size_t subpassesSize = 0;
+	for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
+	{
+		const auto& subpass = pCreateInfo->pSubpasses[i];
+		uint32_t nbAttachments = subpass.inputAttachmentCount + subpass.colorAttachmentCount;
+		if(subpass.pResolveAttachments != nullptr)
+		{
+			nbAttachments += subpass.colorAttachmentCount;
+		}
+		if(subpass.pDepthStencilAttachment != nullptr)
+		{
+			nbAttachments += 1;
+		}
+		subpassesSize += sizeof(VkSubpassDescription) +
+		                 sizeof(VkAttachmentReference) * nbAttachments +
+		                 sizeof(uint32_t) * subpass.preserveAttachmentCount;
+	}
+	size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency);
+
+	return attachmentSize + subpassesSize + dependenciesSize;
 }
 
 void RenderPass::begin()
 {
-	// FIXME (b/119620965): noop
+	currentSubpass = 0;
+}
+
+void RenderPass::nextSubpass()
+{
+	++currentSubpass;
+	ASSERT(currentSubpass < subpassCount);
 }
 
 void RenderPass::end()
 {
-	// FIXME (b/119620965): noop
+	currentSubpass = 0;
 }
 
 } // namespace vk
\ No newline at end of file
diff --git a/src/Vulkan/VkRenderPass.hpp b/src/Vulkan/VkRenderPass.hpp
index 72000f4..2355bb6 100644
--- a/src/Vulkan/VkRenderPass.hpp
+++ b/src/Vulkan/VkRenderPass.hpp
@@ -30,9 +30,52 @@
 	static size_t ComputeRequiredAllocationSize(const VkRenderPassCreateInfo* pCreateInfo);
 
 	void begin();
+	void nextSubpass();
 	void end();
 
+	uint32_t getAttachmentCount() const
+	{
+		return attachmentCount;
+	}
+
+	VkAttachmentDescription getAttachment(uint32_t i) const
+	{
+		return attachments[i];
+	}
+
+	uint32_t getSubpassCount() const
+	{
+		return subpassCount;
+	}
+
+	VkSubpassDescription getSubpass(uint32_t i) const
+	{
+		return subpasses[i];
+	}
+
+	VkSubpassDescription getCurrentSubpass() const
+	{
+		return subpasses[currentSubpass];
+	}
+
+	uint32_t getDependencyCount() const
+	{
+		return dependencyCount;
+	}
+
+	VkSubpassDependency getDependency(uint32_t i) const
+	{
+		return dependencies[i];
+	}
+
 private:
+	uint32_t                 attachmentCount = 0;
+	VkAttachmentDescription* attachments = nullptr;
+	uint32_t                 subpassCount = 0;
+	VkSubpassDescription*    subpasses = nullptr;
+	uint32_t                 dependencyCount = 0;
+	VkSubpassDependency*     dependencies = nullptr;
+	uint32_t                 currentSubpass = 0;
 };
 
 static inline RenderPass* Cast(VkRenderPass object)