1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-31 14:52:11 +01:00

[d3d11] Support different strides for merged indirect draws

Trine 4 uses a stride of 32 bytes. Detecting the stride dynamically
allows us to merge a couple of draws in this game, and others which
do not tightly pack their draw parameter buffers.
This commit is contained in:
Philip Rebohle 2020-11-21 05:39:05 +01:00
parent bf4465f5a2
commit f74071ac0a
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 25 additions and 14 deletions

View File

@ -37,6 +37,7 @@ namespace dxvk {
struct D3D11CmdDrawIndirectData : public D3D11CmdData { struct D3D11CmdDrawIndirectData : public D3D11CmdData {
uint32_t offset; uint32_t offset;
uint32_t count; uint32_t count;
uint32_t stride;
}; };
} }

View File

@ -1535,24 +1535,25 @@ namespace dxvk {
// If possible, batch up multiple indirect draw calls of // If possible, batch up multiple indirect draw calls of
// the same type into one single multiDrawIndirect call // the same type into one single multiDrawIndirect call
constexpr VkDeviceSize stride = sizeof(VkDrawIndexedIndirectCommand);
auto cmdData = static_cast<D3D11CmdDrawIndirectData*>(m_cmdData); auto cmdData = static_cast<D3D11CmdDrawIndirectData*>(m_cmdData);
auto stride = 0u;
bool useMultiDraw = cmdData && cmdData->type == D3D11CmdType::DrawIndirectIndexed if (cmdData && cmdData->type == D3D11CmdType::DrawIndirectIndexed)
&& cmdData->offset + cmdData->count * stride == AlignedByteOffsetForArgs; stride = GetIndirectCommandStride(cmdData, AlignedByteOffsetForArgs, sizeof(VkDrawIndexedIndirectCommand));
if (useMultiDraw) { if (stride) {
cmdData->count += 1; cmdData->count += 1;
cmdData->stride = stride;
} else { } else {
cmdData = EmitCsCmd<D3D11CmdDrawIndirectData>( cmdData = EmitCsCmd<D3D11CmdDrawIndirectData>(
[] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) { [] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) {
ctx->drawIndexedIndirect(data->offset, data->count, ctx->drawIndexedIndirect(data->offset, data->count, data->stride);
sizeof(VkDrawIndexedIndirectCommand));
}); });
cmdData->type = D3D11CmdType::DrawIndirectIndexed; cmdData->type = D3D11CmdType::DrawIndirectIndexed;
cmdData->offset = AlignedByteOffsetForArgs; cmdData->offset = AlignedByteOffsetForArgs;
cmdData->count = 1; cmdData->count = 1;
cmdData->stride = 0;
} }
} }
@ -1565,24 +1566,25 @@ namespace dxvk {
// If possible, batch up multiple indirect draw calls of // If possible, batch up multiple indirect draw calls of
// the same type into one single multiDrawIndirect call // the same type into one single multiDrawIndirect call
constexpr VkDeviceSize stride = sizeof(VkDrawIndirectCommand);
auto cmdData = static_cast<D3D11CmdDrawIndirectData*>(m_cmdData); auto cmdData = static_cast<D3D11CmdDrawIndirectData*>(m_cmdData);
auto stride = 0u;
bool useMultiDraw = cmdData && cmdData->type == D3D11CmdType::DrawIndirect if (cmdData && cmdData->type == D3D11CmdType::DrawIndirect)
&& cmdData->offset + cmdData->count * stride == AlignedByteOffsetForArgs; stride = GetIndirectCommandStride(cmdData, AlignedByteOffsetForArgs, sizeof(VkDrawIndirectCommand));
if (useMultiDraw) { if (stride) {
cmdData->count += 1; cmdData->count += 1;
cmdData->stride = stride;
} else { } else {
cmdData = EmitCsCmd<D3D11CmdDrawIndirectData>( cmdData = EmitCsCmd<D3D11CmdDrawIndirectData>(
[] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) { [] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) {
ctx->drawIndirect(data->offset, data->count, ctx->drawIndirect(data->offset, data->count, data->stride);
sizeof(VkDrawIndirectCommand));
}); });
cmdData->type = D3D11CmdType::DrawIndirect; cmdData->type = D3D11CmdType::DrawIndirect;
cmdData->offset = AlignedByteOffsetForArgs; cmdData->offset = AlignedByteOffsetForArgs;
cmdData->count = 1; cmdData->count = 1;
cmdData->stride = 0;
} }
} }

View File

@ -917,6 +917,14 @@ namespace dxvk {
return pShader != nullptr ? pShader->GetCommonShader() : nullptr; 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<typename Cmd> template<typename Cmd>
void EmitCs(Cmd&& command) { void EmitCs(Cmd&& command) {
m_cmdData = nullptr; m_cmdData = nullptr;