Commit 3c2a5230 by Courtney Goeltzenleuchter Committed by Commit Bot

Vulkan: 8bit index support for DrawElementsIndirect

Add partial support for DrawElementsIndirect. This supports all primitives types except lineloop. Includes a compute shader for converting 8bit index buffers to 16bit index buffers where the index buffer range is defined in a GPU buffer. Test: dEQP.GLES31/functional_draw_indirect_* Bug: angleproject:3564 Change-Id: Ibe9c55323e46a398f0b703cd8597a72ba6790570 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1792948 Commit-Queue: Courtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 7c8e276c
...@@ -82,9 +82,13 @@ ...@@ -82,9 +82,13 @@
"src/libANGLE/renderer/vulkan/shaders/gen/BufferUtils.comp.0000000B.inc": "src/libANGLE/renderer/vulkan/shaders/gen/BufferUtils.comp.0000000B.inc":
"7e13d5325d35f96045e920a1cb3598bc", "7e13d5325d35f96045e920a1cb3598bc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000000.inc": "src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000000.inc":
"dbd9529dd0c4ba0947842a9eb18e6189", "b3877393750a16efd1d6805a0327a9e7",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000001.inc": "src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000001.inc":
"2e8b92c66a347f3517ae1945d3ad625c", "66d7868159587d000ef41d84489780bc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000002.inc":
"db98380613bc3f032037b4a096756975",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000003.inc":
"e676bdff5c3b596eccba13a4e52d3875",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000000.inc": "src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000000.inc":
"f5ef892346ee10e5d0d9f8cba2a491b2", "f5ef892346ee10e5d0d9f8cba2a491b2",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000001.inc": "src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000001.inc":
...@@ -282,7 +286,7 @@ ...@@ -282,7 +286,7 @@
"src/libANGLE/renderer/vulkan/shaders/src/BufferUtils.comp": "src/libANGLE/renderer/vulkan/shaders/src/BufferUtils.comp":
"b7c20e019199f8328ef37b11c6fbcadd", "b7c20e019199f8328ef37b11c6fbcadd",
"src/libANGLE/renderer/vulkan/shaders/src/ConvertIndex.comp": "src/libANGLE/renderer/vulkan/shaders/src/ConvertIndex.comp":
"ca35df77d258baa0636529d1f0f446a9", "083e2b6ed2cf40f036287413c449e675",
"src/libANGLE/renderer/vulkan/shaders/src/ConvertVertex.comp": "src/libANGLE/renderer/vulkan/shaders/src/ConvertVertex.comp":
"88d434e43a01906e6a6b1dd5d5e45cdc", "88d434e43a01906e6a6b1dd5d5e45cdc",
"src/libANGLE/renderer/vulkan/shaders/src/FullScreenQuad.vert": "src/libANGLE/renderer/vulkan/shaders/src/FullScreenQuad.vert":
...@@ -296,9 +300,9 @@ ...@@ -296,9 +300,9 @@
"src/libANGLE/renderer/vulkan/shaders/src/OverlayDraw.comp": "src/libANGLE/renderer/vulkan/shaders/src/OverlayDraw.comp":
"dcc246b398b2e07a869a264666499362", "dcc246b398b2e07a869a264666499362",
"src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp": "src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp":
"c38ca374f8af3ce9a394b7170747cb27", "24c8e4c95087419916f879a8c7976213",
"src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h": "src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h":
"c1fdbaf6ed5605cd453eb94276e9c990", "2ee06bb4c179bcdcd4863396c43776a9",
"tools/glslang/glslang_validator.exe.sha1": "tools/glslang/glslang_validator.exe.sha1":
"289f30598865a987a21b79ae525fc66f", "289f30598865a987a21b79ae525fc66f",
"tools/glslang/glslang_validator.sha1": "tools/glslang/glslang_validator.sha1":
......
...@@ -605,6 +605,24 @@ angle::Result ContextVk::setupIndirectDraw(const gl::Context *context, ...@@ -605,6 +605,24 @@ angle::Result ContextVk::setupIndirectDraw(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode,
gl::DrawElementsType indexType,
vk::CommandBuffer **commandBufferOut,
vk::Buffer **indirectBufferOut)
{
ASSERT(mode != gl::PrimitiveMode::LineLoop);
if (indexType != mCurrentDrawElementsType)
{
mCurrentDrawElementsType = indexType;
setIndexBufferDirty();
}
return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, commandBufferOut,
indirectBufferOut);
}
angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context, angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLint firstVertex, GLint firstVertex,
...@@ -1523,8 +1541,34 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context, ...@@ -1523,8 +1541,34 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
gl::DrawElementsType type, gl::DrawElementsType type,
const void *indirect) const void *indirect)
{ {
ANGLE_VK_UNREACHABLE(this); gl::Buffer *indirectBuffer = mState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
return angle::Result::Stop; ASSERT(indirectBuffer);
const gl::Buffer *indexBuffer = mVertexArray->getState().getElementArrayBuffer();
ASSERT(indexBuffer);
if (type == gl::DrawElementsType::UnsignedByte && mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
{
BufferVk *indexVk = vk::GetImpl(indexBuffer);
BufferVk *cmdBufferVk = vk::GetImpl(indirectBuffer);
ANGLE_TRY(
mVertexArray->convertIndexBufferIndirectGPU(this, cmdBufferVk, indexVk, indirect));
}
vk::CommandBuffer *commandBuffer = nullptr;
vk::Buffer *buffer = nullptr;
ANGLE_TRY(setupIndexedIndirectDraw(context, mode, type, &commandBuffer, &buffer));
if (mode == gl::PrimitiveMode::LineLoop)
{
// TODO - http://anglebug.com/3564
ANGLE_VK_UNREACHABLE(this);
return angle::Result::Stop;
}
commandBuffer->drawIndexedIndirect(*buffer, reinterpret_cast<VkDeviceSize>(indirect), 1, 0);
return angle::Result::Continue;
} }
gl::GraphicsResetStatus ContextVk::getResetStatus() gl::GraphicsResetStatus ContextVk::getResetStatus()
......
...@@ -388,6 +388,11 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO ...@@ -388,6 +388,11 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
DirtyBits dirtyBitMask, DirtyBits dirtyBitMask,
vk::CommandBuffer **commandBufferOut, vk::CommandBuffer **commandBufferOut,
vk::Buffer **indirectBufferOut); vk::Buffer **indirectBufferOut);
angle::Result setupIndexedIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode,
gl::DrawElementsType indexType,
vk::CommandBuffer **commandBufferOut,
vk::Buffer **indirectBufferOut);
angle::Result setupLineLoopDraw(const gl::Context *context, angle::Result setupLineLoopDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
......
...@@ -220,6 +220,13 @@ void SecondaryCommandBuffer::executeCommands(VkCommandBuffer cmdBuffer) ...@@ -220,6 +220,13 @@ void SecondaryCommandBuffer::executeCommands(VkCommandBuffer cmdBuffer)
vkCmdDrawIndirect(cmdBuffer, params->buffer, params->offset, 1, 0); vkCmdDrawIndirect(cmdBuffer, params->buffer, params->offset, 1, 0);
break; break;
} }
case CommandID::DrawIndexedIndirect:
{
const DrawIndexedIndirectParams *params =
getParamPtr<DrawIndexedIndirectParams>(currentCommand);
vkCmdDrawIndexedIndirect(cmdBuffer, params->buffer, params->offset, 1, 0);
break;
}
case CommandID::EndQuery: case CommandID::EndQuery:
{ {
const EndQueryParams *params = getParamPtr<EndQueryParams>(currentCommand); const EndQueryParams *params = getParamPtr<EndQueryParams>(currentCommand);
...@@ -443,6 +450,9 @@ std::string SecondaryCommandBuffer::dumpCommands(const char *separator) const ...@@ -443,6 +450,9 @@ std::string SecondaryCommandBuffer::dumpCommands(const char *separator) const
case CommandID::DrawInstanced: case CommandID::DrawInstanced:
result += "DrawInstanced"; result += "DrawInstanced";
break; break;
case CommandID::DrawIndexedIndirect:
result += "DrawIndexedIndirect";
break;
case CommandID::EndQuery: case CommandID::EndQuery:
result += "EndQuery"; result += "EndQuery";
break; break;
......
...@@ -52,6 +52,7 @@ enum class CommandID : uint16_t ...@@ -52,6 +52,7 @@ enum class CommandID : uint16_t
DrawInstanced, DrawInstanced,
DrawInstancedBaseInstance, DrawInstancedBaseInstance,
DrawIndirect, DrawIndirect,
DrawIndexedIndirect,
EndQuery, EndQuery,
ExecutionBarrier, ExecutionBarrier,
FillBuffer, FillBuffer,
...@@ -231,6 +232,13 @@ struct DrawIndexedInstancedBaseVertexBaseInstanceParams ...@@ -231,6 +232,13 @@ struct DrawIndexedInstancedBaseVertexBaseInstanceParams
}; };
VERIFY_4_BYTE_ALIGNMENT(DrawIndexedInstancedBaseVertexBaseInstanceParams) VERIFY_4_BYTE_ALIGNMENT(DrawIndexedInstancedBaseVertexBaseInstanceParams)
struct DrawIndexedIndirectParams
{
VkBuffer buffer;
VkDeviceSize offset;
};
VERIFY_4_BYTE_ALIGNMENT(DrawIndexedIndirectParams)
struct DispatchParams struct DispatchParams
{ {
uint32_t groupCountX; uint32_t groupCountX;
...@@ -488,6 +496,11 @@ class SecondaryCommandBuffer final : angle::NonCopyable ...@@ -488,6 +496,11 @@ class SecondaryCommandBuffer final : angle::NonCopyable
VkDeviceSize offset, VkDeviceSize offset,
uint32_t drawCount, uint32_t drawCount,
uint32_t stride); uint32_t stride);
void drawIndexedIndirect(const Buffer &buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride);
void endQuery(VkQueryPool queryPool, uint32_t query); void endQuery(VkQueryPool queryPool, uint32_t query);
void executionBarrier(VkPipelineStageFlags stageMask); void executionBarrier(VkPipelineStageFlags stageMask);
...@@ -969,6 +982,18 @@ ANGLE_INLINE void SecondaryCommandBuffer::drawIndirect(const Buffer &buffer, ...@@ -969,6 +982,18 @@ ANGLE_INLINE void SecondaryCommandBuffer::drawIndirect(const Buffer &buffer,
ASSERT(drawCount == 1); ASSERT(drawCount == 1);
} }
ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedIndirect(const Buffer &buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride)
{
DrawIndexedIndirectParams *paramStruct =
initCommand<DrawIndexedIndirectParams>(CommandID::DrawIndexedIndirect);
paramStruct->buffer = buffer.getHandle();
paramStruct->offset = offset;
ASSERT(drawCount == 1);
}
ANGLE_INLINE void SecondaryCommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query) ANGLE_INLINE void SecondaryCommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query)
{ {
EndQueryParams *paramStruct = initCommand<EndQueryParams>(CommandID::EndQuery); EndQueryParams *paramStruct = initCommand<EndQueryParams>(CommandID::EndQuery);
......
...@@ -99,9 +99,9 @@ uint32_t GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters &params) ...@@ -99,9 +99,9 @@ uint32_t GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters &params)
// Assert on the types to make sure the shader supports its. These are based on // Assert on the types to make sure the shader supports its. These are based on
// ConvertVertex_comp::Conversion values. // ConvertVertex_comp::Conversion values.
ASSERT(!destIsSint || srcIsSint); // If destination is sint, src must be sint too ASSERT(!destIsSint || srcIsSint); // If destination is sint, src must be sint too
ASSERT(!destIsUint || srcIsUint); // If destination is uint, src must be uint too ASSERT(!destIsUint || srcIsUint); // If destination is uint, src must be uint too
ASSERT(!srcIsFixed || destIsFloat); // If source is fixed, dest must be float ASSERT(!srcIsFixed || destIsFloat); // If source is fixed, dest must be float
ASSERT(srcIsHalfFloat == destIsHalfFloat); // Both src and dest are half float or neither ASSERT(srcIsHalfFloat == destIsHalfFloat); // Both src and dest are half float or neither
// One of each bool set must be true // One of each bool set must be true
...@@ -508,6 +508,24 @@ angle::Result UtilsVk::ensureConvertIndexResourcesInitialized(ContextVk *context ...@@ -508,6 +508,24 @@ angle::Result UtilsVk::ensureConvertIndexResourcesInitialized(ContextVk *context
ArraySize(setSizes), sizeof(ConvertIndexShaderParams)); ArraySize(setSizes), sizeof(ConvertIndexShaderParams));
} }
angle::Result UtilsVk::ensureConvertIndexIndirectResourcesInitialized(ContextVk *contextVk)
{
if (mPipelineLayouts[Function::ConvertIndexIndirectBuffer].valid())
{
return angle::Result::Continue;
}
VkDescriptorPoolSize setSizes[3] = {
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // source index buffer
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dest index buffer
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // cmd buffer
};
return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectBuffer, setSizes,
ArraySize(setSizes),
sizeof(ConvertIndexIndirectShaderParams));
}
angle::Result UtilsVk::ensureConvertVertexResourcesInitialized(ContextVk *contextVk) angle::Result UtilsVk::ensureConvertVertexResourcesInitialized(ContextVk *contextVk)
{ {
if (mPipelineLayouts[Function::ConvertVertexBuffer].valid()) if (mPipelineLayouts[Function::ConvertVertexBuffer].valid())
...@@ -839,6 +857,71 @@ angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk, ...@@ -839,6 +857,71 @@ angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk,
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk,
vk::BufferHelper *cmdBuffer,
vk::BufferHelper *dest,
vk::BufferHelper *src,
const ConvertIndexIndirectParameters &params)
{
ANGLE_TRY(ensureConvertIndexIndirectResourcesInitialized(contextVk));
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(dest->recordCommands(contextVk, &commandBuffer));
// Tell src we are going to read from it and dest it's being written to.
src->onReadByBuffer(contextVk, dest, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT);
cmdBuffer->onReadByBuffer(contextVk, dest, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_SHADER_WRITE_BIT);
VkDescriptorSet descriptorSet;
vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndexIndirectBuffer,
&descriptorPoolBinding, &descriptorSet));
std::array<VkDescriptorBufferInfo, 3> buffers = {{
{dest->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
{src->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
{cmdBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
}};
VkWriteDescriptorSet writeInfo = {};
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.dstSet = descriptorSet;
writeInfo.dstBinding = kConvertIndexDestinationBinding;
writeInfo.descriptorCount = 3;
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
writeInfo.pBufferInfo = buffers.data();
vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
ConvertIndexIndirectShaderParams shaderParams = {params.indirectBufferOffset >> 2,
params.dstOffset >> 2, params.maxIndex, 0};
uint32_t flags = vk::InternalShader::ConvertIndex_comp::kIsIndirect;
if (contextVk->getState().isPrimitiveRestartEnabled())
{
flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
}
vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexIndirectBuffer, shader, nullptr,
&mConvertIndexPrograms[flags], nullptr, descriptorSet, &shaderParams,
sizeof(ConvertIndexIndirectShaderParams), commandBuffer));
constexpr uint32_t kInvocationsPerGroup = 64;
constexpr uint32_t kInvocationsPerIndex = 2;
const uint32_t kIndexCount = params.maxIndex;
const uint32_t kGroupCount =
UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
commandBuffer->dispatch(kGroupCount, 1, 1);
descriptorPoolBinding.reset();
return angle::Result::Continue;
}
angle::Result UtilsVk::convertVertexBuffer(ContextVk *contextVk, angle::Result UtilsVk::convertVertexBuffer(ContextVk *contextVk,
vk::BufferHelper *dest, vk::BufferHelper *dest,
vk::BufferHelper *src, vk::BufferHelper *src,
......
...@@ -54,6 +54,13 @@ class UtilsVk : angle::NonCopyable ...@@ -54,6 +54,13 @@ class UtilsVk : angle::NonCopyable
uint32_t maxIndex = 0; uint32_t maxIndex = 0;
}; };
struct ConvertIndexIndirectParameters
{
uint32_t indirectBufferOffset = 0;
uint32_t dstOffset = 0;
uint32_t maxIndex = 0;
};
struct ConvertVertexParameters struct ConvertVertexParameters
{ {
size_t vertexCount; size_t vertexCount;
...@@ -137,6 +144,12 @@ class UtilsVk : angle::NonCopyable ...@@ -137,6 +144,12 @@ class UtilsVk : angle::NonCopyable
vk::BufferHelper *dest, vk::BufferHelper *dest,
vk::BufferHelper *src, vk::BufferHelper *src,
const ConvertIndexParameters &params); const ConvertIndexParameters &params);
angle::Result convertIndexIndirectBuffer(ContextVk *contextVk,
vk::BufferHelper *cmdBufferVk,
vk::BufferHelper *dest,
vk::BufferHelper *src,
const ConvertIndexIndirectParameters &params);
angle::Result convertVertexBuffer(ContextVk *contextVk, angle::Result convertVertexBuffer(ContextVk *contextVk,
vk::BufferHelper *dest, vk::BufferHelper *dest,
vk::BufferHelper *src, vk::BufferHelper *src,
...@@ -210,6 +223,14 @@ class UtilsVk : angle::NonCopyable ...@@ -210,6 +223,14 @@ class UtilsVk : angle::NonCopyable
uint32_t _padding = 0; uint32_t _padding = 0;
}; };
struct ConvertIndexIndirectShaderParams
{
uint32_t cmdOffsetDiv4 = 0;
uint32_t dstOffsetDiv4 = 0;
uint32_t maxIndex = 0;
uint32_t _padding = 0;
};
struct ConvertVertexShaderParams struct ConvertVertexShaderParams
{ {
ConvertVertexShaderParams(); ConvertVertexShaderParams();
...@@ -310,9 +331,10 @@ class UtilsVk : angle::NonCopyable ...@@ -310,9 +331,10 @@ class UtilsVk : angle::NonCopyable
BlitResolveStencilNoExport = 6, BlitResolveStencilNoExport = 6,
OverlayCull = 7, OverlayCull = 7,
OverlayDraw = 8, OverlayDraw = 8,
ConvertIndexIndirectBuffer = 9,
InvalidEnum = 9, InvalidEnum = 10,
EnumCount = 9, EnumCount = 10,
}; };
// Common function that creates the pipeline for the specified function, binds it and prepares // Common function that creates the pipeline for the specified function, binds it and prepares
...@@ -346,6 +368,7 @@ class UtilsVk : angle::NonCopyable ...@@ -346,6 +368,7 @@ class UtilsVk : angle::NonCopyable
// appropriate parameters. // appropriate parameters.
angle::Result ensureBufferClearResourcesInitialized(ContextVk *contextVk); angle::Result ensureBufferClearResourcesInitialized(ContextVk *contextVk);
angle::Result ensureConvertIndexResourcesInitialized(ContextVk *contextVk); angle::Result ensureConvertIndexResourcesInitialized(ContextVk *contextVk);
angle::Result ensureConvertIndexIndirectResourcesInitialized(ContextVk *contextVk);
angle::Result ensureConvertVertexResourcesInitialized(ContextVk *contextVk); angle::Result ensureConvertVertexResourcesInitialized(ContextVk *contextVk);
angle::Result ensureImageClearResourcesInitialized(ContextVk *contextVk); angle::Result ensureImageClearResourcesInitialized(ContextVk *contextVk);
angle::Result ensureImageCopyResourcesInitialized(ContextVk *contextVk); angle::Result ensureImageCopyResourcesInitialized(ContextVk *contextVk);
......
...@@ -163,6 +163,35 @@ angle::Result VertexArrayVk::convertIndexBufferGPU(ContextVk *contextVk, ...@@ -163,6 +163,35 @@ angle::Result VertexArrayVk::convertIndexBufferGPU(ContextVk *contextVk,
return contextVk->getUtils().convertIndexBuffer(contextVk, dest, src, params); return contextVk->getUtils().convertIndexBuffer(contextVk, dest, src, params);
} }
angle::Result VertexArrayVk::convertIndexBufferIndirectGPU(ContextVk *contextVk,
BufferVk *cmdBufferVk,
BufferVk *indexBufferVk,
const void *offset)
{
intptr_t indirectBufferOffset = reinterpret_cast<intptr_t>(offset);
size_t srcDataSize = static_cast<size_t>(indexBufferVk->getSize());
mTranslatedByteIndexData.releaseInFlightBuffers(contextVk);
ANGLE_TRY(mTranslatedByteIndexData.allocate(contextVk, sizeof(GLushort) * srcDataSize, nullptr,
nullptr, &mCurrentElementArrayBufferOffset,
nullptr));
mCurrentElementArrayBuffer = mTranslatedByteIndexData.getCurrentBuffer();
vk::BufferHelper *dest = mTranslatedByteIndexData.getCurrentBuffer();
vk::BufferHelper *src = &indexBufferVk->getBuffer();
// Copy relevant section of the source into destination at allocated offset. Note that the
// offset returned by allocate() above is in bytes. As is the indices offset pointer.
UtilsVk::ConvertIndexIndirectParameters params = {};
params.indirectBufferOffset = static_cast<uint32_t>(indirectBufferOffset);
params.dstOffset = static_cast<uint32_t>(mCurrentElementArrayBufferOffset);
params.maxIndex = static_cast<uint32_t>(indexBufferVk->getSize());
return contextVk->getUtils().convertIndexIndirectBuffer(contextVk, &cmdBufferVk->getBuffer(),
dest, src, params);
}
angle::Result VertexArrayVk::convertIndexBufferCPU(ContextVk *contextVk, angle::Result VertexArrayVk::convertIndexBufferCPU(ContextVk *contextVk,
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
size_t indexCount, size_t indexCount,
...@@ -486,7 +515,7 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -486,7 +515,7 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
} }
else else
{ {
vk::BufferHelper &bufferHelper = bufferVk->getBuffer(); vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
mCurrentArrayBuffers[attribIndex] = &bufferHelper; mCurrentArrayBuffers[attribIndex] = &bufferHelper;
mCurrentArrayBufferHandles[attribIndex] = bufferHelper.getBuffer().getHandle(); mCurrentArrayBufferHandles[attribIndex] = bufferHelper.getBuffer().getHandle();
mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset(); mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
......
...@@ -82,6 +82,11 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -82,6 +82,11 @@ class VertexArrayVk : public VertexArrayImpl
BufferVk *bufferVk, BufferVk *bufferVk,
const void *indices); const void *indices);
angle::Result convertIndexBufferIndirectGPU(ContextVk *contextVk,
BufferVk *cmdBufferVk,
BufferVk *indexBufferVk,
const void *indices);
angle::Result convertIndexBufferCPU(ContextVk *contextVk, angle::Result convertIndexBufferCPU(ContextVk *contextVk,
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
size_t indexCount, size_t indexCount,
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
// - Flags: // - Flags:
// * IsPrimitiveRestartEnabled: enables conversion from 0xFF to 0xFFFF, // * IsPrimitiveRestartEnabled: enables conversion from 0xFF to 0xFFFF,
// the restart indices for 8-bit and 16-bit indices. // the restart indices for 8-bit and 16-bit indices.
// * IsIndirect: Use indirect buffer for index info
// //
#version 450 core #version 450 core
...@@ -28,6 +29,28 @@ layout (set = 0, binding = 1) readonly buffer src ...@@ -28,6 +29,28 @@ layout (set = 0, binding = 1) readonly buffer src
uint srcData[]; uint srcData[];
}; };
#if IsIndirect
layout (set = 0, binding = 2) readonly buffer cmd
{
// Shader invocations read from the cmdData buffer to determine what indices to convert
// The command data starts at offset cmdOffsetDiv4 of the cmdData buffer.
uint cmdData[];
};
layout (push_constant) uniform PushConstants
{
// Read offset in bytes into the cmdData array, divided by four.
uint cmdOffsetDiv4;
// Write offset in bytes into the dstData array, divided by four.
uint dstOffsetDiv4;
// Maximum size of the read buffer. The highest index value we will convert.
uint maxIndex;
// Not used in the shader. Kept to pad "PushConstants" to the size of a vec4.
uint _padding;
};
#else
layout (push_constant) uniform PushConstants layout (push_constant) uniform PushConstants
{ {
// Read offset in bytes into the srcData array. // Read offset in bytes into the srcData array.
...@@ -39,10 +62,15 @@ layout (push_constant) uniform PushConstants ...@@ -39,10 +62,15 @@ layout (push_constant) uniform PushConstants
// Not used in the shader. Kept to pad "PushConstants" to the size of a vec4. // Not used in the shader. Kept to pad "PushConstants" to the size of a vec4.
uint _padding; uint _padding;
}; };
#endif
uint PullIndex(uint index) uint PullIndex(uint index)
{ {
#if IsIndirect
uint srcIndex = index;
#else
uint srcIndex = index + srcOffset; uint srcIndex = index + srcOffset;
#endif
uint srcBlock = srcData[srcIndex >> 2]; uint srcBlock = srcData[srcIndex >> 2];
uint srcComponent = (srcIndex & 3); uint srcComponent = (srcIndex & 3);
...@@ -64,21 +92,37 @@ void PackIndexValue(uint srcValue, uint indexIndex, inout uint dstValue) ...@@ -64,21 +92,37 @@ void PackIndexValue(uint srcValue, uint indexIndex, inout uint dstValue)
void main() void main()
{ {
// The element index is simply the invocation ID times two. #if IsIndirect
uint index = (gl_GlobalInvocationID.x << 1); uint indexCount = cmdData[cmdOffsetDiv4];
uint firstIndex = cmdData[cmdOffsetDiv4 + 2];
uint endIndex = firstIndex + indexCount;
#else
uint firstIndex = 0;
uint endIndex = firstIndex + maxIndex;
#endif
// The element index is invocation ID times two plus
// the firstIndex / 2.
// This way the first indexCount/2 invocations will transform
// the data and any additional invocations will be a no-op
uint index = ((gl_GlobalInvocationID.x + (firstIndex >> 1)) << 1);
// Don't write anything to dest if we're entirely past the end of the buffer. // Don't write anything to dest if we're entirely past the end of the buffer.
// We assume buffer size is uint-aligned. // We assume buffer size is uint-aligned.
if (index >= maxIndex) if (index >= endIndex)
return; return;
uint dstValue = 0; uint dstValue = 0;
uint srcValue = PullIndex(index); // Skip packing the first index if we're before the first element.
PackIndexValue(srcValue, 0, dstValue); if (index >= firstIndex)
{
uint srcValue = PullIndex(index);
PackIndexValue(srcValue, 0, dstValue);
}
// Skip packing the second index if we're after the last element. // Skip packing the second index if we're after the last element.
if (index + 1 < maxIndex) if (index + 1 < endIndex)
{ {
uint srcValue = PullIndex(index + 1); uint srcValue = PullIndex(index + 1);
PackIndexValue(srcValue, 1, dstValue); PackIndexValue(srcValue, 1, dstValue);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
"ConvertIndex.comp.json: Build parameters for ConvertIndex.comp." "ConvertIndex.comp.json: Build parameters for ConvertIndex.comp."
], ],
"Flags": [ "Flags": [
"IsPrimitiveRestartEnabled" "IsPrimitiveRestartEnabled",
"IsIndirect"
] ]
} }
...@@ -58,6 +58,8 @@ namespace ...@@ -58,6 +58,8 @@ namespace
#include "libANGLE/renderer/vulkan/shaders/gen/BufferUtils.comp.0000000B.inc" #include "libANGLE/renderer/vulkan/shaders/gen/BufferUtils.comp.0000000B.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000000.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000000.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000001.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000001.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000002.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000003.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000000.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000000.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000001.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000001.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000002.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000002.inc"
...@@ -210,6 +212,8 @@ constexpr ShaderBlob kBufferUtils_comp_shaders[] = { ...@@ -210,6 +212,8 @@ constexpr ShaderBlob kBufferUtils_comp_shaders[] = {
constexpr ShaderBlob kConvertIndex_comp_shaders[] = { constexpr ShaderBlob kConvertIndex_comp_shaders[] = {
{kConvertIndex_comp_00000000, sizeof(kConvertIndex_comp_00000000)}, {kConvertIndex_comp_00000000, sizeof(kConvertIndex_comp_00000000)},
{kConvertIndex_comp_00000001, sizeof(kConvertIndex_comp_00000001)}, {kConvertIndex_comp_00000001, sizeof(kConvertIndex_comp_00000001)},
{kConvertIndex_comp_00000002, sizeof(kConvertIndex_comp_00000002)},
{kConvertIndex_comp_00000003, sizeof(kConvertIndex_comp_00000003)},
}; };
constexpr ShaderBlob kConvertVertex_comp_shaders[] = { constexpr ShaderBlob kConvertVertex_comp_shaders[] = {
{kConvertVertex_comp_00000000, sizeof(kConvertVertex_comp_00000000)}, {kConvertVertex_comp_00000000, sizeof(kConvertVertex_comp_00000000)},
......
...@@ -51,6 +51,8 @@ angle_vulkan_internal_shaders = [ ...@@ -51,6 +51,8 @@ angle_vulkan_internal_shaders = [
"src/libANGLE/renderer/vulkan/shaders/gen/BufferUtils.comp.0000000B.inc", "src/libANGLE/renderer/vulkan/shaders/gen/BufferUtils.comp.0000000B.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000000.inc", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000000.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000001.inc", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000001.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000002.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertIndex.comp.00000003.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000000.inc", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000000.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000001.inc", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000001.inc",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000002.inc", "src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000002.inc",
......
...@@ -73,8 +73,9 @@ namespace ConvertIndex_comp ...@@ -73,8 +73,9 @@ namespace ConvertIndex_comp
enum flags enum flags
{ {
kIsPrimitiveRestartEnabled = 0x00000001, kIsPrimitiveRestartEnabled = 0x00000001,
kIsIndirect = 0x00000002,
}; };
constexpr size_t kArrayLen = 0x00000002; constexpr size_t kArrayLen = 0x00000004;
} // namespace ConvertIndex_comp } // namespace ConvertIndex_comp
namespace ConvertVertex_comp namespace ConvertVertex_comp
......
...@@ -277,6 +277,10 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer> ...@@ -277,6 +277,10 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
uint32_t firstIndex, uint32_t firstIndex,
int32_t vertexOffset, int32_t vertexOffset,
uint32_t firstInstance); uint32_t firstInstance);
void drawIndexedIndirect(const Buffer &buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride);
VkResult end(); VkResult end();
void endQuery(VkQueryPool queryPool, uint32_t query); void endQuery(VkQueryPool queryPool, uint32_t query);
...@@ -966,6 +970,15 @@ ANGLE_INLINE void CommandBuffer::drawIndexedInstancedBaseVertexBaseInstance(uint ...@@ -966,6 +970,15 @@ ANGLE_INLINE void CommandBuffer::drawIndexedInstancedBaseVertexBaseInstance(uint
vkCmdDrawIndexed(mHandle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); vkCmdDrawIndexed(mHandle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
} }
ANGLE_INLINE void CommandBuffer::drawIndexedIndirect(const Buffer &buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride)
{
ASSERT(valid());
vkCmdDrawIndexedIndirect(mHandle, buffer.getHandle(), offset, drawCount, stride);
}
ANGLE_INLINE void CommandBuffer::dispatch(uint32_t groupCountX, ANGLE_INLINE void CommandBuffer::dispatch(uint32_t groupCountX,
uint32_t groupCountY, uint32_t groupCountY,
uint32_t groupCountZ) uint32_t groupCountZ)
......
...@@ -635,11 +635,7 @@ ...@@ -635,11 +635,7 @@
// Indirect draw: // Indirect draw:
3564 VULKAN : dEQP-GLES31.functional.draw_indirect.draw_arrays_indirect.line_loop.* = SKIP 3564 VULKAN : dEQP-GLES31.functional.draw_indirect.draw_arrays_indirect.line_loop.* = SKIP
3564 VULKAN : dEQP-GLES31.functional.draw_indirect.draw_elements_indirect.* = SKIP 3564 VULKAN : dEQP-GLES31.functional.draw_indirect.draw_elements_indirect.line_loop.* = SKIP
3564 VULKAN : dEQP-GLES31.functional.draw_indirect.instancing.draw_elements* = SKIP
3564 VULKAN : dEQP-GLES31.functional.draw_indirect.compute_interop.separate.drawelements* = SKIP
3564 VULKAN : dEQP-GLES31.functional.draw_indirect.compute_interop.combined.drawelements* = SKIP
3564 VULKAN : dEQP-GLES31.functional.draw_indirect.compute_interop.large.drawelements* = SKIP
3564 VULKAN : dEQP-GLES31.functional.draw_indirect.random.* = SKIP 3564 VULKAN : dEQP-GLES31.functional.draw_indirect.random.* = SKIP
// Tessellation geometry interaction: // Tessellation geometry interaction:
......
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