RenderPass begin and end

Implemented vkCmdBeginRenderPass and vkCmdEndRenderPass.
The RenderPass object begin and end are noop for now, but
the framebuffer gets cleared within vkCmdBeginRenderPass.

Bug b/119620965 b/118619338

Change-Id: I8e1f2932d9d52b3dcb5c10d4e60cba83b28bb95d
Reviewed-on: https://swiftshader-review.googlesource.com/c/23108
Reviewed-by: Corentin Wallez <cwallez@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index 1b74365..d2a50af 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -13,7 +13,9 @@
 // limitations under the License.
 
 #include "VkCommandBuffer.hpp"
+#include "VkFramebuffer.hpp"
 #include "VkImage.hpp"
+#include "VkRenderpass.hpp"
 
 #include <cstring>
 
@@ -24,7 +26,7 @@
 {
 public:
 	// FIXME (b/119421344): change the commandBuffer argument to a CommandBuffer state
-	virtual void play(CommandBuffer* commandBuffer) = 0;
+	virtual void play(CommandBuffer::ExecutionState& executionState) = 0;
 	virtual ~Command() {}
 };
 
@@ -47,9 +49,10 @@
 	}
 
 protected:
-	void play(CommandBuffer* commandBuffer)
+	void play(CommandBuffer::ExecutionState& executionState)
 	{
-		UNIMPLEMENTED();
+		Cast(renderPass)->begin();
+		Cast(framebuffer)->clear(clearValueCount, clearValues, renderArea);
 	}
 
 private:
@@ -68,9 +71,9 @@
 	}
 
 protected:
-	void play(CommandBuffer* commandBuffer)
+	void play(CommandBuffer::ExecutionState& executionState)
 	{
-		UNIMPLEMENTED();
+		Cast(executionState.renderpass)->end();
 	}
 
 private:
@@ -85,9 +88,9 @@
 	}
 
 protected:
-	void play(CommandBuffer* commandBuffer)
+	void play(CommandBuffer::ExecutionState& executionState)
 	{
-		UNIMPLEMENTED();
+		executionState.pipelines[pipelineBindPoint] = pipeline;
 	}
 
 private:
@@ -102,9 +105,9 @@
 	{
 	}
 
-	void play(CommandBuffer* commandBuffer)
+	void play(CommandBuffer::ExecutionState& executionState)
 	{
-		UNIMPLEMENTED();
+		executionState.vertexInputBindings[binding] = { buffer, offset };
 	}
 
 	uint32_t binding;
@@ -118,7 +121,7 @@
 	{
 	}
 
-	void play(CommandBuffer* commandBuffer)
+	void play(CommandBuffer::ExecutionState& executionState)
 	{
 		UNIMPLEMENTED();
 	}
@@ -133,7 +136,7 @@
 	{
 	}
 
-	void play(CommandBuffer* commandBuffer)
+	void play(CommandBuffer::ExecutionState& executionState)
 	{
 		Cast(srcImage)->copyTo(dstImage, region);
 	}
@@ -151,7 +154,7 @@
 	{
 	}
 
-	void play(CommandBuffer* commandBuffer)
+	void play(CommandBuffer::ExecutionState& executionState)
 	{
 		Cast(srcImage)->copyTo(dstBuffer, region);
 	}
@@ -169,7 +172,7 @@
 	{
 	}
 
-	void play(CommandBuffer* commandBuffer)
+	void play(CommandBuffer::ExecutionState& executionState)
 	{
 		Cast(dstImage)->copyFrom(srcBuffer, region);
 	}
@@ -186,7 +189,7 @@
 	{
 	}
 
-	void play(CommandBuffer* commandBuffer)
+	void play(CommandBuffer::ExecutionState& executionState)
 	{
 		// This can currently be a noop. The sw::Surface locking/unlocking mechanism used by the renderer already takes care of
 		// making sure the read/writes always happen in order. Eventually, if we remove this synchronization mechanism, we can
@@ -205,9 +208,6 @@
 {
 	// FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
 	commands = new std::vector<std::unique_ptr<Command> >();
-
-	pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS] = VK_NULL_HANDLE;
-	pipelines[VK_PIPELINE_BIND_POINT_COMPUTE] = VK_NULL_HANDLE;
 }
 
 void CommandBuffer::destroy(const VkAllocationCallbacks* pAllocator)
