From b540c783557808f778f8afd332b33aa81f7e5ec6 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 9 Oct 2020 21:31:33 +0200 Subject: [PATCH] rhi: gl: d3d: Reduce the size of the Command struct Copied by value so the size matters. Change-Id: I17eae99212801a4fb390a0e298b361123644d17d Reviewed-by: Andy Nichols --- src/gui/rhi/qrhi.cpp | 6 ++++++ src/gui/rhi/qrhid3d11.cpp | 32 ++++++++++++++++++-------------- src/gui/rhi/qrhid3d11_p_p.h | 12 +++++++----- src/gui/rhi/qrhigles2.cpp | 4 ++-- src/gui/rhi/qrhigles2_p_p.h | 5 +++-- 5 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index ead50628f6a..c67659478a5 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -5275,6 +5275,9 @@ void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps) \note All offsets in \a dynamicOffsets must be byte aligned to the value returned from QRhi::ubufAlignment(). + \note Some backends may limit the number of supported dynamic offsets. + Avoid using a \a dynamicOffsetCount larger than 8. + \note QRhi will optimize out unnecessary invocations within a pass (taking the conditions described above into account), so therefore overoptimizing to avoid calls to this function is not necessary on the applications' side. @@ -5303,6 +5306,9 @@ void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb, in \a bindings. Each element in \a bindings specifies a QRhiBuffer and an offset. + \note Some backends may limit the number of vertex buffer bindings. Avoid + using a \a bindingCount larger than 8. + Superfluous vertex input and index changes in the same pass are ignored automatically with most backends and therefore applications do not need to overoptimize to avoid calls to this function. diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index 7d8339252b6..dc4f6b1f01d 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -788,7 +788,7 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && hasDynamicOffsetInSrb; cmd.args.bindShaderResources.dynamicOffsetCount = 0; if (hasDynamicOffsetInSrb) { - if (dynamicOffsetCount < QD3D11CommandBuffer::Command::MAX_UBUF_BINDINGS) { + if (dynamicOffsetCount < QD3D11CommandBuffer::Command::MAX_DYNAMIC_OFFSET_COUNT) { cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount; uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs; for (int i = 0; i < dynamicOffsetCount; ++i) { @@ -801,7 +801,7 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind } } else { qWarning("Too many dynamic offsets (%d, max is %d)", - dynamicOffsetCount, QD3D11CommandBuffer::Command::MAX_UBUF_BINDINGS); + dynamicOffsetCount, QD3D11CommandBuffer::Command::MAX_DYNAMIC_OFFSET_COUNT); } } @@ -837,6 +837,11 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb, QD3D11CommandBuffer::Command cmd; cmd.cmd = QD3D11CommandBuffer::Command::BindVertexBuffers; cmd.args.bindVertexBuffers.startSlot = startBinding; + if (bindingCount > QD3D11CommandBuffer::Command::MAX_VERTEX_BUFFER_BINDING_COUNT) { + qWarning("Too many vertex buffer bindings (%d, max is %d)", + bindingCount, QD3D11CommandBuffer::Command::MAX_VERTEX_BUFFER_BINDING_COUNT); + bindingCount = QD3D11CommandBuffer::Command::MAX_VERTEX_BUFFER_BINDING_COUNT; + } cmd.args.bindVertexBuffers.slotCount = bindingCount; QD3D11GraphicsPipeline *psD = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline); const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout); @@ -2173,7 +2178,7 @@ void QRhiD3D11::executeBufferHostWrites(QD3D11Buffer *bufD) } } -static void applyDynamicOffsets(QVarLengthArray *offsets, +static void applyDynamicOffsets(UINT *offsets, int batchIndex, QRhiBatchedBindings *originalBindings, QRhiBatchedBindings *staticOffsets, @@ -2182,15 +2187,15 @@ static void applyDynamicOffsets(QVarLengthArray *offsets, const int count = staticOffsets->batches[batchIndex].resources.count(); // Make a copy of the offset list, the entries that have no corresponding // dynamic offset will continue to use the existing offset value. - *offsets = staticOffsets->batches[batchIndex].resources; for (int b = 0; b < count; ++b) { + offsets[b] = staticOffsets->batches[batchIndex].resources[b]; for (int di = 0; di < dynOfsPairCount; ++di) { const uint binding = dynOfsPairs[2 * di]; // binding is the SPIR-V style binding point here, nothing to do // with the native one. if (binding == originalBindings->batches[batchIndex].resources[b]) { const uint offsetInConstants = dynOfsPairs[2 * di + 1]; - (*offsets)[b] = offsetInConstants; + offsets[b] = offsetInConstants; break; } } @@ -2264,6 +2269,8 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD, } } + UINT offsets[QD3D11CommandBuffer::Command::MAX_DYNAMIC_OFFSET_COUNT]; + for (int i = 0, ie = srbD->vsubufs.batches.count(); i != ie; ++i) { const uint count = clampedResourceCount(srbD->vsubufs.batches[i].startBinding, srbD->vsubufs.batches[i].resources.count(), @@ -2277,13 +2284,12 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD, srbD->vsubufoffsets.batches[i].resources.constData(), srbD->vsubufsizes.batches[i].resources.constData()); } else { - QVarLengthArray offsets; - applyDynamicOffsets(&offsets, i, &srbD->vsubuforigbindings, &srbD->vsubufoffsets, + applyDynamicOffsets(offsets, i, &srbD->vsubuforigbindings, &srbD->vsubufoffsets, dynOfsPairs, dynOfsPairCount); context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding, count, srbD->vsubufs.batches[i].resources.constData(), - offsets.constData(), + offsets, srbD->vsubufsizes.batches[i].resources.constData()); } } @@ -2302,13 +2308,12 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD, srbD->fsubufoffsets.batches[i].resources.constData(), srbD->fsubufsizes.batches[i].resources.constData()); } else { - QVarLengthArray offsets; - applyDynamicOffsets(&offsets, i, &srbD->fsubuforigbindings, &srbD->fsubufoffsets, + applyDynamicOffsets(offsets, i, &srbD->fsubuforigbindings, &srbD->fsubufoffsets, dynOfsPairs, dynOfsPairCount); context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding, count, srbD->fsubufs.batches[i].resources.constData(), - offsets.constData(), + offsets, srbD->fsubufsizes.batches[i].resources.constData()); } } @@ -2327,13 +2332,12 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD, srbD->csubufoffsets.batches[i].resources.constData(), srbD->csubufsizes.batches[i].resources.constData()); } else { - QVarLengthArray offsets; - applyDynamicOffsets(&offsets, i, &srbD->csubuforigbindings, &srbD->csubufoffsets, + applyDynamicOffsets(offsets, i, &srbD->csubuforigbindings, &srbD->csubufoffsets, dynOfsPairs, dynOfsPairCount); context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding, count, srbD->csubufs.batches[i].resources.constData(), - offsets.constData(), + offsets, srbD->csubufsizes.batches[i].resources.constData()); } } diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h index 4de193530aa..b2ff0f77f79 100644 --- a/src/gui/rhi/qrhid3d11_p_p.h +++ b/src/gui/rhi/qrhid3d11_p_p.h @@ -345,7 +345,9 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer enum ClearFlag { Color = 1, Depth = 2, Stencil = 4 }; Cmd cmd; - static const int MAX_UBUF_BINDINGS = 32; // should be D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT but 128 is a waste of space for our purposes + // these must be kept at a reasonably low value otherwise sizeof Command explodes + static const int MAX_DYNAMIC_OFFSET_COUNT = 8; + static const int MAX_VERTEX_BUFFER_BINDING_COUNT = 8; // QRhi*/QD3D11* references should be kept at minimum (so no // QRhiTexture/Buffer/etc. pointers). @@ -370,9 +372,9 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer struct { int startSlot; int slotCount; - ID3D11Buffer *buffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; - UINT offsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; - UINT strides[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; + ID3D11Buffer *buffers[MAX_VERTEX_BUFFER_BINDING_COUNT]; + UINT offsets[MAX_VERTEX_BUFFER_BINDING_COUNT]; + UINT strides[MAX_VERTEX_BUFFER_BINDING_COUNT]; } bindVertexBuffers; struct { ID3D11Buffer *buffer; @@ -386,7 +388,7 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer QD3D11ShaderResourceBindings *srb; bool offsetOnlyChange; int dynamicOffsetCount; - uint dynamicOffsetPairs[MAX_UBUF_BINDINGS * 2]; // binding, offsetInConstants + uint dynamicOffsetPairs[MAX_DYNAMIC_OFFSET_COUNT * 2]; // binding, offsetInConstants } bindShaderResources; struct { QD3D11GraphicsPipeline *ps; diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 1ea116d78c8..63f419da94f 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -1169,7 +1169,7 @@ void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind cmd.args.bindShaderResources.srb = srb; cmd.args.bindShaderResources.dynamicOffsetCount = 0; if (hasDynamicOffsetInSrb) { - if (dynamicOffsetCount < QGles2CommandBuffer::Command::MAX_UBUF_BINDINGS) { + if (dynamicOffsetCount < QGles2CommandBuffer::Command::MAX_DYNAMIC_OFFSET_COUNT) { cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount; uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs; for (int i = 0; i < dynamicOffsetCount; ++i) { @@ -1179,7 +1179,7 @@ void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind } } else { qWarning("Too many dynamic offsets (%d, max is %d)", - dynamicOffsetCount, QGles2CommandBuffer::Command::MAX_UBUF_BINDINGS); + dynamicOffsetCount, QGles2CommandBuffer::Command::MAX_DYNAMIC_OFFSET_COUNT); } } cbD->commands.append(cmd); diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index 2023585b6b4..d037bbc4f68 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -345,7 +345,8 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer }; Cmd cmd; - static const int MAX_UBUF_BINDINGS = 32; // should be more than enough + // keep at a reasonably low value otherwise sizeof Command explodes + static const int MAX_DYNAMIC_OFFSET_COUNT = 8; // QRhi*/QGles2* references should be kept at minimum (so no // QRhiTexture/Buffer/etc. pointers). @@ -398,7 +399,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer QRhiComputePipeline *maybeComputePs; QRhiShaderResourceBindings *srb; int dynamicOffsetCount; - uint dynamicOffsetPairs[MAX_UBUF_BINDINGS * 2]; // binding, offset + uint dynamicOffsetPairs[MAX_DYNAMIC_OFFSET_COUNT * 2]; // binding, offset } bindShaderResources; struct { GLbitfield mask;