From fe3a1617afd71e5ea2fced740a69b3d27958e2d7 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 22 Sep 2020 11:01:24 +0200 Subject: rhi: d3d: Fix dynamic offsets with multiple buffers Fixes: QTBUG-86821 Change-Id: I57f86bf0f7e95b92f5b2c5fee587112ecf0fc8e6 Reviewed-by: Andy Nichols --- src/gui/rhi/qrhid3d11.cpp | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) (limited to 'src/gui/rhi/qrhid3d11.cpp') diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index b9829ed263..f3ddc7aac4 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -1903,14 +1903,17 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]) { srbD->vsubufs.clear(); + srbD->vsubuforigbindings.clear(); srbD->vsubufoffsets.clear(); srbD->vsubufsizes.clear(); srbD->fsubufs.clear(); + srbD->fsubuforigbindings.clear(); srbD->fsubufoffsets.clear(); srbD->fsubufsizes.clear(); srbD->csubufs.clear(); + srbD->csubuforigbindings.clear(); srbD->csubufoffsets.clear(); srbD->csubufsizes.clear(); @@ -1927,6 +1930,7 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, struct Stage { struct Buffer { + int binding; // stored and sent along in XXorigbindings just for applyDynamicOffsets() int breg; // b0, b1, ... ID3D11Buffer *buffer; uint offsetInConstants; @@ -1960,9 +1964,12 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, Q_ASSERT(aligned(b->u.ubuf.offset, 256) == b->u.ubuf.offset); bd.ubuf.id = bufD->m_id; bd.ubuf.generation = bufD->generation; - // dynamic ubuf offsets are not considered here, those are baked in + // Dynamic ubuf offsets are not considered here, those are baked in // at a later stage, which is good as vsubufoffsets and friends are - // per-srb, not per-setShaderResources call + // per-srb, not per-setShaderResources call. Other backends (GL, + // Metal) are different in this respect since those do not store + // per-srb vsubufoffsets etc. data so life's a bit easier for them. + // But here we have to defer baking in the dynamic offset. const uint offsetInConstants = uint(b->u.ubuf.offset) / 16; // size must be 16 mult. (in constants, i.e. multiple of 256 bytes). // We can round up if needed since the buffers's actual size @@ -1971,17 +1978,17 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) { QPair nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps); if (nativeBinding.first >= 0) - res[RBM_VERTEX].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants }); + res[RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants }); } if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) { QPair nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps); if (nativeBinding.first >= 0) - res[RBM_FRAGMENT].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants }); + res[RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants }); } if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { QPair nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps); if (nativeBinding.first >= 0) - res[RBM_COMPUTE].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants }); + res[RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants }); } } break; @@ -2088,28 +2095,34 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, for (const Stage::Buffer &buf : qAsConst(res[RBM_VERTEX].buffers)) { srbD->vsubufs.feed(buf.breg, buf.buffer); + srbD->vsubuforigbindings.feed(buf.breg, UINT(buf.binding)); srbD->vsubufoffsets.feed(buf.breg, buf.offsetInConstants); srbD->vsubufsizes.feed(buf.breg, buf.sizeInConstants); } srbD->vsubufs.finish(); + srbD->vsubuforigbindings.finish(); srbD->vsubufoffsets.finish(); srbD->vsubufsizes.finish(); for (const Stage::Buffer &buf : qAsConst(res[RBM_FRAGMENT].buffers)) { srbD->fsubufs.feed(buf.breg, buf.buffer); + srbD->fsubuforigbindings.feed(buf.breg, UINT(buf.binding)); srbD->fsubufoffsets.feed(buf.breg, buf.offsetInConstants); srbD->fsubufsizes.feed(buf.breg, buf.sizeInConstants); } srbD->fsubufs.finish(); + srbD->fsubuforigbindings.finish(); srbD->fsubufoffsets.finish(); srbD->fsubufsizes.finish(); for (const Stage::Buffer &buf : qAsConst(res[RBM_COMPUTE].buffers)) { srbD->csubufs.feed(buf.breg, buf.buffer); + srbD->csubuforigbindings.feed(buf.breg, UINT(buf.binding)); srbD->csubufoffsets.feed(buf.breg, buf.offsetInConstants); srbD->csubufsizes.feed(buf.breg, buf.sizeInConstants); } srbD->csubufs.finish(); + srbD->csubuforigbindings.finish(); srbD->csubufoffsets.finish(); srbD->csubufsizes.finish(); @@ -2158,17 +2171,20 @@ void QRhiD3D11::executeBufferHostWrites(QD3D11Buffer *bufD) static void applyDynamicOffsets(QVarLengthArray *offsets, int batchIndex, - QRhiBatchedBindings *ubufs, - QRhiBatchedBindings *ubufoffsets, + QRhiBatchedBindings *originalBindings, + QRhiBatchedBindings *staticOffsets, const uint *dynOfsPairs, int dynOfsPairCount) { - const int count = ubufs->batches[batchIndex].resources.count(); - const UINT startBinding = ubufs->batches[batchIndex].startBinding; - *offsets = ubufoffsets->batches[batchIndex].resources; + 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) { for (int di = 0; di < dynOfsPairCount; ++di) { const uint binding = dynOfsPairs[2 * di]; - if (binding == startBinding + UINT(b)) { + // 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; break; @@ -2258,7 +2274,8 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD, srbD->vsubufsizes.batches[i].resources.constData()); } else { QVarLengthArray offsets; - applyDynamicOffsets(&offsets, i, &srbD->vsubufs, &srbD->vsubufoffsets, dynOfsPairs, dynOfsPairCount); + applyDynamicOffsets(&offsets, i, &srbD->vsubuforigbindings, &srbD->vsubufoffsets, + dynOfsPairs, dynOfsPairCount); context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding, count, srbD->vsubufs.batches[i].resources.constData(), @@ -2282,7 +2299,8 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD, srbD->fsubufsizes.batches[i].resources.constData()); } else { QVarLengthArray offsets; - applyDynamicOffsets(&offsets, i, &srbD->fsubufs, &srbD->fsubufoffsets, dynOfsPairs, dynOfsPairCount); + applyDynamicOffsets(&offsets, i, &srbD->fsubuforigbindings, &srbD->fsubufoffsets, + dynOfsPairs, dynOfsPairCount); context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding, count, srbD->fsubufs.batches[i].resources.constData(), @@ -2306,7 +2324,8 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD, srbD->csubufsizes.batches[i].resources.constData()); } else { QVarLengthArray offsets; - applyDynamicOffsets(&offsets, i, &srbD->csubufs, &srbD->csubufoffsets, dynOfsPairs, dynOfsPairCount); + applyDynamicOffsets(&offsets, i, &srbD->csubuforigbindings, &srbD->csubufoffsets, + dynOfsPairs, dynOfsPairCount); context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding, count, srbD->csubufs.batches[i].resources.constData(), -- cgit v1.2.3