1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-27 04:54:15 +01:00

[dxvk] Unroll merged indirect draws as necessary

This commit is contained in:
Philip Rebohle 2025-02-19 19:09:47 +01:00 committed by Philip Rebohle
parent 1d8fb818fc
commit a135e01f89
4 changed files with 72 additions and 31 deletions

View File

@ -1121,7 +1121,7 @@ namespace dxvk {
} else { } else {
cmdData = EmitCsCmd<D3D11CmdDrawIndirectData>( cmdData = EmitCsCmd<D3D11CmdDrawIndirectData>(
[] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) { [] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) {
ctx->drawIndexedIndirect(data->offset, data->count, data->stride); ctx->drawIndexedIndirect(data->offset, data->count, data->stride, true);
}); });
cmdData->type = D3D11CmdType::DrawIndirectIndexed; cmdData->type = D3D11CmdType::DrawIndirectIndexed;
@ -1156,7 +1156,7 @@ namespace dxvk {
} else { } else {
cmdData = EmitCsCmd<D3D11CmdDrawIndirectData>( cmdData = EmitCsCmd<D3D11CmdDrawIndirectData>(
[] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) { [] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) {
ctx->drawIndirect(data->offset, data->count, data->stride); ctx->drawIndirect(data->offset, data->count, data->stride, true);
}); });
cmdData->type = D3D11CmdType::DrawIndirect; cmdData->type = D3D11CmdType::DrawIndirect;

View File

@ -53,7 +53,7 @@ namespace dxvk {
cOffset = ByteOffsetForArgs, cOffset = ByteOffsetForArgs,
cStride = ByteStrideForArgs cStride = ByteStrideForArgs
] (DxvkContext* ctx) { ] (DxvkContext* ctx) {
ctx->drawIndirect(cOffset, cCount, cStride); ctx->drawIndirect(cOffset, cCount, cStride, false);
}); });
} }
@ -72,7 +72,7 @@ namespace dxvk {
cOffset = ByteOffsetForArgs, cOffset = ByteOffsetForArgs,
cStride = ByteStrideForArgs cStride = ByteStrideForArgs
] (DxvkContext* ctx) { ] (DxvkContext* ctx) {
ctx->drawIndexedIndirect(cOffset, cCount, cStride); ctx->drawIndexedIndirect(cOffset, cCount, cStride, false);
}); });
} }

View File

