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:
parent
bf4465f5a2
commit
f74071ac0a
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user