summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2020-02-26 15:07:49 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2020-03-03 18:25:56 +0100
commit5bbc9986f99a5d61c2e43b79fe815ea8ca450fcd (patch)
treef330a155c5a0ead9bf42f509761ae3f59e850e7e
parent753e4d82be966b82ff6ba41a0e7c4452f494790a (diff)
rhi: d3d: Use native resource binding mapping table when present
Newer versions of QShaderBaker will now use distinct, zero-based b, t+s, and u register spaces in the generated HLSL source. If this is the case, the native resource binding map (which so far we only used with Metal) contains the SPIR-V binding -> HLSL register binding mappings. This way we won't end up with invalid resource binding attempts (consider that e.g. D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT is only 16), just because, for example, a combined image sampler had a binding of 18 which then got blindly mapped to s18 and t18 in HLSL. Task-number: QTBUG-82472 Change-Id: I8bdcb5378634cf159f6367424582f9e9e5821c8e Reviewed-by: Christian Strømme <christian.stromme@qt.io>
-rw-r--r--src/gui/rhi/qrhid3d11.cpp257
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h22
2 files changed, 215 insertions, 64 deletions
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index ce39b42cf5..7b583e6fd2 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -580,6 +580,11 @@ void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
}
}
+static const int RBM_SUPPORTED_STAGES = 3;
+static const int RBM_VERTEX = 0;
+static const int RBM_FRAGMENT = 1;
+static const int RBM_COMPUTE = 2;
+
void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
int dynamicOffsetCount,
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
@@ -667,8 +672,17 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
}
}
- if (srbUpdate)
- updateShaderResourceBindings(srbD);
+ if (srbUpdate) {
+ const QShader::NativeResourceBindingMap *resBindMaps[RBM_SUPPORTED_STAGES];
+ memset(resBindMaps, 0, sizeof(resBindMaps));
+ if (gfxPsD) {
+ resBindMaps[RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
+ resBindMaps[RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
+ } else {
+ resBindMaps[RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
+ }
+ updateShaderResourceBindings(srbD, resBindMaps);
+ }
const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
@@ -1774,7 +1788,26 @@ void QRhiD3D11::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
cbD->commands.append(cmd);
}
-void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
+static inline QPair<int, int> mapBinding(int binding,
+ int stageIndex,
+ const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
+{
+ const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
+ if (!map || map->isEmpty())
+ return { binding, binding }; // old QShader versions do not have this map, assume 1:1 mapping then
+
+ auto it = map->constFind(binding);
+ if (it != map->cend())
+ return *it;
+
+ // Hitting this path is normal too. It is not given that the resource is
+ // present in the shaders for all the stages specified by the visibility
+ // mask in the QRhiShaderResourceBinding.
+ return { -1, -1 };
+}
+
+void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
+ const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
{
srbD->vsubufs.clear();
srbD->vsubufoffsets.clear();
@@ -1799,6 +1832,31 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
srbD->csUAVs.clear();
+ struct Stage {
+ struct Buffer {
+ int breg; // b0, b1, ...
+ ID3D11Buffer *buffer;
+ uint offsetInConstants;
+ uint sizeInConstants;
+ };
+ struct Texture {
+ int treg; // t0, t1, ...
+ ID3D11ShaderResourceView *srv;
+ };
+ struct Sampler {
+ int sreg; // s0, s1, ...
+ ID3D11SamplerState *sampler;
+ };
+ struct Uav {
+ int ureg;
+ ID3D11UnorderedAccessView *uav;
+ };
+ QVarLengthArray<Buffer, 8> buffers;
+ QVarLengthArray<Texture, 8> textures;
+ QVarLengthArray<Sampler, 8> samplers;
+ QVarLengthArray<Uav, 8> uavs;
+ } res[RBM_SUPPORTED_STAGES];
+
for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding::Data *b = srbD->sortedBindings.at(i).data();
QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
@@ -1818,26 +1876,24 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
// (ByteWidth) is always a multiple of 256.
const uint sizeInConstants = uint(aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256) / 16);
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
- srbD->vsubufs.feed(b->binding, bufD->buffer);
- srbD->vsubufoffsets.feed(b->binding, offsetInConstants);
- srbD->vsubufsizes.feed(b->binding, sizeInConstants);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_VERTEX].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
- srbD->fsubufs.feed(b->binding, bufD->buffer);
- srbD->fsubufoffsets.feed(b->binding, offsetInConstants);
- srbD->fsubufsizes.feed(b->binding, sizeInConstants);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_FRAGMENT].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- srbD->csubufs.feed(b->binding, bufD->buffer);
- srbD->csubufoffsets.feed(b->binding, offsetInConstants);
- srbD->csubufsizes.feed(b->binding, sizeInConstants);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_COMPUTE].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
}
}
break;
case QRhiShaderResourceBinding::SampledTexture:
{
- // A sampler with binding N is mapped to a HLSL sampler and texture
- // with registers sN and tN by SPIRV-Cross.
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler);
bd.stex.texId = texD->m_id;
@@ -1845,16 +1901,25 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.stex.samplerId = samplerD->m_id;
bd.stex.samplerGeneration = samplerD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
- srbD->vssamplers.feed(b->binding, samplerD->samplerState);
- srbD->vsshaderresources.feed(b->binding, texD->srv);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
+ res[RBM_VERTEX].textures.append({ nativeBinding.first, texD->srv });
+ res[RBM_VERTEX].samplers.append({ nativeBinding.second, samplerD->samplerState });
+ }
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
- srbD->fssamplers.feed(b->binding, samplerD->samplerState);
- srbD->fsshaderresources.feed(b->binding, texD->srv);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
+ res[RBM_FRAGMENT].textures.append({ nativeBinding.first, texD->srv });
+ res[RBM_FRAGMENT].samplers.append({ nativeBinding.second, samplerD->samplerState });
+ }
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- srbD->cssamplers.feed(b->binding, samplerD->samplerState);
- srbD->csshaderresources.feed(b->binding, texD->srv);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
+ res[RBM_COMPUTE].textures.append({ nativeBinding.first, texD->srv });
+ res[RBM_COMPUTE].samplers.append({ nativeBinding.second, samplerD->samplerState });
+ }
}
}
break;
@@ -1866,9 +1931,12 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.simage.id = texD->m_id;
bd.simage.generation = texD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
- if (uav)
- srbD->csUAVs.feed(b->binding, uav);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0) {
+ ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
+ if (uav)
+ res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
+ }
} else {
qWarning("Unordered access only supported at compute stage");
}
@@ -1882,9 +1950,12 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.sbuf.id = bufD->m_id;
bd.sbuf.generation = bufD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView();
- if (uav)
- srbD->csUAVs.feed(b->binding, uav);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0) {
+ ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView();
+ if (uav)
+ res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
+ }
} else {
qWarning("Unordered access only supported at compute stage");
}
@@ -1896,27 +1967,75 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
}
}
+ // QRhiBatchedBindings works with the native bindings and expects
+ // sorted input. The pre-sorted QRhiShaderResourceBinding list (based
+ // on the QRhi (SPIR-V) binding) is not helpful in this regard, so we
+ // have to sort here every time.
+ for (int stage = 0; stage < RBM_SUPPORTED_STAGES; ++stage) {
+ std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](const Stage::Buffer &a, const Stage::Buffer &b) {
+ return a.breg < b.breg;
+ });
+ std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](const Stage::Texture &a, const Stage::Texture &b) {
+ return a.treg < b.treg;
+ });
+ std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](const Stage::Sampler &a, const Stage::Sampler &b) {
+ return a.sreg < b.sreg;
+ });
+ std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](const Stage::Uav &a, const Stage::Uav &b) {
+ return a.ureg < b.ureg;
+ });
+ }
+
+ for (const Stage::Buffer &buf : qAsConst(res[RBM_VERTEX].buffers)) {
+ srbD->vsubufs.feed(buf.breg, buf.buffer);
+ srbD->vsubufoffsets.feed(buf.breg, buf.offsetInConstants);
+ srbD->vsubufsizes.feed(buf.breg, buf.sizeInConstants);
+ }
srbD->vsubufs.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->fsubufoffsets.feed(buf.breg, buf.offsetInConstants);
+ srbD->fsubufsizes.feed(buf.breg, buf.sizeInConstants);
+ }
srbD->fsubufs.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->csubufoffsets.feed(buf.breg, buf.offsetInConstants);
+ srbD->csubufsizes.feed(buf.breg, buf.sizeInConstants);
+ }
srbD->csubufs.finish();
srbD->csubufoffsets.finish();
srbD->csubufsizes.finish();
+ for (const Stage::Texture &t : qAsConst(res[RBM_VERTEX].textures))
+ srbD->vsshaderresources.feed(t.treg, t.srv);
+ for (const Stage::Sampler &s : qAsConst(res[RBM_VERTEX].samplers))
+ srbD->vssamplers.feed(s.sreg, s.sampler);
srbD->vssamplers.finish();
srbD->vsshaderresources.finish();
+ for (const Stage::Texture &t : qAsConst(res[RBM_FRAGMENT].textures))
+ srbD->fsshaderresources.feed(t.treg, t.srv);
+ for (const Stage::Sampler &s : qAsConst(res[RBM_FRAGMENT].samplers))
+ srbD->fssamplers.feed(s.sreg, s.sampler);
srbD->fssamplers.finish();
srbD->fsshaderresources.finish();
+ for (const Stage::Texture &t : qAsConst(res[RBM_COMPUTE].textures))
+ srbD->csshaderresources.feed(t.treg, t.srv);
+ for (const Stage::Sampler &s : qAsConst(res[RBM_COMPUTE].samplers))
+ srbD->cssamplers.feed(s.sreg, s.sampler);
srbD->cssamplers.finish();
srbD->csshaderresources.finish();
+ for (const Stage::Uav &u : qAsConst(res[RBM_COMPUTE].uavs))
+ srbD->csUAVs.feed(u.ureg, u.uav);
srbD->csUAVs.finish();
}
@@ -2205,8 +2324,8 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
case QD3D11CommandBuffer::Command::BindGraphicsPipeline:
{
QD3D11GraphicsPipeline *psD = cmd.args.bindGraphicsPipeline.ps;
- context->VSSetShader(psD->vs, nullptr, 0);
- context->PSSetShader(psD->fs, nullptr, 0);
+ context->VSSetShader(psD->vs.shader, nullptr, 0);
+ context->PSSetShader(psD->fs.shader, nullptr, 0);
context->IASetPrimitiveTopology(psD->d3dTopology);
context->IASetInputLayout(psD->inputLayout);
context->OMSetDepthStencilState(psD->dsState, stencilRef);
@@ -2281,7 +2400,7 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
annotations->SetMarker(reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
break;
case QD3D11CommandBuffer::Command::BindComputePipeline:
- context->CSSetShader(cmd.args.bindComputePipeline.ps->cs, nullptr, 0);
+ context->CSSetShader(cmd.args.bindComputePipeline.ps->cs.shader, nullptr, 0);
break;
case QD3D11CommandBuffer::Command::Dispatch:
context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
@@ -3137,6 +3256,7 @@ QD3D11ShaderResourceBindings::~QD3D11ShaderResourceBindings()
void QD3D11ShaderResourceBindings::release()
{
sortedBindings.clear();
+ boundResourceData.clear();
}
bool QD3D11ShaderResourceBindings::build()
@@ -3153,8 +3273,8 @@ bool QD3D11ShaderResourceBindings::build()
boundResourceData.resize(sortedBindings.count());
- QRHI_RES_RHI(QRhiD3D11);
- rhiD->updateShaderResourceBindings(this);
+ for (BoundResourceData &bd : boundResourceData)
+ memset(&bd, 0, sizeof(BoundResourceData));
generation += 1;
return true;
@@ -3195,15 +3315,17 @@ void QD3D11GraphicsPipeline::release()
rastState = nullptr;
}
- if (vs) {
- vs->Release();
- vs = nullptr;
+ if (vs.shader) {
+ vs.shader->Release();
+ vs.shader = nullptr;
}
+ vs.nativeResourceBindingMap.clear();
- if (fs) {
- fs->Release();
- fs = nullptr;
+ if (fs.shader) {
+ fs.shader->Release();
+ fs.shader = nullptr;
}
+ fs.nativeResourceBindingMap.clear();
rhiD->unregisterResource(this);
}
@@ -3405,13 +3527,14 @@ static pD3DCompile resolveD3DCompile()
return nullptr;
}
-static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error)
+static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error, QShaderKey *usedShaderKey)
{
QShaderCode dxbc = shader.shader({ QShader::DxbcShader, 50, shaderVariant });
if (!dxbc.shader().isEmpty())
return dxbc.shader();
- QShaderCode hlslSource = shader.shader({ QShader::HlslShader, 50, shaderVariant });
+ const QShaderKey key = { QShader::HlslShader, 50, shaderVariant };
+ QShaderCode hlslSource = shader.shader(key);
if (hlslSource.shader().isEmpty()) {
qWarning() << "No HLSL (shader model 5.0) code found in baked shader" << shader;
return QByteArray();
@@ -3463,6 +3586,9 @@ static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Varian
return QByteArray();
}
+ if (usedShaderKey)
+ *usedShaderKey = key;
+
QByteArray result;
result.resize(int(bytecode->GetBufferSize()));
memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
@@ -3554,20 +3680,23 @@ bool QD3D11GraphicsPipeline::build()
if (cacheIt != rhiD->m_shaderCache.constEnd()) {
switch (shaderStage.type()) {
case QRhiShaderStage::Vertex:
- vs = static_cast<ID3D11VertexShader *>(cacheIt->s);
- vs->AddRef();
+ vs.shader = static_cast<ID3D11VertexShader *>(cacheIt->s);
+ vs.shader->AddRef();
vsByteCode = cacheIt->bytecode;
+ vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
break;
case QRhiShaderStage::Fragment:
- fs = static_cast<ID3D11PixelShader *>(cacheIt->s);
- fs->AddRef();
+ fs.shader = static_cast<ID3D11PixelShader *>(cacheIt->s);
+ fs.shader->AddRef();
+ fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
break;
default:
break;
}
} else {
QString error;
- const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error);
+ QShaderKey shaderKey;
+ const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error, &shaderKey);
if (bytecode.isEmpty()) {
qWarning("HLSL shader compilation failed: %s", qPrintable(error));
return false;
@@ -3580,23 +3709,27 @@ bool QD3D11GraphicsPipeline::build()
switch (shaderStage.type()) {
case QRhiShaderStage::Vertex:
- hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &vs);
+ hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &vs.shader);
if (FAILED(hr)) {
qWarning("Failed to create vertex shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
vsByteCode = bytecode;
- rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs, bytecode));
- vs->AddRef();
+ if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey))
+ vs.nativeResourceBindingMap = *map;
+ rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
+ vs.shader->AddRef();
break;
case QRhiShaderStage::Fragment:
- hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs);
+ hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs.shader);
if (FAILED(hr)) {
qWarning("Failed to create pixel shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
- rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs, bytecode));
- fs->AddRef();
+ if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey))
+ fs.nativeResourceBindingMap = *map;
+ rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
+ fs.shader->AddRef();
break;
default:
break;
@@ -3655,46 +3788,52 @@ void QD3D11ComputePipeline::release()
{
QRHI_RES_RHI(QRhiD3D11);
- if (!cs)
+ if (!cs.shader)
return;
- cs->Release();
- cs = nullptr;
+ cs.shader->Release();
+ cs.shader = nullptr;
+ cs.nativeResourceBindingMap.clear();
rhiD->unregisterResource(this);
}
bool QD3D11ComputePipeline::build()
{
- if (cs)
+ if (cs.shader)
release();
QRHI_RES_RHI(QRhiD3D11);
auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
if (cacheIt != rhiD->m_shaderCache.constEnd()) {
- cs = static_cast<ID3D11ComputeShader *>(cacheIt->s);
+ cs.shader = static_cast<ID3D11ComputeShader *>(cacheIt->s);
+ cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
} else {
QString error;
- const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error);
+ QShaderKey shaderKey;
+ const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error, &shaderKey);
if (bytecode.isEmpty()) {
qWarning("HLSL compute shader compilation failed: %s", qPrintable(error));
return false;
}
- HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &cs);
+ HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &cs.shader);
if (FAILED(hr)) {
qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
+ if (const QShader::NativeResourceBindingMap *map = m_shaderStage.shader().nativeResourceBindingMap(shaderKey))
+ cs.nativeResourceBindingMap = *map;
+
if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
rhiD->clearShaderCache();
- rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs, bytecode));
+ rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
}
- cs->AddRef();
+ cs.shader->AddRef();
generation += 1;
rhiD->registerResource(this);
diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h
index b70f541c68..f749b612b5 100644
--- a/src/gui/rhi/qrhid3d11_p_p.h
+++ b/src/gui/rhi/qrhid3d11_p_p.h
@@ -270,8 +270,14 @@ struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline
ID3D11DepthStencilState *dsState = nullptr;
ID3D11BlendState *blendState = nullptr;
- ID3D11VertexShader *vs = nullptr;
- ID3D11PixelShader *fs = nullptr;
+ struct {
+ ID3D11VertexShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } vs;
+ struct {
+ ID3D11PixelShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } fs;
ID3D11InputLayout *inputLayout = nullptr;
D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
ID3D11RasterizerState *rastState = nullptr;
@@ -286,7 +292,10 @@ struct QD3D11ComputePipeline : public QRhiComputePipeline
void release() override;
bool build() override;
- ID3D11ComputeShader *cs = nullptr;
+ struct {
+ ID3D11ComputeShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } cs;
uint generation = 0;
friend class QRhiD3D11;
};
@@ -642,7 +651,8 @@ public:
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
- void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD);
+ void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
+ const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]);
void executeBufferHostWrites(QD3D11Buffer *bufD);
void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
const uint *dynOfsPairs, int dynOfsPairCount,
@@ -701,9 +711,11 @@ public:
struct Shader {
Shader() = default;
- Shader(IUnknown *s, const QByteArray &bytecode) : s(s), bytecode(bytecode) { }
+ Shader(IUnknown *s, const QByteArray &bytecode, const QShader::NativeResourceBindingMap &rbm)
+ : s(s), bytecode(bytecode), nativeResourceBindingMap(rbm) { }
IUnknown *s;
QByteArray bytecode;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
};
QHash<QRhiShaderStage, Shader> m_shaderCache;