diff --git a/src/d3d11/d3d11_cmd.h b/src/d3d11/d3d11_cmd.h index 8a7a4f9bb..52f2f4dbc 100644 --- a/src/d3d11/d3d11_cmd.h +++ b/src/d3d11/d3d11_cmd.h @@ -37,6 +37,7 @@ namespace dxvk { struct D3D11CmdDrawIndirectData : public D3D11CmdData { uint32_t offset; uint32_t count; + uint32_t stride; }; } \ No newline at end of file diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 6349b3e38..5dcf4de3e 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -1535,24 +1535,25 @@ namespace dxvk { // If possible, batch up multiple indirect draw calls of // the same type into one single multiDrawIndirect call - constexpr VkDeviceSize stride = sizeof(VkDrawIndexedIndirectCommand); auto cmdData = static_cast(m_cmdData); - - bool useMultiDraw = cmdData && cmdData->type == D3D11CmdType::DrawIndirectIndexed - && cmdData->offset + cmdData->count * stride == AlignedByteOffsetForArgs; + auto stride = 0u; - if (useMultiDraw) { + if (cmdData && cmdData->type == D3D11CmdType::DrawIndirectIndexed) + stride = GetIndirectCommandStride(cmdData, AlignedByteOffsetForArgs, sizeof(VkDrawIndexedIndirectCommand)); + + if (stride) { cmdData->count += 1; + cmdData->stride = stride; } else { cmdData = EmitCsCmd( [] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) { - ctx->drawIndexedIndirect(data->offset, data->count, - sizeof(VkDrawIndexedIndirectCommand)); + ctx->drawIndexedIndirect(data->offset, data->count, data->stride); }); cmdData->type = D3D11CmdType::DrawIndirectIndexed; cmdData->offset = AlignedByteOffsetForArgs; cmdData->count = 1; + cmdData->stride = 0; } } @@ -1565,24 +1566,25 @@ namespace dxvk { // If possible, batch up multiple indirect draw calls of // the same type into one single multiDrawIndirect call - constexpr VkDeviceSize stride = sizeof(VkDrawIndirectCommand); auto cmdData = static_cast(m_cmdData); - - bool useMultiDraw = cmdData && cmdData->type == D3D11CmdType::DrawIndirect - && cmdData->offset + cmdData->count * stride == AlignedByteOffsetForArgs; + auto stride = 0u; - if (useMultiDraw) { + if (cmdData && cmdData->type == D3D11CmdType::DrawIndirect) + stride = GetIndirectCommandStride(cmdData, AlignedByteOffsetForArgs, sizeof(VkDrawIndirectCommand)); + + if (stride) { cmdData->count += 1; + cmdData->stride = stride; } else { cmdData = EmitCsCmd( [] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) { - ctx->drawIndirect(data->offset, data->count, - sizeof(VkDrawIndirectCommand)); + ctx->drawIndirect(data->offset, data->count, data->stride); }); cmdData->type = D3D11CmdType::DrawIndirect; cmdData->offset = AlignedByteOffsetForArgs; cmdData->count = 1; + cmdData->stride = 0; } } diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index baf0e6272..8c029d867 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -917,6 +917,14 @@ namespace dxvk { return pShader != nullptr ? pShader->GetCommonShader() : nullptr; } + static uint32_t GetIndirectCommandStride(const D3D11CmdDrawIndirectData* cmdData, uint32_t offset, uint32_t minStride) { + if (likely(cmdData->stride)) + return cmdData->offset + cmdData->count * cmdData->stride == offset ? cmdData->stride : 0; + + uint32_t stride = offset - cmdData->offset; + return stride >= minStride && stride <= 32 ? stride : 0; + } + template void EmitCs(Cmd&& command) { m_cmdData = nullptr;