rhi: d3d11: Add compute and load/store res support

Also revise how we reset shader input/outputs at the beginning
of a pass.

Change-Id: I6d4057f32318ca09b12e16c602bb1033a3ec8e3c
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Laszlo Agocs 2019-06-19 16:23:54 +02:00
parent 33f16af307
commit 484fc8545f
2 changed files with 450 additions and 80 deletions

View File

@ -376,7 +376,7 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
case QRhi::ElementIndexUint: case QRhi::ElementIndexUint:
return true; return true;
case QRhi::Compute: case QRhi::Compute:
return false; return true;
default: default:
Q_UNREACHABLE(); Q_UNREACHABLE();
return false; return false;
@ -460,10 +460,11 @@ void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::RenderPass); Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::RenderPass);
QD3D11GraphicsPipeline *psD = QRHI_RES(QD3D11GraphicsPipeline, ps); QD3D11GraphicsPipeline *psD = QRHI_RES(QD3D11GraphicsPipeline, ps);
const bool pipelineChanged = cbD->currentPipeline != ps || cbD->currentPipelineGeneration != psD->generation; const bool pipelineChanged = cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation;
if (pipelineChanged) { if (pipelineChanged) {
cbD->currentPipeline = ps; cbD->currentGraphicsPipeline = ps;
cbD->currentComputePipeline = nullptr;
cbD->currentPipelineGeneration = psD->generation; cbD->currentPipelineGeneration = psD->generation;
QD3D11CommandBuffer::Command cmd; QD3D11CommandBuffer::Command cmd;
@ -478,11 +479,16 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
{ {
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::RenderPass); Q_ASSERT(cbD->recordingPass != QD3D11CommandBuffer::NoPass);
Q_ASSERT(cbD->currentPipeline); QD3D11GraphicsPipeline *gfxPsD = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline);
QD3D11ComputePipeline *compPsD = QRHI_RES(QD3D11ComputePipeline, cbD->currentComputePipeline);
if (!srb) if (!srb) {
srb = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentPipeline)->m_shaderResourceBindings; if (gfxPsD)
srb = gfxPsD->m_shaderResourceBindings;
else
srb = compPsD->m_shaderResourceBindings;
}
QD3D11ShaderResourceBindings *srbD = QRHI_RES(QD3D11ShaderResourceBindings, srb); QD3D11ShaderResourceBindings *srbD = QRHI_RES(QD3D11ShaderResourceBindings, srb);
@ -525,6 +531,34 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
} }
} }
break; break;
case QRhiShaderResourceBinding::ImageLoad:
Q_FALLTHROUGH();
case QRhiShaderResourceBinding::ImageStore:
Q_FALLTHROUGH();
case QRhiShaderResourceBinding::ImageLoadStore:
{
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.simage.tex);
if (texD->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
srbUpdate = true;
bd.simage.id = texD->m_id;
bd.simage.generation = texD->generation;
}
}
break;
case QRhiShaderResourceBinding::BufferLoad:
Q_FALLTHROUGH();
case QRhiShaderResourceBinding::BufferStore:
Q_FALLTHROUGH();
case QRhiShaderResourceBinding::BufferLoadStore:
{
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.sbuf.buf);
if (bufD->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
srbUpdate = true;
bd.sbuf.id = bufD->m_id;
bd.sbuf.generation = bufD->generation;
}
}
break;
default: default:
Q_UNREACHABLE(); Q_UNREACHABLE();
break; break;
@ -534,10 +568,17 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
if (srbUpdate) if (srbUpdate)
updateShaderResourceBindings(srbD); updateShaderResourceBindings(srbD);
const bool srbChanged = cbD->currentSrb != srb || cbD->currentSrbGeneration != srbD->generation; const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
if (srbChanged || srbUpdate || hasDynamicOffsetInSrb) { if (srbChanged || srbRebuilt || srbUpdate || hasDynamicOffsetInSrb) {
cbD->currentSrb = srb; if (gfxPsD) {
cbD->currentGraphicsSrb = srb;
cbD->currentComputeSrb = nullptr;
} else {
cbD->currentGraphicsSrb = nullptr;
cbD->currentComputeSrb = srb;
}
cbD->currentSrbGeneration = srbD->generation; cbD->currentSrbGeneration = srbD->generation;
QD3D11CommandBuffer::Command cmd; QD3D11CommandBuffer::Command cmd;
@ -545,7 +586,7 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
cmd.args.bindShaderResources.srb = srbD; cmd.args.bindShaderResources.srb = srbD;
// dynamic offsets have to be applied at the time of executing the bind // dynamic offsets have to be applied at the time of executing the bind
// operations, not here // operations, not here
cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbUpdate && hasDynamicOffsetInSrb; cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && hasDynamicOffsetInSrb;
cmd.args.bindShaderResources.dynamicOffsetCount = 0; cmd.args.bindShaderResources.dynamicOffsetCount = 0;
if (hasDynamicOffsetInSrb) { if (hasDynamicOffsetInSrb) {
if (dynamicOffsetCount < QD3D11CommandBuffer::Command::MAX_UBUF_BINDINGS) { if (dynamicOffsetCount < QD3D11CommandBuffer::Command::MAX_UBUF_BINDINGS) {
@ -599,7 +640,7 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb,
cmd.args.bindVertexBuffers.startSlot = startBinding; cmd.args.bindVertexBuffers.startSlot = startBinding;
cmd.args.bindVertexBuffers.slotCount = bindingCount; cmd.args.bindVertexBuffers.slotCount = bindingCount;
const QVector<QRhiVertexInputBinding> inputBindings = const QVector<QRhiVertexInputBinding> inputBindings =
QRHI_RES(QD3D11GraphicsPipeline, cbD->currentPipeline)->m_vertexInputLayout.bindings(); QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline)->m_vertexInputLayout.bindings();
for (int i = 0, ie = qMin(bindingCount, inputBindings.count()); i != ie; ++i) { for (int i = 0, ie = qMin(bindingCount, inputBindings.count()); i != ie; ++i) {
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, bindings[i].first); QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, bindings[i].first);
cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer; cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
@ -688,7 +729,7 @@ void QRhiD3D11::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
QD3D11CommandBuffer::Command cmd; QD3D11CommandBuffer::Command cmd;
cmd.cmd = QD3D11CommandBuffer::Command::BlendConstants; cmd.cmd = QD3D11CommandBuffer::Command::BlendConstants;
cmd.args.blendConstants.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentPipeline); cmd.args.blendConstants.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline);
cmd.args.blendConstants.c[0] = c.redF(); cmd.args.blendConstants.c[0] = c.redF();
cmd.args.blendConstants.c[1] = c.greenF(); cmd.args.blendConstants.c[1] = c.greenF();
cmd.args.blendConstants.c[2] = c.blueF(); cmd.args.blendConstants.c[2] = c.blueF();
@ -703,7 +744,7 @@ void QRhiD3D11::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
QD3D11CommandBuffer::Command cmd; QD3D11CommandBuffer::Command cmd;
cmd.cmd = QD3D11CommandBuffer::Command::StencilRef; cmd.cmd = QD3D11CommandBuffer::Command::StencilRef;
cmd.args.stencilRef.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentPipeline); cmd.args.stencilRef.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline);
cmd.args.stencilRef.ref = refValue; cmd.args.stencilRef.ref = refValue;
cbD->commands.append(cmd); cbD->commands.append(cmd);
} }
@ -716,7 +757,7 @@ void QRhiD3D11::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
QD3D11CommandBuffer::Command cmd; QD3D11CommandBuffer::Command cmd;
cmd.cmd = QD3D11CommandBuffer::Command::Draw; cmd.cmd = QD3D11CommandBuffer::Command::Draw;
cmd.args.draw.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentPipeline); cmd.args.draw.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline);
cmd.args.draw.vertexCount = vertexCount; cmd.args.draw.vertexCount = vertexCount;
cmd.args.draw.instanceCount = instanceCount; cmd.args.draw.instanceCount = instanceCount;
cmd.args.draw.firstVertex = firstVertex; cmd.args.draw.firstVertex = firstVertex;
@ -732,7 +773,7 @@ void QRhiD3D11::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
QD3D11CommandBuffer::Command cmd; QD3D11CommandBuffer::Command cmd;
cmd.cmd = QD3D11CommandBuffer::Command::DrawIndexed; cmd.cmd = QD3D11CommandBuffer::Command::DrawIndexed;
cmd.args.drawIndexed.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentPipeline); cmd.args.drawIndexed.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline);
cmd.args.drawIndexed.indexCount = indexCount; cmd.args.drawIndexed.indexCount = indexCount;
cmd.args.drawIndexed.instanceCount = instanceCount; cmd.args.drawIndexed.instanceCount = instanceCount;
cmd.args.drawIndexed.firstIndex = firstIndex; cmd.args.drawIndexed.firstIndex = firstIndex;
@ -795,8 +836,12 @@ void QRhiD3D11::endExternal(QRhiCommandBuffer *cb)
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
Q_ASSERT(cbD->commands.isEmpty()); Q_ASSERT(cbD->commands.isEmpty());
cbD->resetCachedState(); cbD->resetCachedState();
if (cbD->currentTarget) // could be compute, no rendertarget then if (cbD->currentTarget) { // could be compute, no rendertarget then
enqueueSetRenderTarget(cbD, cbD->currentTarget); QD3D11CommandBuffer::Command fbCmd;
fbCmd.cmd = QD3D11CommandBuffer::Command::SetRenderTarget;
fbCmd.args.setRenderTarget.rt = cbD->currentTarget;
cbD->commands.append(fbCmd);
}
} }
QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
@ -1379,14 +1424,6 @@ void QRhiD3D11::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *r
enqueueResourceUpdates(cb, resourceUpdates); enqueueResourceUpdates(cb, resourceUpdates);
} }
void QRhiD3D11::enqueueSetRenderTarget(QD3D11CommandBuffer *cbD, QRhiRenderTarget *rt)
{
QD3D11CommandBuffer::Command fbCmd;
fbCmd.cmd = QD3D11CommandBuffer::Command::SetRenderTarget;
fbCmd.args.setRenderTarget.rt = rt;
cbD->commands.append(fbCmd);
}
void QRhiD3D11::beginPass(QRhiCommandBuffer *cb, void QRhiD3D11::beginPass(QRhiCommandBuffer *cb,
QRhiRenderTarget *rt, QRhiRenderTarget *rt,
const QColor &colorClearValue, const QColor &colorClearValue,
@ -1407,7 +1444,13 @@ void QRhiD3D11::beginPass(QRhiCommandBuffer *cb,
wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents); wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents); wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
} }
enqueueSetRenderTarget(cbD, rt);
QD3D11CommandBuffer::Command fbCmd;
fbCmd.cmd = QD3D11CommandBuffer::Command::ResetShaderResources;
cbD->commands.append(fbCmd);
fbCmd.cmd = QD3D11CommandBuffer::Command::SetRenderTarget;
fbCmd.args.setRenderTarget.rt = rt;
cbD->commands.append(fbCmd);
QD3D11CommandBuffer::Command clearCmd; QD3D11CommandBuffer::Command clearCmd;
clearCmd.cmd = QD3D11CommandBuffer::Command::Clear; clearCmd.cmd = QD3D11CommandBuffer::Command::Clear;
@ -1499,6 +1542,10 @@ void QRhiD3D11::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch
if (resourceUpdates) if (resourceUpdates)
enqueueResourceUpdates(cb, resourceUpdates); enqueueResourceUpdates(cb, resourceUpdates);
QD3D11CommandBuffer::Command cmd;
cmd.cmd = QD3D11CommandBuffer::Command::ResetShaderResources;
cbD->commands.append(cmd);
cbD->recordingPass = QD3D11CommandBuffer::ComputePass; cbD->recordingPass = QD3D11CommandBuffer::ComputePass;
} }
@ -1515,16 +1562,34 @@ void QRhiD3D11::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *r
void QRhiD3D11::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) void QRhiD3D11::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps)
{ {
Q_UNUSED(cb); QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
Q_UNUSED(ps); Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::ComputePass);
QD3D11ComputePipeline *psD = QRHI_RES(QD3D11ComputePipeline, ps);
const bool pipelineChanged = cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation;
if (pipelineChanged) {
cbD->currentGraphicsPipeline = nullptr;
cbD->currentComputePipeline = psD;
cbD->currentPipelineGeneration = psD->generation;
QD3D11CommandBuffer::Command cmd;
cmd.cmd = QD3D11CommandBuffer::Command::BindComputePipeline;
cmd.args.bindComputePipeline.ps = psD;
cbD->commands.append(cmd);
}
} }
void QRhiD3D11::dispatch(QRhiCommandBuffer *cb, int x, int y, int z) void QRhiD3D11::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
{ {
Q_UNUSED(cb); QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
Q_UNUSED(x); Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::ComputePass);
Q_UNUSED(y);
Q_UNUSED(z); QD3D11CommandBuffer::Command cmd;
cmd.cmd = QD3D11CommandBuffer::Command::Dispatch;
cmd.args.dispatch.x = x;
cmd.args.dispatch.y = y;
cmd.args.dispatch.z = z;
cbD->commands.append(cmd);
} }
void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD) void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
@ -1537,12 +1602,21 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
srbD->fsubufoffsets.clear(); srbD->fsubufoffsets.clear();
srbD->fsubufsizes.clear(); srbD->fsubufsizes.clear();
srbD->csubufs.clear();
srbD->csubufoffsets.clear();
srbD->csubufsizes.clear();
srbD->vssamplers.clear(); srbD->vssamplers.clear();
srbD->vsshaderresources.clear(); srbD->vsshaderresources.clear();
srbD->fssamplers.clear(); srbD->fssamplers.clear();
srbD->fsshaderresources.clear(); srbD->fsshaderresources.clear();
srbD->cssamplers.clear();
srbD->csshaderresources.clear();
srbD->csUAVs.clear();
for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) { for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->sortedBindings[i]); const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->sortedBindings[i]);
QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]); QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
@ -1571,6 +1645,11 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
srbD->fsubufoffsets.feed(b->binding, offsetInConstants); srbD->fsubufoffsets.feed(b->binding, offsetInConstants);
srbD->fsubufsizes.feed(b->binding, sizeInConstants); srbD->fsubufsizes.feed(b->binding, 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);
}
} }
break; break;
case QRhiShaderResourceBinding::SampledTexture: case QRhiShaderResourceBinding::SampledTexture:
@ -1591,6 +1670,46 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
srbD->fssamplers.feed(b->binding, samplerD->samplerState); srbD->fssamplers.feed(b->binding, samplerD->samplerState);
srbD->fsshaderresources.feed(b->binding, texD->srv); srbD->fsshaderresources.feed(b->binding, texD->srv);
} }
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
srbD->cssamplers.feed(b->binding, samplerD->samplerState);
srbD->csshaderresources.feed(b->binding, texD->srv);
}
}
break;
case QRhiShaderResourceBinding::ImageLoad:
Q_FALLTHROUGH();
case QRhiShaderResourceBinding::ImageStore:
Q_FALLTHROUGH();
case QRhiShaderResourceBinding::ImageLoadStore:
{
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.simage.tex);
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);
} else {
qWarning("Unordered access only supported at compute stage");
}
}
break;
case QRhiShaderResourceBinding::BufferLoad:
Q_FALLTHROUGH();
case QRhiShaderResourceBinding::BufferStore:
Q_FALLTHROUGH();
case QRhiShaderResourceBinding::BufferLoadStore:
{
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.sbuf.buf);
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);
} else {
qWarning("Unordered access only supported at compute stage");
}
} }
break; break;
default: default:
@ -1607,11 +1726,20 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
srbD->fsubufoffsets.finish(); srbD->fsubufoffsets.finish();
srbD->fsubufsizes.finish(); srbD->fsubufsizes.finish();
srbD->csubufs.finish();
srbD->csubufoffsets.finish();
srbD->csubufsizes.finish();
srbD->vssamplers.finish(); srbD->vssamplers.finish();
srbD->vsshaderresources.finish(); srbD->vsshaderresources.finish();
srbD->fssamplers.finish(); srbD->fssamplers.finish();
srbD->fsshaderresources.finish(); srbD->fsshaderresources.finish();
srbD->cssamplers.finish();
srbD->csshaderresources.finish();
srbD->csUAVs.finish();
} }
void QRhiD3D11::executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD) void QRhiD3D11::executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD)
@ -1631,6 +1759,27 @@ void QRhiD3D11::executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD)
} }
} }
static void applyDynamicOffsets(QVarLengthArray<UINT, 4> *offsets,
int batchIndex,
QRhiBatchedBindings<ID3D11Buffer *> *ubufs,
QRhiBatchedBindings<UINT> *ubufoffsets,
const uint *dynOfsPairs, int dynOfsPairCount)
{
const UINT count = ubufs->batches[batchIndex].resources.count();
const UINT startBinding = ubufs->batches[batchIndex].startBinding;
*offsets = ubufoffsets->batches[batchIndex].resources;
for (UINT b = 0; b < count; ++b) {
for (int di = 0; di < dynOfsPairCount; ++di) {
const uint binding = dynOfsPairs[2 * di];
if (binding == startBinding + b) {
const uint offsetInConstants = dynOfsPairs[2 * di + 1];
(*offsets)[b] = offsetInConstants;
break;
}
}
}
}
void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD, void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
const uint *dynOfsPairs, int dynOfsPairCount, const uint *dynOfsPairs, int dynOfsPairCount,
bool offsetOnlyChange) bool offsetOnlyChange)
@ -1653,6 +1802,15 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
contextState.fsHighestActiveSrvBinding = qMax<int>(contextState.fsHighestActiveSrvBinding, contextState.fsHighestActiveSrvBinding = qMax<int>(contextState.fsHighestActiveSrvBinding,
batch.startBinding + batch.resources.count() - 1); batch.startBinding + batch.resources.count() - 1);
} }
for (const auto &batch : srbD->cssamplers.batches)
context->CSSetSamplers(batch.startBinding, batch.resources.count(), batch.resources.constData());
for (const auto &batch : srbD->csshaderresources.batches) {
context->CSSetShaderResources(batch.startBinding, batch.resources.count(), batch.resources.constData());
contextState.csHighestActiveSrvBinding = qMax<int>(contextState.csHighestActiveSrvBinding,
batch.startBinding + batch.resources.count() - 1);
}
} }
for (int i = 0, ie = srbD->vsubufs.batches.count(); i != ie; ++i) { for (int i = 0, ie = srbD->vsubufs.batches.count(); i != ie; ++i) {
@ -1663,21 +1821,10 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
srbD->vsubufoffsets.batches[i].resources.constData(), srbD->vsubufoffsets.batches[i].resources.constData(),
srbD->vsubufsizes.batches[i].resources.constData()); srbD->vsubufsizes.batches[i].resources.constData());
} else { } else {
const UINT count = srbD->vsubufs.batches[i].resources.count(); QVarLengthArray<UINT, 4> offsets;
const UINT startBinding = srbD->vsubufs.batches[i].startBinding; applyDynamicOffsets(&offsets, i, &srbD->vsubufs, &srbD->vsubufoffsets, dynOfsPairs, dynOfsPairCount);
QVarLengthArray<UINT, 4> offsets = srbD->vsubufoffsets.batches[i].resources; context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
for (UINT b = 0; b < count; ++b) { srbD->vsubufs.batches[i].resources.count(),
for (int di = 0; di < dynOfsPairCount; ++di) {
const uint binding = dynOfsPairs[2 * di];
if (binding == startBinding + b) {
const uint offsetInConstants = dynOfsPairs[2 * di + 1];
offsets[b] = offsetInConstants;
break;
}
}
}
context->VSSetConstantBuffers1(startBinding,
count,
srbD->vsubufs.batches[i].resources.constData(), srbD->vsubufs.batches[i].resources.constData(),
offsets.constData(), offsets.constData(),
srbD->vsubufsizes.batches[i].resources.constData()); srbD->vsubufsizes.batches[i].resources.constData());
@ -1692,33 +1839,73 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
srbD->fsubufoffsets.batches[i].resources.constData(), srbD->fsubufoffsets.batches[i].resources.constData(),
srbD->fsubufsizes.batches[i].resources.constData()); srbD->fsubufsizes.batches[i].resources.constData());
} else { } else {
const UINT count = srbD->fsubufs.batches[i].resources.count(); QVarLengthArray<UINT, 4> offsets;
const UINT startBinding = srbD->fsubufs.batches[i].startBinding; applyDynamicOffsets(&offsets, i, &srbD->fsubufs, &srbD->fsubufoffsets, dynOfsPairs, dynOfsPairCount);
QVarLengthArray<UINT, 4> offsets = srbD->fsubufoffsets.batches[i].resources; context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
for (UINT b = 0; b < count; ++b) { srbD->fsubufs.batches[i].resources.count(),
for (int di = 0; di < dynOfsPairCount; ++di) {
const uint binding = dynOfsPairs[2 * di];
if (binding == startBinding + b) {
const uint offsetInConstants = dynOfsPairs[2 * di + 1];
offsets[b] = offsetInConstants;
break;
}
}
}
context->PSSetConstantBuffers1(startBinding,
count,
srbD->fsubufs.batches[i].resources.constData(), srbD->fsubufs.batches[i].resources.constData(),
offsets.constData(), offsets.constData(),
srbD->fsubufsizes.batches[i].resources.constData()); srbD->fsubufsizes.batches[i].resources.constData());
} }
} }
for (int i = 0, ie = srbD->csubufs.batches.count(); i != ie; ++i) {
if (!dynOfsPairCount) {
context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
srbD->csubufs.batches[i].resources.count(),
srbD->csubufs.batches[i].resources.constData(),
srbD->csubufoffsets.batches[i].resources.constData(),
srbD->csubufsizes.batches[i].resources.constData());
} else {
QVarLengthArray<UINT, 4> offsets;
applyDynamicOffsets(&offsets, i, &srbD->csubufs, &srbD->csubufoffsets, dynOfsPairs, dynOfsPairCount);
context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
srbD->csubufs.batches[i].resources.count(),
srbD->csubufs.batches[i].resources.constData(),
offsets.constData(),
srbD->csubufsizes.batches[i].resources.constData());
}
}
for (int i = 0, ie = srbD->csUAVs.batches.count(); i != ie; ++i) {
const uint startBinding = srbD->csUAVs.batches[i].startBinding;
const uint count = srbD->csUAVs.batches[i].resources.count();
context->CSSetUnorderedAccessViews(startBinding,
count,
srbD->csUAVs.batches[i].resources.constData(),
nullptr);
contextState.csHighestActiveUavBinding = qMax<int>(contextState.csHighestActiveUavBinding,
startBinding + count - 1);
}
} }
void QRhiD3D11::setRenderTarget(QRhiRenderTarget *rt) void QRhiD3D11::resetShaderResources()
{ {
// The new output cannot be bound as input from the previous frame, // Output cannot be bound on input etc.
// otherwise the debug layer complains. Avoid this.
const int nullsrvCount = qMax(contextState.vsHighestActiveSrvBinding, contextState.fsHighestActiveSrvBinding) + 1; if (contextState.vsHasIndexBufferBound) {
context->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0);
contextState.vsHasIndexBufferBound = false;
}
if (contextState.vsHighestActiveVertexBufferBinding >= 0) {
const int count = contextState.vsHighestActiveVertexBufferBinding + 1;
QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
for (int i = 0; i < count; ++i)
nullbufs[i] = nullptr;
QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
for (int i = 0; i < count; ++i)
nullstrides[i] = 0;
QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
for (int i = 0; i < count; ++i)
nulloffsets[i] = 0;
context->IASetVertexBuffers(0, count, nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
contextState.vsHighestActiveVertexBufferBinding = -1;
}
int nullsrvCount = qMax(contextState.vsHighestActiveSrvBinding, contextState.fsHighestActiveSrvBinding);
nullsrvCount = qMax(nullsrvCount, contextState.csHighestActiveSrvBinding);
nullsrvCount += 1;
if (nullsrvCount > 0) { if (nullsrvCount > 0) {
QVarLengthArray<ID3D11ShaderResourceView *, QVarLengthArray<ID3D11ShaderResourceView *,
D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount); D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
@ -1732,9 +1919,21 @@ void QRhiD3D11::setRenderTarget(QRhiRenderTarget *rt)
context->PSSetShaderResources(0, contextState.fsHighestActiveSrvBinding + 1, nullsrvs.constData()); context->PSSetShaderResources(0, contextState.fsHighestActiveSrvBinding + 1, nullsrvs.constData());
contextState.fsHighestActiveSrvBinding = -1; contextState.fsHighestActiveSrvBinding = -1;
} }
if (contextState.csHighestActiveSrvBinding >= 0) {
context->CSSetShaderResources(0, contextState.csHighestActiveSrvBinding + 1, nullsrvs.constData());
contextState.csHighestActiveSrvBinding = -1;
}
}
if (contextState.csHighestActiveUavBinding >= 0) {
const int nulluavCount = contextState.csHighestActiveUavBinding + 1;
QVarLengthArray<ID3D11UnorderedAccessView *,
D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
for (int i = 0; i < nulluavCount; ++i)
nulluavs[i] = nullptr;
context->CSSetUnorderedAccessViews(0, nulluavCount, nulluavs.constData(), nullptr);
contextState.csHighestActiveUavBinding = -1;
} }
QD3D11RenderTargetData *rtD = rtData(rt);
context->OMSetRenderTargets(rtD->colorAttCount, rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
} }
void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain) void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain)
@ -1755,15 +1954,22 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
// it around by issuing a semi-fake OMSetRenderTargets early and // it around by issuing a semi-fake OMSetRenderTargets early and
// writing the first timestamp only afterwards. // writing the first timestamp only afterwards.
context->Begin(tsDisjoint); context->Begin(tsDisjoint);
setRenderTarget(&timestampSwapChain->rt); QD3D11RenderTargetData *rtD = rtData(&timestampSwapChain->rt);
context->OMSetRenderTargets(rtD->colorAttCount, rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
context->End(tsStart); // just record a timestamp, no Begin needed context->End(tsStart); // just record a timestamp, no Begin needed
} }
} }
for (const QD3D11CommandBuffer::Command &cmd : qAsConst(cbD->commands)) { for (const QD3D11CommandBuffer::Command &cmd : qAsConst(cbD->commands)) {
switch (cmd.cmd) { switch (cmd.cmd) {
case QD3D11CommandBuffer::Command::ResetShaderResources:
resetShaderResources();
break;
case QD3D11CommandBuffer::Command::SetRenderTarget: case QD3D11CommandBuffer::Command::SetRenderTarget:
setRenderTarget(cmd.args.setRenderTarget.rt); {
QD3D11RenderTargetData *rtD = rtData(cmd.args.setRenderTarget.rt);
context->OMSetRenderTargets(rtD->colorAttCount, rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
}
break; break;
case QD3D11CommandBuffer::Command::Clear: case QD3D11CommandBuffer::Command::Clear:
{ {
@ -1805,6 +2011,9 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
} }
break; break;
case QD3D11CommandBuffer::Command::BindVertexBuffers: case QD3D11CommandBuffer::Command::BindVertexBuffers:
contextState.vsHighestActiveVertexBufferBinding = qMax<int>(
contextState.vsHighestActiveVertexBufferBinding,
cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
context->IASetVertexBuffers(cmd.args.bindVertexBuffers.startSlot, context->IASetVertexBuffers(cmd.args.bindVertexBuffers.startSlot,
cmd.args.bindVertexBuffers.slotCount, cmd.args.bindVertexBuffers.slotCount,
cmd.args.bindVertexBuffers.buffers, cmd.args.bindVertexBuffers.buffers,
@ -1812,6 +2021,7 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
cmd.args.bindVertexBuffers.offsets); cmd.args.bindVertexBuffers.offsets);
break; break;
case QD3D11CommandBuffer::Command::BindIndexBuffer: case QD3D11CommandBuffer::Command::BindIndexBuffer:
contextState.vsHasIndexBufferBound = true;
context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer, context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
cmd.args.bindIndexBuffer.format, cmd.args.bindIndexBuffer.format,
cmd.args.bindIndexBuffer.offset); cmd.args.bindIndexBuffer.offset);
@ -1894,6 +2104,12 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
case QD3D11CommandBuffer::Command::DebugMarkMsg: case QD3D11CommandBuffer::Command::DebugMarkMsg:
annotations->SetMarker(reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16())); annotations->SetMarker(reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
break; break;
case QD3D11CommandBuffer::Command::BindComputePipeline:
context->CSSetShader(cmd.args.bindComputePipeline.ps->cs, nullptr, 0);
break;
case QD3D11CommandBuffer::Command::Dispatch:
context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
break;
default: default:
break; break;
} }
@ -1920,6 +2136,11 @@ void QD3D11Buffer::release()
buffer->Release(); buffer->Release();
buffer = nullptr; buffer = nullptr;
if (uav) {
uav->Release();
uav = nullptr;
}
QRHI_RES_RHI(QRhiD3D11); QRHI_RES_RHI(QRhiD3D11);
QRHI_PROF; QRHI_PROF;
QRHI_PROF_F(releaseBuffer(this)); QRHI_PROF_F(releaseBuffer(this));
@ -1935,6 +2156,8 @@ static inline uint toD3DBufferUsage(QRhiBuffer::UsageFlags usage)
u |= D3D11_BIND_INDEX_BUFFER; u |= D3D11_BIND_INDEX_BUFFER;
if (usage.testFlag(QRhiBuffer::UniformBuffer)) if (usage.testFlag(QRhiBuffer::UniformBuffer))
u |= D3D11_BIND_CONSTANT_BUFFER; u |= D3D11_BIND_CONSTANT_BUFFER;
if (usage.testFlag(QRhiBuffer::StorageBuffer))
u |= D3D11_BIND_UNORDERED_ACCESS;
return u; return u;
} }
@ -1948,8 +2171,13 @@ bool QD3D11Buffer::build()
return false; return false;
} }
if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
qWarning("StorageBuffer cannot be combined with Dynamic");
return false;
}
const int nonZeroSize = m_size <= 0 ? 256 : m_size; const int nonZeroSize = m_size <= 0 ? 256 : m_size;
const int roundedSize = m_usage.testFlag(QRhiBuffer::UniformBuffer) ? aligned(nonZeroSize, 256) : nonZeroSize; const int roundedSize = aligned(nonZeroSize, m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256 : 4);
D3D11_BUFFER_DESC desc; D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
@ -1957,6 +2185,7 @@ bool QD3D11Buffer::build()
desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
desc.BindFlags = toD3DBufferUsage(m_usage); desc.BindFlags = toD3DBufferUsage(m_usage);
desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0; desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
QRHI_RES_RHI(QRhiD3D11); QRHI_RES_RHI(QRhiD3D11);
HRESULT hr = rhiD->dev->CreateBuffer(&desc, nullptr, &buffer); HRESULT hr = rhiD->dev->CreateBuffer(&desc, nullptr, &buffer);
@ -1981,6 +2210,30 @@ bool QD3D11Buffer::build()
return true; return true;
} }
ID3D11UnorderedAccessView *QD3D11Buffer::unorderedAccessView()
{
if (uav)
return uav;
// SPIRV-Cross generated HLSL uses RWByteAddressBuffer
D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
memset(&desc, 0, sizeof(desc));
desc.Format = DXGI_FORMAT_R32_TYPELESS;
desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
desc.Buffer.FirstElement = 0;
desc.Buffer.NumElements = aligned(m_size, 4) / 4;
desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
QRHI_RES_RHI(QRhiD3D11);
HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
if (FAILED(hr)) {
qWarning("Failed to create UAV: %s", qPrintable(comErrorMessage(hr)));
return nullptr;
}
return uav;
}
QD3D11RenderBuffer::QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, QD3D11RenderBuffer::QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
int sampleCount, QRhiRenderBuffer::Flags flags) int sampleCount, QRhiRenderBuffer::Flags flags)
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags) : QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags)
@ -2097,6 +2350,8 @@ QD3D11Texture::QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize
int sampleCount, Flags flags) int sampleCount, Flags flags)
: QRhiTexture(rhi, format, pixelSize, sampleCount, flags) : QRhiTexture(rhi, format, pixelSize, sampleCount, flags)
{ {
for (int i = 0; i < QRhi::MAX_LEVELS; ++i)
perLevelViews[i] = nullptr;
} }
QD3D11Texture::~QD3D11Texture() QD3D11Texture::~QD3D11Texture()
@ -2114,6 +2369,13 @@ void QD3D11Texture::release()
srv = nullptr; srv = nullptr;
} }
for (int i = 0; i < QRhi::MAX_LEVELS; ++i) {
if (perLevelViews[i]) {
perLevelViews[i]->Release();
perLevelViews[i] = nullptr;
}
}
if (owns) if (owns)
tex->Release(); tex->Release();
@ -2244,6 +2506,8 @@ bool QD3D11Texture::build()
bindFlags |= D3D11_BIND_RENDER_TARGET; bindFlags |= D3D11_BIND_RENDER_TARGET;
miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
} }
if (m_flags.testFlag(UsedWithLoadStore))
bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
D3D11_TEXTURE2D_DESC desc; D3D11_TEXTURE2D_DESC desc;
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
@ -2306,6 +2570,37 @@ const QRhiNativeHandles *QD3D11Texture::nativeHandles()
return &nativeHandlesStruct; return &nativeHandlesStruct;
} }
ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level)
{
if (perLevelViews[level])
return perLevelViews[level];
const bool isCube = m_flags.testFlag(CubeMap);
D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
memset(&desc, 0, sizeof(desc));
desc.Format = dxgiFormat;
if (isCube) {
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
desc.Texture2DArray.MipSlice = level;
desc.Texture2DArray.FirstArraySlice = 0;
desc.Texture2DArray.ArraySize = 6;
} else {
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
desc.Texture2D.MipSlice = level;
}
QRHI_RES_RHI(QRhiD3D11);
ID3D11UnorderedAccessView *uav = nullptr;
HRESULT hr = rhiD->dev->CreateUnorderedAccessView(tex, &desc, &uav);
if (FAILED(hr)) {
qWarning("Failed to create UAV: %s", qPrintable(comErrorMessage(hr)));
return nullptr;
}
perLevelViews[level] = uav;
return uav;
}
QD3D11Sampler::QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, QD3D11Sampler::QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
AddressMode u, AddressMode v) AddressMode u, AddressMode v)
: QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v) : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
@ -3121,11 +3416,40 @@ QD3D11ComputePipeline::~QD3D11ComputePipeline()
void QD3D11ComputePipeline::release() void QD3D11ComputePipeline::release()
{ {
QRHI_RES_RHI(QRhiD3D11);
if (!cs)
return;
cs->Release();
cs = nullptr;
rhiD->unregisterResource(this);
} }
bool QD3D11ComputePipeline::build() bool QD3D11ComputePipeline::build()
{ {
return false; if (cs)
release();
QRHI_RES_RHI(QRhiD3D11);
QString error;
QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error);
if (bytecode.isEmpty()) {
qWarning("HLSL compute shader compilation failed: %s", qPrintable(error));
return false;
}
HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), bytecode.size(), nullptr, &cs);
if (FAILED(hr)) {
qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
generation += 1;
rhiD->registerResource(this);
return true;
} }
QD3D11CommandBuffer::QD3D11CommandBuffer(QRhiImplementation *rhi) QD3D11CommandBuffer::QD3D11CommandBuffer(QRhiImplementation *rhi)

