Commit e1cf863e by Chris Forbes

Support for per-instance attributes

Bug: b/129149966 Test: dEQP-VK.*instance* Change-Id: I51642d32a8390495f5d9ecd0bb64bca1db33a03d Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/26689 Presubmit-Ready: Chris Forbes <chrisforbes@google.com> Tested-by: 's avatarChris Forbes <chrisforbes@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com>
parent 221459f4
...@@ -314,7 +314,7 @@ namespace sw ...@@ -314,7 +314,7 @@ namespace sw
for(int i = 0; i < MAX_VERTEX_INPUTS; i++) for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
{ {
data->input[i] = context->input[i].buffer; data->input[i] = context->input[i].buffer;
data->stride[i] = context->input[i].stride; data->stride[i] = context->input[i].vertexStride;
} }
if(context->indexBuffer) if(context->indexBuffer)
...@@ -322,7 +322,7 @@ namespace sw ...@@ -322,7 +322,7 @@ namespace sw
data->indices = context->indexBuffer; data->indices = context->indexBuffer;
} }
if(context->vertexShader->hasBuiltinInput(spv::BuiltInInstanceId)) if(context->vertexShader->hasBuiltinInput(spv::BuiltInInstanceIndex))
{ {
data->instanceID = context->instanceID; data->instanceID = context->instanceID;
} }
...@@ -1550,6 +1550,19 @@ namespace sw ...@@ -1550,6 +1550,19 @@ namespace sw
queries.remove(query); queries.remove(query);
} }
void Renderer::advanceInstanceAttributes()
{
for(uint32_t i = 0; i < vk::MAX_VERTEX_INPUT_BINDINGS; i++)
{
auto &attrib = context->input[i];
if (attrib.count && attrib.instanceStride)
{
// Under the casts: attrib.buffer += attrib.instanceStride
attrib.buffer = (void const *)((uintptr_t)attrib.buffer + attrib.instanceStride);
}
}
}
#if PERF_HUD #if PERF_HUD
int Renderer::getThreadCount() int Renderer::getThreadCount()
{ {
......
...@@ -250,6 +250,8 @@ namespace sw ...@@ -250,6 +250,8 @@ namespace sw
void addQuery(Query *query); void addQuery(Query *query);
void removeQuery(Query *query); void removeQuery(Query *query);
void advanceInstanceAttributes();
void synchronize(); void synchronize();
#if PERF_HUD #if PERF_HUD
......
...@@ -39,15 +39,17 @@ namespace sw ...@@ -39,15 +39,17 @@ namespace sw
struct StreamResource struct StreamResource
{ {
const void *buffer; const void *buffer;
unsigned int stride; unsigned int vertexStride;
unsigned int instanceStride;
}; };
struct Stream : public StreamResource struct Stream : public StreamResource
{ {
Stream(const void *buffer = nullptr, unsigned int stride = 0) Stream(const void *buffer = nullptr, unsigned int vertexStride = 0)
{ {
this->buffer = buffer; this->buffer = buffer;
this->stride = stride; this->vertexStride = vertexStride;
this->instanceStride = 0;
} }
Stream &define(StreamType type, unsigned int count, bool normalized = false) Stream &define(StreamType type, unsigned int count, bool normalized = false)
...@@ -74,7 +76,8 @@ namespace sw ...@@ -74,7 +76,8 @@ namespace sw
static const float4 null = {0, 0, 0, 1}; static const float4 null = {0, 0, 0, 1};
buffer = &null; buffer = &null;
stride = 0; vertexStride = 0;
instanceStride = 0;
type = STREAMTYPE_FLOAT; type = STREAMTYPE_FLOAT;
count = 0; count = 0;
normalized = false; normalized = false;
......
...@@ -206,7 +206,7 @@ struct IndexBufferBind : public CommandBuffer::Command ...@@ -206,7 +206,7 @@ struct IndexBufferBind : public CommandBuffer::Command
const VkIndexType indexType; const VkIndexType indexType;
}; };
void CommandBuffer::ExecutionState::bindVertexInputs(sw::Context& context, int firstVertex) void CommandBuffer::ExecutionState::bindVertexInputs(sw::Context& context, int firstVertex, int firstInstance)
{ {
for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++) for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++)
{ {
...@@ -216,7 +216,7 @@ void CommandBuffer::ExecutionState::bindVertexInputs(sw::Context& context, int f ...@@ -216,7 +216,7 @@ void CommandBuffer::ExecutionState::bindVertexInputs(sw::Context& context, int f
const auto &vertexInput = vertexInputBindings[attrib.binding]; const auto &vertexInput = vertexInputBindings[attrib.binding];
Buffer *buffer = Cast(vertexInput.buffer); Buffer *buffer = Cast(vertexInput.buffer);
attrib.buffer = buffer ? buffer->getOffsetPointer( attrib.buffer = buffer ? buffer->getOffsetPointer(
attrib.offset + vertexInput.offset + attrib.stride * firstVertex) : nullptr; attrib.offset + vertexInput.offset + attrib.vertexStride * firstVertex + attrib.instanceStride * firstInstance) : nullptr;
} }
} }
} }
...@@ -266,7 +266,7 @@ struct Draw : public CommandBuffer::Command ...@@ -266,7 +266,7 @@ struct Draw : public CommandBuffer::Command
executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]); executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]);
sw::Context context = pipeline->getContext(); sw::Context context = pipeline->getContext();
executionState.bindVertexInputs(context, firstVertex); executionState.bindVertexInputs(context, firstVertex, firstInstance);
const auto& boundDescriptorSets = executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_GRAPHICS]; const auto& boundDescriptorSets = executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_GRAPHICS];
for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++) for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++)
...@@ -284,11 +284,11 @@ struct Draw : public CommandBuffer::Command ...@@ -284,11 +284,11 @@ struct Draw : public CommandBuffer::Command
executionState.bindAttachments(); executionState.bindAttachments();
const uint32_t primitiveCount = pipeline->computePrimitiveCount(vertexCount); const uint32_t primitiveCount = pipeline->computePrimitiveCount(vertexCount);
const uint32_t lastInstance = firstInstance + instanceCount - 1; for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
for(uint32_t instance = firstInstance; instance <= lastInstance; instance++)
{ {
executionState.renderer->setInstanceID(instance); executionState.renderer->setInstanceID(instance);
executionState.renderer->draw(context.drawType, primitiveCount); executionState.renderer->draw(context.drawType, primitiveCount);
executionState.renderer->advanceInstanceAttributes();
} }
} }
...@@ -311,7 +311,8 @@ struct DrawIndexed : public CommandBuffer::Command ...@@ -311,7 +311,8 @@ struct DrawIndexed : public CommandBuffer::Command
executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]); executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]);
sw::Context context = pipeline->getContext(); sw::Context context = pipeline->getContext();
executionState.bindVertexInputs(context, vertexOffset);
executionState.bindVertexInputs(context, vertexOffset, firstInstance);
const auto& boundDescriptorSets = executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_GRAPHICS]; const auto& boundDescriptorSets = executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_GRAPHICS];
for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++) for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++)
...@@ -335,11 +336,11 @@ struct DrawIndexed : public CommandBuffer::Command ...@@ -335,11 +336,11 @@ struct DrawIndexed : public CommandBuffer::Command
? (context.drawType | sw::DRAW_INDEXED16) : (context.drawType | sw::DRAW_INDEXED32); ? (context.drawType | sw::DRAW_INDEXED16) : (context.drawType | sw::DRAW_INDEXED32);
const uint32_t primitiveCount = pipeline->computePrimitiveCount(indexCount); const uint32_t primitiveCount = pipeline->computePrimitiveCount(indexCount);
const uint32_t lastInstance = firstInstance + instanceCount - 1; for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
for(uint32_t instance = firstInstance; instance <= lastInstance; instance++)
{ {
executionState.renderer->setInstanceID(instance); executionState.renderer->setInstanceID(instance);
executionState.renderer->draw(static_cast<sw::DrawType>(drawType), primitiveCount); executionState.renderer->draw(static_cast<sw::DrawType>(drawType), primitiveCount);
executionState.renderer->advanceInstanceAttributes();
} }
} }
......
...@@ -140,7 +140,7 @@ public: ...@@ -140,7 +140,7 @@ public:
VkIndexType indexType; VkIndexType indexType;
void bindAttachments(); void bindAttachments();
void bindVertexInputs(sw::Context& context, int firstVertex); void bindVertexInputs(sw::Context& context, int firstVertex, int firstInstance);
}; };
void submit(CommandBuffer::ExecutionState& executionState); void submit(CommandBuffer::ExecutionState& executionState);
......
...@@ -276,15 +276,13 @@ GraphicsPipeline::GraphicsPipeline(const VkGraphicsPipelineCreateInfo* pCreateIn ...@@ -276,15 +276,13 @@ GraphicsPipeline::GraphicsPipeline(const VkGraphicsPipelineCreateInfo* pCreateIn
// Temporary in-binding-order representation of buffer strides, to be consumed below // Temporary in-binding-order representation of buffer strides, to be consumed below
// when considering attributes. TODO: unfuse buffers from attributes in backend, is old GL model. // when considering attributes. TODO: unfuse buffers from attributes in backend, is old GL model.
uint32_t bufferStrides[MAX_VERTEX_INPUT_BINDINGS]; uint32_t vertexStrides[MAX_VERTEX_INPUT_BINDINGS];
uint32_t instanceStrides[MAX_VERTEX_INPUT_BINDINGS];
for(uint32_t i = 0; i < vertexInputState->vertexBindingDescriptionCount; i++) for(uint32_t i = 0; i < vertexInputState->vertexBindingDescriptionCount; i++)
{ {
auto const & desc = vertexInputState->pVertexBindingDescriptions[i]; auto const & desc = vertexInputState->pVertexBindingDescriptions[i];
bufferStrides[desc.binding] = desc.stride; vertexStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_VERTEX ? desc.stride : 0;
if(desc.inputRate != VK_VERTEX_INPUT_RATE_VERTEX) instanceStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_INSTANCE ? desc.stride : 0;
{
UNIMPLEMENTED("vertexInputState->pVertexBindingDescriptions[%d]", i);
}
} }
for(uint32_t i = 0; i < vertexInputState->vertexAttributeDescriptionCount; i++) for(uint32_t i = 0; i < vertexInputState->vertexAttributeDescriptionCount; i++)
...@@ -296,7 +294,8 @@ GraphicsPipeline::GraphicsPipeline(const VkGraphicsPipelineCreateInfo* pCreateIn ...@@ -296,7 +294,8 @@ GraphicsPipeline::GraphicsPipeline(const VkGraphicsPipelineCreateInfo* pCreateIn
input.normalized = !vk::Format(desc.format).isNonNormalizedInteger(); input.normalized = !vk::Format(desc.format).isNonNormalizedInteger();
input.offset = desc.offset; input.offset = desc.offset;
input.binding = desc.binding; input.binding = desc.binding;
input.stride = bufferStrides[desc.binding]; input.vertexStride = vertexStrides[desc.binding];
input.instanceStride = instanceStrides[desc.binding];
} }
const VkPipelineInputAssemblyStateCreateInfo* assemblyState = pCreateInfo->pInputAssemblyState; const VkPipelineInputAssemblyStateCreateInfo* assemblyState = pCreateInfo->pInputAssemblyState;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment