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>
This commit is contained in:
Laszlo Agocs 2020-02-26 15:07:49 +01:00
parent 753e4d82be
commit 5bbc9986f9
2 changed files with 215 additions and 64 deletions

View File

@ -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);

View File

@ -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;