Implement indexed draws

Adds support for vkBindIndexBuffer and vkDrawIndexed.
There is significant duplication currently between Draw::play and
DrawIndexed::play, but most of it is going to evaporate when we
solve the context stomping problems.

Bug: b/118619338
Change-Id: If8e9f7b1f11a3c763e73663733697fddd3e1fcac
Reviewed-on: https://swiftshader-review.googlesource.com/c/25508
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index d1932bc..7b5fe9f 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -140,6 +140,25 @@
 	const VkDeviceSize offset;
 };
 
+struct IndexBufferBind : public CommandBuffer::Command
+{
+	IndexBufferBind(const VkBuffer buffer, const VkDeviceSize offset, const VkIndexType indexType) :
+		buffer(buffer), offset(offset), indexType(indexType)
+	{
+
+	}
+
+	void play(CommandBuffer::ExecutionState& executionState) override
+	{
+		executionState.indexBufferBinding = {buffer, offset};
+		executionState.indexType = indexType;
+	}
+
+	const VkBuffer buffer;
+	const VkDeviceSize offset;
+	const VkIndexType indexType;
+};
+
 struct Draw : public CommandBuffer::Command
 {
 	Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
@@ -185,7 +204,7 @@
 		for(uint32_t instance = firstInstance; instance <= lastInstance; instance++)
 		{
 			executionState.renderer->setInstanceID(instance);
-			executionState.renderer->draw(context.drawType, 0, primitiveCount);
+			executionState.renderer->draw(context.drawType, primitiveCount);
 		}
 	}
 
@@ -195,6 +214,68 @@
 	uint32_t firstInstance;
 };
 
+struct DrawIndexed : public CommandBuffer::Command
+{
+	DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
+			: indexCount(indexCount), instanceCount(instanceCount), firstIndex(firstIndex), vertexOffset(vertexOffset), firstInstance(firstInstance)
+	{
+	}
+
+	void play(CommandBuffer::ExecutionState& executionState) override
+	{
+		GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>(
+				executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]);
+
+		sw::Context context = pipeline->getContext();
+		for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++)
+		{
+			auto &attrib = context.input[i];
+			if (attrib.count)
+			{
+				const auto &vertexInput = executionState.vertexInputBindings[attrib.binding];
+				Buffer *buffer = Cast(vertexInput.buffer);
+				attrib.buffer = buffer ? buffer->getOffsetPointer(
+						attrib.offset + vertexInput.offset + attrib.stride * vertexOffset) : nullptr;
+			}
+		}
+
+		context.indexBuffer = Cast(executionState.indexBufferBinding.buffer)->getOffsetPointer(
+				executionState.indexBufferBinding.offset + firstIndex * (executionState.indexType == VK_INDEX_TYPE_UINT16 ? 2 : 4));
+
+		executionState.renderer->setContext(context);
+		executionState.renderer->setScissor(pipeline->getScissor());
+		executionState.renderer->setViewport(pipeline->getViewport());
+		executionState.renderer->setBlendConstant(pipeline->getBlendConstants());
+
+		for (auto i = 0u; i < executionState.renderPass->getCurrentSubpass().colorAttachmentCount; i++)
+		{
+			auto attachmentReference = executionState.renderPass->getCurrentSubpass().pColorAttachments[i];
+			if (attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
+			{
+				auto attachment = executionState.renderPassFramebuffer->getAttachment(attachmentReference.attachment);
+				executionState.renderer->setRenderTarget(i, attachment, 0);
+			}
+		}
+
+		auto drawType = executionState.indexType == VK_INDEX_TYPE_UINT16
+				? (context.drawType | sw::DRAW_INDEXED16) : (context.drawType | sw::DRAW_INDEXED32);
+
+		const uint32_t primitiveCount = pipeline->computePrimitiveCount(indexCount);
+		const uint32_t lastInstance = firstInstance + instanceCount - 1;
+		for(uint32_t instance = firstInstance; instance <= lastInstance; instance++)
+		{
+			executionState.renderer->setInstanceID(instance);
+			executionState.renderer->draw(static_cast<sw::DrawType>(drawType), primitiveCount);
+		}
+	}
+
+	uint32_t indexCount;
+	uint32_t instanceCount;
+	uint32_t firstIndex;
+	int32_t vertexOffset;
+	uint32_t firstInstance;
+};
+
 struct ImageToImageCopy : public CommandBuffer::Command
 {
 	ImageToImageCopy(VkImage pSrcImage, VkImage pDstImage, const VkImageCopy& pRegion) :
@@ -715,7 +796,7 @@
 
 void CommandBuffer::bindIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType)
 {
-	UNIMPLEMENTED();
+	addCommand<IndexBufferBind>(buffer, offset, indexType);
 }
 
 void CommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
@@ -876,7 +957,7 @@
 
 void CommandBuffer::drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
 {
-	UNIMPLEMENTED();
+	addCommand<DrawIndexed>(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
 }
 
 void CommandBuffer::drawIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)