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:
parent
bf4465f5a2
commit
f74071ac0a
@ -37,6 +37,7 @@ namespace dxvk {
|
||||
struct D3D11CmdDrawIndirectData : public D3D11CmdData {
|
||||
uint32_t offset;
|
||||
uint32_t count;
|
||||
uint32_t stride;
|
||||
};
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user