View File

@ -65,9 +65,12 @@ struct QD3D11Buffer : public QRhiBuffer
void release() override; void release() override;
bool build() override; bool build() override;
ID3D11UnorderedAccessView *unorderedAccessView();
ID3D11Buffer *buffer = nullptr; ID3D11Buffer *buffer = nullptr;
QByteArray dynBuf; QByteArray dynBuf;
bool hasPendingDynamicUpdates = false; bool hasPendingDynamicUpdates = false;
ID3D11UnorderedAccessView *uav = nullptr;
uint generation = 0; uint generation = 0;
friend class QRhiD3D11; friend class QRhiD3D11;
}; };
@ -101,6 +104,7 @@ struct QD3D11Texture : public QRhiTexture
bool prepareBuild(QSize *adjustedSize = nullptr); bool prepareBuild(QSize *adjustedSize = nullptr);
bool finishBuild(); bool finishBuild();
ID3D11UnorderedAccessView *unorderedAccessViewForLevel(int level);
ID3D11Texture2D *tex = nullptr; ID3D11Texture2D *tex = nullptr;
bool owns = true; bool owns = true;
@ -109,6 +113,7 @@ struct QD3D11Texture : public QRhiTexture
uint mipLevelCount = 0; uint mipLevelCount = 0;
DXGI_SAMPLE_DESC sampleDesc; DXGI_SAMPLE_DESC sampleDesc;
QRhiD3D11TextureNativeHandles nativeHandlesStruct; QRhiD3D11TextureNativeHandles nativeHandlesStruct;
ID3D11UnorderedAccessView *perLevelViews[QRhi::MAX_LEVELS];
uint generation = 0; uint generation = 0;
friend class QRhiD3D11; friend class QRhiD3D11;
}; };
@ -209,10 +214,20 @@ struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
quint64 samplerId; quint64 samplerId;
uint samplerGeneration; uint samplerGeneration;
}; };
struct BoundStorageImageData {
quint64 id;
uint generation;
};
struct BoundStorageBufferData {
quint64 id;
uint generation;
};
struct BoundResourceData { struct BoundResourceData {
union { union {
BoundUniformBufferData ubuf; BoundUniformBufferData ubuf;
BoundSampledTextureData stex; BoundSampledTextureData stex;
BoundStorageImageData simage;
BoundStorageBufferData sbuf;
}; };
}; };
QVector<BoundResourceData> boundResourceData; QVector<BoundResourceData> boundResourceData;
@ -225,12 +240,21 @@ struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
QRhiBatchedBindings<UINT> fsubufoffsets; QRhiBatchedBindings<UINT> fsubufoffsets;
QRhiBatchedBindings<UINT> fsubufsizes; QRhiBatchedBindings<UINT> fsubufsizes;
QRhiBatchedBindings<ID3D11Buffer *> csubufs;
QRhiBatchedBindings<UINT> csubufoffsets;
QRhiBatchedBindings<UINT> csubufsizes;
QRhiBatchedBindings<ID3D11SamplerState *> vssamplers; QRhiBatchedBindings<ID3D11SamplerState *> vssamplers;
QRhiBatchedBindings<ID3D11ShaderResourceView *> vsshaderresources; QRhiBatchedBindings<ID3D11ShaderResourceView *> vsshaderresources;
QRhiBatchedBindings<ID3D11SamplerState *> fssamplers; QRhiBatchedBindings<ID3D11SamplerState *> fssamplers;
QRhiBatchedBindings<ID3D11ShaderResourceView *> fsshaderresources; QRhiBatchedBindings<ID3D11ShaderResourceView *> fsshaderresources;
QRhiBatchedBindings<ID3D11SamplerState *> cssamplers;
QRhiBatchedBindings<ID3D11ShaderResourceView *> csshaderresources;
QRhiBatchedBindings<ID3D11UnorderedAccessView *> csUAVs;
friend class QRhiD3D11; friend class QRhiD3D11;
}; };
@ -260,6 +284,10 @@ struct QD3D11ComputePipeline : public QRhiComputePipeline
~QD3D11ComputePipeline(); ~QD3D11ComputePipeline();
void release() override; void release() override;
bool build() override; bool build() override;
ID3D11ComputeShader *cs = nullptr;
uint generation = 0;
friend class QRhiD3D11;
}; };
struct QD3D11SwapChain; struct QD3D11SwapChain;
@ -272,6 +300,7 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
struct Command { struct Command {
enum Cmd { enum Cmd {
ResetShaderResources,
SetRenderTarget, SetRenderTarget,
Clear, Clear,
Viewport, Viewport,
@ -290,7 +319,9 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
GenMip, GenMip,
DebugMarkBegin, DebugMarkBegin,
DebugMarkEnd, DebugMarkEnd,
DebugMarkMsg DebugMarkMsg,
BindComputePipeline,
Dispatch
}; };
enum ClearFlag { Color = 1, Depth = 2, Stencil = 4 }; enum ClearFlag { Color = 1, Depth = 2, Stencil = 4 };
Cmd cmd; Cmd cmd;
@ -392,6 +423,14 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
struct { struct {
char s[64]; char s[64];
} debugMark; } debugMark;
struct {
QD3D11ComputePipeline *ps;
} bindComputePipeline;
struct {
UINT x;
UINT y;
UINT z;
} dispatch;
} args; } args;
}; };
@ -404,9 +443,11 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
QVector<Command> commands; QVector<Command> commands;
PassType recordingPass; PassType recordingPass;
QRhiRenderTarget *currentTarget; QRhiRenderTarget *currentTarget;
QRhiGraphicsPipeline *currentPipeline; QRhiGraphicsPipeline *currentGraphicsPipeline;
QRhiComputePipeline *currentComputePipeline;
uint currentPipelineGeneration; uint currentPipelineGeneration;
QRhiShaderResourceBindings *currentSrb; QRhiShaderResourceBindings *currentGraphicsSrb;
QRhiShaderResourceBindings *currentComputeSrb;
uint currentSrbGeneration; uint currentSrbGeneration;
ID3D11Buffer *currentIndexBuffer; ID3D11Buffer *currentIndexBuffer;
quint32 currentIndexOffset; quint32 currentIndexOffset;
@ -438,9 +479,11 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
resetCachedState(); resetCachedState();
} }
void resetCachedState() { void resetCachedState() {
currentPipeline = nullptr; currentGraphicsPipeline = nullptr;
currentComputePipeline = nullptr;
currentPipelineGeneration = 0; currentPipelineGeneration = 0;
currentSrb = nullptr; currentGraphicsSrb = nullptr;
currentComputeSrb = nullptr;
currentSrbGeneration = 0; currentSrbGeneration = 0;
currentIndexBuffer = nullptr; currentIndexBuffer = nullptr;
currentIndexOffset = 0; currentIndexOffset = 0;
@ -596,11 +639,10 @@ public:
void bindShaderResources(QD3D11ShaderResourceBindings *srbD, void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
const uint *dynOfsPairs, int dynOfsPairCount, const uint *dynOfsPairs, int dynOfsPairCount,
bool offsetOnlyChange); bool offsetOnlyChange);
void setRenderTarget(QRhiRenderTarget *rt); void resetShaderResources();
void executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain = nullptr); void executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain = nullptr);
DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount) const; DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount) const;
void finishActiveReadbacks(); void finishActiveReadbacks();
void enqueueSetRenderTarget(QD3D11CommandBuffer *cbD, QRhiRenderTarget *rt);
void reportLiveObjects(ID3D11Device *device); void reportLiveObjects(ID3D11Device *device);
bool debugLayer = false; bool debugLayer = false;
@ -614,8 +656,12 @@ public:
QRhiD3D11NativeHandles nativeHandlesStruct; QRhiD3D11NativeHandles nativeHandlesStruct;
struct { struct {
int vsHighestActiveVertexBufferBinding = -1;
bool vsHasIndexBufferBound = false;
int vsHighestActiveSrvBinding = -1; int vsHighestActiveSrvBinding = -1;
int fsHighestActiveSrvBinding = -1; int fsHighestActiveSrvBinding = -1;
int csHighestActiveSrvBinding = -1;
int csHighestActiveUavBinding = -1;
QD3D11SwapChain *currentSwapChain = nullptr; QD3D11SwapChain *currentSwapChain = nullptr;
} contextState; } contextState;