1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-18 20:52:10 +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 {
uint32_t offset;
uint32_t count;
uint32_t stride;
};
}

View File

@ -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<D3D11CmdDrawIndirectData*>(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<D3D11CmdDrawIndirectData>(
[] (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<D3D11CmdDrawIndirectData*>(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<D3D11CmdDrawIndirectData>(
[] (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;
}
}

View File

@ -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<typename Cmd>
void EmitCs(Cmd&& command) {
m_cmdData = nullptr;