@@ -591,14 +591,14 @@
 	UNIMPLEMENTED();
 }
 
-void CommandBuffer::submit()
+void CommandBuffer::submit(CommandBuffer::ExecutionState& executionState)
 {
 	// Perform recorded work
 	state = PENDING;
 
 	for(auto& command : *commands)
 	{
-		command->play(this);
+		command->play(executionState);
 	}
 
 	// After work is completed
diff --git a/src/Vulkan/VkCommandBuffer.hpp b/src/Vulkan/VkCommandBuffer.hpp
index 8191c65..c90dd1d 100644
--- a/src/Vulkan/VkCommandBuffer.hpp
+++ b/src/Vulkan/VkCommandBuffer.hpp
@@ -109,7 +109,21 @@
 	void drawIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
 	void drawIndexedIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
 
-	void submit();
+	// TODO(sugoi): Move ExecutionState out of CommandBuffer (possibly into Device)
+	struct ExecutionState
+	{
+		VkRenderPass renderpass = VK_NULL_HANDLE;
+		VkPipeline pipelines[VK_PIPELINE_BIND_POINT_RANGE_SIZE] = {};
+
+		struct VertexInputBinding
+		{
+			VkBuffer buffer;
+			VkDeviceSize offset;
+		};
+		VertexInputBinding vertexInputBindings[MAX_VERTEX_INPUT_BINDINGS] = {};
+	};
+
+	void submit(CommandBuffer::ExecutionState& executionState);
 
 	class Command;
 private:
@@ -118,14 +132,6 @@
 	enum State { INITIAL, RECORDING, EXECUTABLE, PENDING, INVALID };
 	State state = INITIAL;
 	VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
-	VkPipeline pipelines[VK_PIPELINE_BIND_POINT_RANGE_SIZE];
-
-	struct VertexInputBindings
-	{
-		VkBuffer buffer;
-		VkDeviceSize offset;
-	};
-	VertexInputBindings vertexInputBindings[MAX_VERTEX_INPUT_BINDINGS];
 
 	// FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
 	std::vector<std::unique_ptr<Command>>* commands;
diff --git a/src/Vulkan/VkQueue.cpp b/src/Vulkan/VkQueue.cpp
index 43bb4a0..b433815 100644
--- a/src/Vulkan/VkQueue.cpp
+++ b/src/Vulkan/VkQueue.cpp
@@ -34,9 +34,12 @@
 			vk::Cast(submitInfo.pWaitSemaphores[j])->wait(submitInfo.pWaitDstStageMask[j]);
 		}
 
-		for(uint32_t j = 0; j < submitInfo.commandBufferCount; j++)
 		{
-			vk::Cast(submitInfo.pCommandBuffers[j])->submit();
+			CommandBuffer::ExecutionState executionState;
+			for(uint32_t j = 0; j < submitInfo.commandBufferCount; j++)
+			{
+				vk::Cast(submitInfo.pCommandBuffers[j])->submit(executionState);
+			}
 		}
 
 		for(uint32_t j = 0; j < submitInfo.signalSemaphoreCount; j++)
diff --git a/src/Vulkan/VkRenderPass.cpp b/src/Vulkan/VkRenderPass.cpp
index 3222f53..0b60e0c 100644
--- a/src/Vulkan/VkRenderPass.cpp
+++ b/src/Vulkan/VkRenderPass.cpp
@@ -30,4 +30,14 @@
 	return 0;
 }
 
+void RenderPass::begin()
+{
+	// FIXME (b/119620965): noop
+}
+
+void RenderPass::end()
+{
+	// FIXME (b/119620965): noop
+}
+
 } // namespace vk
\ No newline at end of file
diff --git a/src/Vulkan/VkRenderPass.hpp b/src/Vulkan/VkRenderPass.hpp
index 5d0273e..72000f4 100644
--- a/src/Vulkan/VkRenderPass.hpp
+++ b/src/Vulkan/VkRenderPass.hpp
@@ -29,6 +29,9 @@
 
 	static size_t ComputeRequiredAllocationSize(const VkRenderPassCreateInfo* pCreateInfo);
 
+	void begin();
+	void end();
+
 private:
 };