Support render area instead of extent in Renderer::draw()

Some Vulkan 1.3 features related to dynamic rendering expect the
render area to support an offset, as opposed to only requiring a
width and height, so this CL adds support for a render area in
Renderer::draw().

Note: This may be related to b/177842474, but since we're
missing test coverage for it, we can't test it yet, but
this CL might be a step in the right direction.

Bug: b/204502119
Bug: b/177842474
Change-Id: I6d27f353279ef6d46f86c8c65c8e0d1fa76ff927
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/62970
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Commit-Queue: Alexis Hétu <sugoi@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
diff --git a/src/Device/Renderer.cpp b/src/Device/Renderer.cpp
index 1fa8b8c..2b13deb 100644
--- a/src/Device/Renderer.cpp
+++ b/src/Device/Renderer.cpp
@@ -181,7 +181,7 @@
 }
 
 void Renderer::draw(const vk::GraphicsPipeline *pipeline, const vk::DynamicState &dynamicState, unsigned int count, int baseVertex,
-                    CountedEvent *events, int instanceID, int viewID, void *indexBuffer, const VkExtent3D &framebufferExtent,
+                    CountedEvent *events, int instanceID, int viewID, void *indexBuffer, const VkRect2D &renderArea,
                     vk::Pipeline::PushConstantStorage const &pushConstants, bool update)
 {
 	if(count == 0) { return; }
@@ -413,10 +413,14 @@
 	{
 		const VkRect2D &scissor = pipelineState.getScissor();
 
-		data->scissorX0 = clamp<int>(scissor.offset.x, 0, framebufferExtent.width);
-		data->scissorX1 = clamp<int>(scissor.offset.x + scissor.extent.width, 0, framebufferExtent.width);
-		data->scissorY0 = clamp<int>(scissor.offset.y, 0, framebufferExtent.height);
-		data->scissorY1 = clamp<int>(scissor.offset.y + scissor.extent.height, 0, framebufferExtent.height);
+		int x0 = renderArea.offset.x;
+		int y0 = renderArea.offset.y;
+		int x1 = x0 + renderArea.extent.width;
+		int y1 = y0 + renderArea.extent.height;
+		data->scissorX0 = clamp<int>(scissor.offset.x, x0, x1);
+		data->scissorX1 = clamp<int>(scissor.offset.x + scissor.extent.width, x0, x1);
+		data->scissorY0 = clamp<int>(scissor.offset.y, y0, y1);
+		data->scissorY1 = clamp<int>(scissor.offset.y + scissor.extent.height, y0, y1);
 	}
 
 	// Push constants
diff --git a/src/Device/Renderer.hpp b/src/Device/Renderer.hpp
index be0bb94..610c592 100644
--- a/src/Device/Renderer.hpp
+++ b/src/Device/Renderer.hpp
@@ -206,7 +206,7 @@
 	bool hasOcclusionQuery() const { return occlusionQuery != nullptr; }
 
 	void draw(const vk::GraphicsPipeline *pipeline, const vk::DynamicState &dynamicState, unsigned int count, int baseVertex,
-	          CountedEvent *events, int instanceID, int viewID, void *indexBuffer, const VkExtent3D &framebufferExtent,
+	          CountedEvent *events, int instanceID, int viewID, void *indexBuffer, const VkRect2D &renderArea,
 	          vk::Pipeline::PushConstantStorage const &pushConstants, bool update = true);
 
 	void addQuery(vk::Query *query);
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index a890b06..93f7ab3 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -787,6 +787,8 @@
 		std::vector<std::pair<uint32_t, void *>> indexBuffers;
 		pipeline->getIndexBuffers(executionState.dynamicState, count, first, indexed, &indexBuffers);
 
+		VkRect2D renderArea = executionState.getRenderArea();
+
 		for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
 		{
 			// FIXME: reconsider instances/views nesting.
@@ -800,8 +802,7 @@
 				{
 					executionState.renderer->draw(pipeline, executionState.dynamicState, indexBuffer.first, vertexOffset,
 					                              executionState.events, instance, viewID, indexBuffer.second,
-					                              executionState.renderPassFramebuffer->getExtent(),
-					                              executionState.pushConstants);
+					                              renderArea, executionState.pushConstants);
 				}
 			}
 
@@ -2161,6 +2162,18 @@
 	}
 }
 
+VkRect2D CommandBuffer::ExecutionState::getRenderArea() const
+{
+	VkRect2D renderArea = {};
+
+	if(renderPassFramebuffer)
+	{
+		renderArea.extent = renderPassFramebuffer->getExtent();
+	}
+
+	return renderArea;
+}
+
 // Returns the number of bits set in the view mask, or 1 if multiview is disabled.
 uint32_t CommandBuffer::ExecutionState::viewCount() const
 {
diff --git a/src/Vulkan/VkCommandBuffer.hpp b/src/Vulkan/VkCommandBuffer.hpp
index f66d38c..28699ff 100644
--- a/src/Vulkan/VkCommandBuffer.hpp
+++ b/src/Vulkan/VkCommandBuffer.hpp
@@ -173,6 +173,7 @@
 
 		void bindAttachments(Attachments *attachments);
 
+		VkRect2D getRenderArea() const;
 		uint32_t viewCount() const;
 	};
 
diff --git a/src/Vulkan/VkFramebuffer.cpp b/src/Vulkan/VkFramebuffer.cpp
index 77eb295..4d34cc2 100644
--- a/src/Vulkan/VkFramebuffer.cpp
+++ b/src/Vulkan/VkFramebuffer.cpp
@@ -25,7 +25,7 @@
 
 Framebuffer::Framebuffer(const VkFramebufferCreateInfo *pCreateInfo, void *mem)
     : attachments(reinterpret_cast<ImageView **>(mem))
-    , extent{ pCreateInfo->width, pCreateInfo->height, pCreateInfo->layers }
+    , extent{ pCreateInfo->width, pCreateInfo->height }
 {
 	const VkBaseInStructure *curInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
 	const VkFramebufferAttachmentsCreateInfo *attachmentsCreateInfo = nullptr;
diff --git a/src/Vulkan/VkFramebuffer.hpp b/src/Vulkan/VkFramebuffer.hpp
index 63c02f7..51a8406 100644
--- a/src/Vulkan/VkFramebuffer.hpp
+++ b/src/Vulkan/VkFramebuffer.hpp
@@ -36,12 +36,12 @@
 	ImageView *getAttachment(uint32_t index) const;
 	void resolve(const RenderPass *renderPass, uint32_t subpassIndex);
 
-	const VkExtent3D &getExtent() const { return extent; }
+	const VkExtent2D &getExtent() const { return extent; }
 
 private:
 	uint32_t attachmentCount = 0;
 	ImageView **attachments = nullptr;
-	const VkExtent3D extent = {};
+	const VkExtent2D extent = {};
 };
 
 static inline Framebuffer *Cast(VkFramebuffer object)