Commit 7fe5a06d by Alexis Hetu Committed by Alexis Hétu

Primitive Restart implementation

This cl is a very basic implementation of primitive restart which records every segment of at least 1 primitive into a vector of index buffers and primitive counts which are then looped over at draw time. There's no caching involved, so the primitive restart segments will get recomputed at every draw, until a caching mechanism is introduced. Tests: dEQP-VK.pipeline.input_assembly.primitive_restart.* Bug b/118619338 Change-Id: If2f88ffb7971d1aa7d1451c7916f0ba65a2e09de Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31032Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Presubmit-Ready: Alexis Hétu <sugoi@google.com> Reviewed-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent e228502d
...@@ -455,6 +455,51 @@ struct DrawBase : public CommandBuffer::Command ...@@ -455,6 +455,51 @@ struct DrawBase : public CommandBuffer::Command
return executionState.indexType == VK_INDEX_TYPE_UINT16 ? 2 : 4; return executionState.indexType == VK_INDEX_TYPE_UINT16 ? 2 : 4;
} }
template<typename T>
void processPrimitiveRestart(T* indexBuffer,
uint32_t count,
GraphicsPipeline* pipeline,
std::vector<std::pair<uint32_t, void*>>& indexBuffers)
{
static const T RestartIndex = static_cast<T>(-1);
T* indexBufferStart = indexBuffer;
uint32_t vertexCount = 0;
for(uint32_t i = 0; i < count; i++)
{
if(indexBuffer[i] == RestartIndex)
{
// Record previous segment
if(vertexCount > 0)
{
uint32_t primitiveCount = pipeline->computePrimitiveCount(vertexCount);
if(primitiveCount > 0)
{
indexBuffers.push_back({ primitiveCount, indexBufferStart });
}
}
vertexCount = 0;
}
else
{
if(vertexCount == 0)
{
indexBufferStart = indexBuffer + i;
}
vertexCount++;
}
}
// Record last segment
if(vertexCount > 0)
{
uint32_t primitiveCount = pipeline->computePrimitiveCount(vertexCount);
if(primitiveCount > 0)
{
indexBuffers.push_back({ primitiveCount, indexBufferStart });
}
}
}
void draw(CommandBuffer::ExecutionState& executionState, bool indexed, void draw(CommandBuffer::ExecutionState& executionState, bool indexed,
uint32_t count, uint32_t instanceCount, uint32_t first, int32_t vertexOffset, uint32_t firstInstance) uint32_t count, uint32_t instanceCount, uint32_t first, int32_t vertexOffset, uint32_t firstInstance)
{ {
...@@ -470,12 +515,6 @@ struct DrawBase : public CommandBuffer::Command ...@@ -470,12 +515,6 @@ struct DrawBase : public CommandBuffer::Command
context.descriptorDynamicOffsets = pipelineState.descriptorDynamicOffsets; context.descriptorDynamicOffsets = pipelineState.descriptorDynamicOffsets;
context.pushConstants = executionState.pushConstants; context.pushConstants = executionState.pushConstants;
if(indexed)
{
context.indexBuffer = Cast(executionState.indexBufferBinding.buffer)->getOffsetPointer(
executionState.indexBufferBinding.offset + first * bytesPerIndex(executionState));
}
// Apply either pipeline state or dynamic state // Apply either pipeline state or dynamic state
executionState.renderer->setScissor(pipeline->hasDynamicState(VK_DYNAMIC_STATE_SCISSOR) ? executionState.renderer->setScissor(pipeline->hasDynamicState(VK_DYNAMIC_STATE_SCISSOR) ?
executionState.dynamicState.scissor : pipeline->getScissor()); executionState.dynamicState.scissor : pipeline->getScissor());
...@@ -520,11 +559,46 @@ struct DrawBase : public CommandBuffer::Command ...@@ -520,11 +559,46 @@ struct DrawBase : public CommandBuffer::Command
context.multiSampleMask = context.sampleMask & ((unsigned)0xFFFFFFFF >> (32 - context.sampleCount)); context.multiSampleMask = context.sampleMask & ((unsigned)0xFFFFFFFF >> (32 - context.sampleCount));
context.occlusionEnabled = executionState.renderer->hasQueryOfType(VK_QUERY_TYPE_OCCLUSION); context.occlusionEnabled = executionState.renderer->hasQueryOfType(VK_QUERY_TYPE_OCCLUSION);
const uint32_t primitiveCount = pipeline->computePrimitiveCount(count); std::vector<std::pair<uint32_t, void*>> indexBuffers;
if(indexed)
{
void* indexBuffer = Cast(executionState.indexBufferBinding.buffer)->getOffsetPointer(
executionState.indexBufferBinding.offset + first * bytesPerIndex(executionState));
if(pipeline->hasPrimitiveRestartEnable())
{
switch(executionState.indexType)
{
case VK_INDEX_TYPE_UINT16:
processPrimitiveRestart(static_cast<uint16_t*>(indexBuffer), count, pipeline, indexBuffers);
break;
case VK_INDEX_TYPE_UINT32:
processPrimitiveRestart(static_cast<uint32_t*>(indexBuffer), count, pipeline, indexBuffers);
break;
default:
UNIMPLEMENTED("executionState.indexType %d", int(executionState.indexType));
}
}
else
{
indexBuffers.push_back({ pipeline->computePrimitiveCount(count), indexBuffer });
}
}
else
{
indexBuffers.push_back({ pipeline->computePrimitiveCount(count), nullptr });
}
for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++) for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
{ {
context.instanceID = instance; context.instanceID = instance;
executionState.renderer->draw(&context, executionState.indexType, primitiveCount, vertexOffset, executionState.fence);
for(auto indexBuffer : indexBuffers)
{
const uint32_t primitiveCount = indexBuffer.first;
context.indexBuffer = indexBuffer.second;
executionState.renderer->draw(&context, executionState.indexType, primitiveCount, vertexOffset, executionState.fence);
}
executionState.renderer->advanceInstanceAttributes(context.input); executionState.renderer->advanceInstanceAttributes(context.input);
} }
} }
......
...@@ -301,12 +301,12 @@ GraphicsPipeline::GraphicsPipeline(const VkGraphicsPipelineCreateInfo* pCreateIn ...@@ -301,12 +301,12 @@ GraphicsPipeline::GraphicsPipeline(const VkGraphicsPipelineCreateInfo* pCreateIn
} }
const VkPipelineInputAssemblyStateCreateInfo* assemblyState = pCreateInfo->pInputAssemblyState; const VkPipelineInputAssemblyStateCreateInfo* assemblyState = pCreateInfo->pInputAssemblyState;
if((assemblyState->flags != 0) || if(assemblyState->flags != 0)
(assemblyState->primitiveRestartEnable != 0))
{ {
UNIMPLEMENTED("pCreateInfo->pInputAssemblyState settings"); UNIMPLEMENTED("pCreateInfo->pInputAssemblyState settings");
} }
primitiveRestartEnable = assemblyState->primitiveRestartEnable;
context.topology = assemblyState->topology; context.topology = assemblyState->topology;
const VkPipelineViewportStateCreateInfo* viewportState = pCreateInfo->pViewportState; const VkPipelineViewportStateCreateInfo* viewportState = pCreateInfo->pViewportState;
......
...@@ -80,12 +80,14 @@ public: ...@@ -80,12 +80,14 @@ public:
const VkViewport& getViewport() const; const VkViewport& getViewport() const;
const sw::Color<float>& getBlendConstants() const; const sw::Color<float>& getBlendConstants() const;
bool hasDynamicState(VkDynamicState dynamicState) const; bool hasDynamicState(VkDynamicState dynamicState) const;
bool hasPrimitiveRestartEnable() const { return primitiveRestartEnable; }
private: private:
sw::SpirvShader *vertexShader = nullptr; sw::SpirvShader *vertexShader = nullptr;
sw::SpirvShader *fragmentShader = nullptr; sw::SpirvShader *fragmentShader = nullptr;
uint32_t dynamicStateFlags = 0; uint32_t dynamicStateFlags = 0;
bool primitiveRestartEnable = false;
sw::Context context; sw::Context context;
VkRect2D scissor; VkRect2D scissor;
VkViewport viewport; VkViewport viewport;
......
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