Implement indirect draws
Bug: b/118619338
Test: dEQP-VK.draw.*
Change-Id: I282c0f1e8f44b0bec2318ab901ec511413bff11d
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27888
Tested-by: Chris Forbes <chrisforbes@google.com>
Presubmit-Ready: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index 3156053..447075e 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -268,59 +268,15 @@
}
}
-struct Draw : public CommandBuffer::Command
+struct DrawBase : public CommandBuffer::Command
{
- Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
- : vertexCount(vertexCount), instanceCount(instanceCount), firstVertex(firstVertex), firstInstance(firstInstance)
+ int bytesPerIndex(CommandBuffer::ExecutionState const& executionState)
{
+ return executionState.indexType == VK_INDEX_TYPE_UINT16 ? 2 : 4;
}
- void play(CommandBuffer::ExecutionState& executionState) override
- {
- GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>(
- executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]);
-
- sw::Context context = pipeline->getContext();
- executionState.bindVertexInputs(context, firstVertex, firstInstance);
-
- const auto& boundDescriptorSets = executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_GRAPHICS];
- for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++)
- {
- context.descriptorSets[i] = reinterpret_cast<vk::DescriptorSet*>(boundDescriptorSets[i]);
- }
-
- context.pushConstants = executionState.pushConstants;
-
- executionState.renderer->setContext(context);
- executionState.renderer->setScissor(pipeline->getScissor());
- executionState.renderer->setViewport(pipeline->getViewport());
- executionState.renderer->setBlendConstant(pipeline->getBlendConstants());
-
- executionState.bindAttachments();
-
- const uint32_t primitiveCount = pipeline->computePrimitiveCount(vertexCount);
- for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
- {
- executionState.renderer->setInstanceID(instance);
- executionState.renderer->draw(context.drawType, primitiveCount);
- executionState.renderer->advanceInstanceAttributes();
- }
- }
-
- uint32_t vertexCount;
- uint32_t instanceCount;
- uint32_t firstVertex;
- 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
+ void draw(CommandBuffer::ExecutionState& executionState, bool indexed,
+ uint32_t count, uint32_t instanceCount, uint32_t first, int32_t vertexOffset, uint32_t firstInstance)
{
GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>(
executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]);
@@ -336,9 +292,16 @@
}
context.pushConstants = executionState.pushConstants;
+ auto drawType = context.drawType;
- context.indexBuffer = Cast(executionState.indexBufferBinding.buffer)->getOffsetPointer(
- executionState.indexBufferBinding.offset + firstIndex * (executionState.indexType == VK_INDEX_TYPE_UINT16 ? 2 : 4));
+ if (indexed)
+ {
+ context.indexBuffer = Cast(executionState.indexBufferBinding.buffer)->getOffsetPointer(
+ executionState.indexBufferBinding.offset + first * bytesPerIndex(executionState));
+
+ drawType = static_cast<sw::DrawType>(executionState.indexType == VK_INDEX_TYPE_UINT16
+ ? (context.drawType | sw::DRAW_INDEXED16) : (context.drawType | sw::DRAW_INDEXED32));
+ }
executionState.renderer->setContext(context);
executionState.renderer->setScissor(pipeline->getScissor());
@@ -347,17 +310,45 @@
executionState.bindAttachments();
- 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 primitiveCount = pipeline->computePrimitiveCount(count);
for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
{
executionState.renderer->setInstanceID(instance);
- executionState.renderer->draw(static_cast<sw::DrawType>(drawType), primitiveCount);
+ executionState.renderer->draw(drawType, primitiveCount);
executionState.renderer->advanceInstanceAttributes();
}
}
+};
+
+struct Draw : public DrawBase
+{
+ Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
+ : vertexCount(vertexCount), instanceCount(instanceCount), firstVertex(firstVertex), firstInstance(firstInstance)
+ {
+ }
+
+ void play(CommandBuffer::ExecutionState& executionState) override
+ {
+ draw(executionState, false, vertexCount, instanceCount, 0, firstVertex, firstInstance);
+ }
+
+ uint32_t vertexCount;
+ uint32_t instanceCount;
+ uint32_t firstVertex;
+ uint32_t firstInstance;
+};
+
+struct DrawIndexed : public DrawBase
+{
+ 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
+ {
+ draw(executionState, true, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
+ }
uint32_t indexCount;
uint32_t instanceCount;
@@ -366,6 +357,50 @@
uint32_t firstInstance;
};
+struct DrawIndirect : public DrawBase
+{
+ DrawIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
+ : buffer(buffer), offset(offset), drawCount(drawCount), stride(stride)
+ {
+ }
+
+ void play(CommandBuffer::ExecutionState& executionState) override
+ {
+ for (auto drawId = 0u; drawId < drawCount; drawId++)
+ {
+ auto cmd = reinterpret_cast<VkDrawIndirectCommand const *>(Cast(buffer)->getOffsetPointer(offset + drawId * stride));
+ draw(executionState, false, cmd->vertexCount, cmd->instanceCount, 0, cmd->firstVertex, cmd->firstInstance);
+ }
+ }
+
+ VkBuffer buffer;
+ VkDeviceSize offset;
+ uint32_t drawCount;
+ uint32_t stride;
+};
+
+struct DrawIndexedIndirect : public DrawBase
+{
+ DrawIndexedIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
+ : buffer(buffer), offset(offset), drawCount(drawCount), stride(stride)
+ {
+ }
+
+ void play(CommandBuffer::ExecutionState& executionState) override
+ {
+ for (auto drawId = 0u; drawId < drawCount; drawId++)
+ {
+ auto cmd = reinterpret_cast<VkDrawIndexedIndirectCommand const *>(Cast(buffer)->getOffsetPointer(offset + drawId * stride));
+ draw(executionState, true, cmd->indexCount, cmd->instanceCount, cmd->firstIndex, cmd->vertexOffset, cmd->firstInstance);
+ }
+ }
+
+ VkBuffer buffer;
+ VkDeviceSize offset;
+ uint32_t drawCount;
+ uint32_t stride;
+};
+
struct ImageToImageCopy : public CommandBuffer::Command
{
ImageToImageCopy(VkImage pSrcImage, VkImage pDstImage, const VkImageCopy& pRegion) :
@@ -1110,12 +1145,12 @@
void CommandBuffer::drawIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
{
- UNIMPLEMENTED("drawIndirect");
+ addCommand<DrawIndirect>(buffer, offset, drawCount, stride);
}
void CommandBuffer::drawIndexedIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
{
- UNIMPLEMENTED("drawIndexedIndirect");
+ addCommand<DrawIndexedIndirect>(buffer, offset, drawCount, stride);
}
void CommandBuffer::submit(CommandBuffer::ExecutionState& executionState)