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/Device/Context.hpp b/src/Device/Context.hpp
index daa2420..245f516 100644
--- a/src/Device/Context.hpp
+++ b/src/Device/Context.hpp
@@ -197,7 +197,7 @@
vk::ImageView *texture[TOTAL_IMAGE_UNITS];
Stream input[MAX_VERTEX_INPUTS];
- uint8_t *indexBuffer;
+ void *indexBuffer;
vk::ImageView *renderTarget[RENDERTARGETS];
unsigned int renderTargetLayer[RENDERTARGETS];
diff --git a/src/Device/PixelProcessor.cpp b/src/Device/PixelProcessor.cpp
index 0d43b81..db32be0 100644
--- a/src/Device/PixelProcessor.cpp
+++ b/src/Device/PixelProcessor.cpp
@@ -77,11 +77,6 @@
context->renderTargetLayer[index] = layer;
}
- vk::ImageView* PixelProcessor::getRenderTarget(int index)
- {
- return context->renderTarget[index];
- }
-
void PixelProcessor::setDepthBuffer(vk::ImageView *depthBuffer, unsigned int layer)
{
context->depthBuffer = depthBuffer;
diff --git a/src/Device/PixelProcessor.hpp b/src/Device/PixelProcessor.hpp
index 9a0d20f..90b3f81 100644
--- a/src/Device/PixelProcessor.hpp
+++ b/src/Device/PixelProcessor.hpp
@@ -146,7 +146,6 @@
virtual ~PixelProcessor();
void setRenderTarget(int index, vk::ImageView *renderTarget, unsigned int layer = 0);
- vk::ImageView *getRenderTarget(int index);
void setDepthBuffer(vk::ImageView *depthBuffer, unsigned int layer = 0);
void setStencilBuffer(vk::ImageView *stencilBuffer, unsigned int layer = 0);
diff --git a/src/Device/Renderer.cpp b/src/Device/Renderer.cpp
index 7ad30dd..1f90929 100644
--- a/src/Device/Renderer.cpp
+++ b/src/Device/Renderer.cpp
@@ -211,7 +211,7 @@
sw::deallocate(mem);
}
- void Renderer::draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update)
+ void Renderer::draw(DrawType drawType, unsigned int count, bool update)
{
#ifndef NDEBUG
if(count < minPrimitives || count > maxPrimitives)
@@ -315,23 +315,15 @@
for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
{
- draw->vertexStream[i] = context->input[i].resource;
data->input[i] = context->input[i].buffer;
data->stride[i] = context->input[i].stride;
-
- if(draw->vertexStream[i])
- {
- draw->vertexStream[i]->lock(PUBLIC, PRIVATE);
- }
}
if(context->indexBuffer)
{
- data->indices = &context->indexBuffer[indexOffset];
+ data->indices = context->indexBuffer;
}
- draw->indexBuffer = context->indexBuffer;
-
for(int sampler = 0; sampler < TOTAL_IMAGE_UNITS; sampler++)
{
draw->texture[sampler] = 0;
@@ -834,14 +826,6 @@
draw.queries = 0;
}
- for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
- {
- if(draw.vertexStream[i])
- {
- draw.vertexStream[i]->unlock();
- }
- }
-
draw.vertexRoutine->unbind();
draw.setupRoutine->unbind();
draw.pixelRoutine->unbind();
@@ -1575,11 +1559,6 @@
}
}
- void Renderer::setIndexBuffer(uint8_t *indexBuffer)
- {
- context->indexBuffer = indexBuffer;
- }
-
void Renderer::setMultiSampleMask(unsigned int mask)
{
context->sampleMask = mask;
diff --git a/src/Device/Renderer.hpp b/src/Device/Renderer.hpp
index 013bc3d..598c81a 100644
--- a/src/Device/Renderer.hpp
+++ b/src/Device/Renderer.hpp
@@ -247,14 +247,13 @@
void *operator new(size_t size);
void operator delete(void * mem);
- void draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update = true);
+ void draw(DrawType drawType, unsigned int count, bool update = true);
void clear(void *value, VkFormat format, Surface *dest, const Rect &rect, unsigned int rgbaMask);
void blit(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil = false, bool sRGBconversion = true);
void blit3D(Surface *source, Surface *dest);
void setContext(const sw::Context& context);
- void setIndexBuffer(uint8_t *indexBuffer);
void setMultiSampleMask(unsigned int mask);
void setTransparencyAntialiasing(TransparencyAntialiasing transparencyAntialiasing);
@@ -423,8 +422,6 @@
int (Renderer::*setupPrimitives)(int batch, int count);
SetupProcessor::State setupState;
- Resource *vertexStream[MAX_VERTEX_INPUTS];
- uint8_t *indexBuffer;
vk::ImageView *renderTarget[RENDERTARGETS];
vk::ImageView *depthBuffer;
vk::ImageView *stencilBuffer;
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)
diff --git a/src/Vulkan/VkCommandBuffer.hpp b/src/Vulkan/VkCommandBuffer.hpp
index 1a1548b..eb5f891 100644
--- a/src/Vulkan/VkCommandBuffer.hpp
+++ b/src/Vulkan/VkCommandBuffer.hpp
@@ -133,6 +133,8 @@
VkDeviceSize offset;
};
VertexInputBinding vertexInputBindings[MAX_VERTEX_INPUT_BINDINGS] = {};
+ VertexInputBinding indexBufferBinding;
+ VkIndexType indexType;
};
void submit(CommandBuffer::ExecutionState& executionState);