@ -937,18 +937,9 @@ namespace dxvk {
void DxvkContext::drawIndirect( void DxvkContext::drawIndirect(
VkDeviceSize offset, VkDeviceSize offset,
uint32_t count, uint32_t count,
uint32_t stride) { uint32_t stride,
if (this->commitGraphicsState<false, true>()) { bool unroll) {
auto descriptor = m_state.id.argBuffer.getDescriptor(); drawIndirectGeneric<false>(offset, count, stride, unroll);
m_cmd->cmdDrawIndirect(
descriptor.buffer.buffer,
descriptor.buffer.offset + offset,
count, stride);
if (unlikely(m_state.id.argBuffer.buffer()->hasGfxStores()))
accessDrawBuffer(offset, count, stride, sizeof(VkDrawIndirectCommand));
}
} }
@ -995,18 +986,9 @@ namespace dxvk {
void DxvkContext::drawIndexedIndirect( void DxvkContext::drawIndexedIndirect(
VkDeviceSize offset, VkDeviceSize offset,
uint32_t count, uint32_t count,
uint32_t stride) { uint32_t stride,
if (this->commitGraphicsState<true, true>()) { bool unroll) {
auto descriptor = m_state.id.argBuffer.getDescriptor(); drawIndirectGeneric<true>(offset, count, stride, unroll);
m_cmd->cmdDrawIndexedIndirect(
descriptor.buffer.buffer,
descriptor.buffer.offset + offset,
count, stride);
if (unlikely(m_state.id.argBuffer.buffer()->hasGfxStores()))
accessDrawBuffer(offset, count, stride, sizeof(VkDrawIndexedIndirectCommand));
}
} }
@ -1739,6 +1721,52 @@ namespace dxvk {
} }
template<bool Indexed>
void DxvkContext::drawIndirectGeneric(
VkDeviceSize offset,
uint32_t count,
uint32_t stride,
bool unroll) {
if (this->commitGraphicsState<Indexed, true>()) {
auto descriptor = m_state.id.argBuffer.getDescriptor();
if (unroll) {
// Need to do this check after initially setting up the pipeline
unroll = m_state.gp.flags.test(DxvkGraphicsPipelineFlag::UnrollMergedDraws)
&& !m_barrierControl.test(DxvkBarrierControl::GraphicsAllowReadWriteOverlap);
}
// If draws are merged but the pipeline has order-dependent stores, submit
// one draw at a time as well as barriers in between. Otherwise, keep the
// draws merged.
uint32_t step = unroll ? 1u : count;
for (uint32_t i = 0; i < count; i += step) {
if (unlikely(i)) {
// Insert barrier after the first iteration
this->commitGraphicsState<Indexed, true>();
}
if (Indexed) {
m_cmd->cmdDrawIndexedIndirect(descriptor.buffer.buffer,
descriptor.buffer.offset + offset, step, stride);
} else {
m_cmd->cmdDrawIndirect(descriptor.buffer.buffer,
descriptor.buffer.offset + offset, step, stride);
}
if (unlikely(m_state.id.argBuffer.buffer()->hasGfxStores())) {
accessDrawBuffer(offset, step, stride, Indexed
? sizeof(VkDrawIndexedIndirectCommand)
: sizeof(VkDrawIndirectCommand));
}
offset += step * stride;
}
}
}
void DxvkContext::resolveImage( void DxvkContext::resolveImage(
const Rc<DxvkImage>& dstImage, const Rc<DxvkImage>& dstImage,
const Rc<DxvkImage>& srcImage, const Rc<DxvkImage>& srcImage,

View File

@ -763,11 +763,14 @@ namespace dxvk {
* \param [in] offset Draw buffer offset * \param [in] offset Draw buffer offset
* \param [in] count Number of draws * \param [in] count Number of draws
* \param [in] stride Stride between dispatch calls * \param [in] stride Stride between dispatch calls
* \param [in] unroll Whether to unroll multiple draws if
* there are any potential data dependencies between them.
*/ */
void drawIndirect( void drawIndirect(
VkDeviceSize offset, VkDeviceSize offset,
uint32_t count, uint32_t count,
uint32_t stride); uint32_t stride,
bool unroll);
/** /**
* \brief Indirect draw call * \brief Indirect draw call
@ -809,12 +812,15 @@ namespace dxvk {
* \param [in] offset Draw buffer offset * \param [in] offset Draw buffer offset
* \param [in] count Number of draws * \param [in] count Number of draws
* \param [in] stride Stride between dispatch calls * \param [in] stride Stride between dispatch calls
* \param [in] unroll Whether to unroll multiple draws if
* there are any potential data dependencies between them.
*/ */
void drawIndexedIndirect( void drawIndexedIndirect(
VkDeviceSize offset, VkDeviceSize offset,
uint32_t count, uint32_t count,
uint32_t stride); uint32_t stride,
bool unroll);
/** /**
* \brief Indirect indexed draw call * \brief Indirect indexed draw call
* *
@ -1589,6 +1595,13 @@ namespace dxvk {
const Rc<DxvkBuffer>& buffer, const Rc<DxvkBuffer>& buffer,
VkDeviceSize offset); VkDeviceSize offset);
template<bool Indexed>
void drawIndirectGeneric(
VkDeviceSize offset,
uint32_t count,
uint32_t stride,
bool unroll);
void resolveImageHw( void resolveImageHw(
const Rc<DxvkImage>& dstImage, const Rc<DxvkImage>& dstImage,
const Rc<DxvkImage>& srcImage, const Rc<DxvkImage>& srcImage,