Add UAVs for fragment stage on DX11
Add support for UAV's in fragment stage. UAV's are required to implement order independent transparency. Task-number: QTBUG-130332 Change-Id: Ia539ff3f94df43d3276d1d242091d55eafcbfadb Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
parent
d8ac4cd869
commit
cf037274d1
@ -2392,6 +2392,7 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
|
||||
srbD->csSamplerBatches.clear();
|
||||
|
||||
srbD->csUavBatches.clear();
|
||||
srbD->fsUavBatches.clear();
|
||||
|
||||
struct Stage {
|
||||
struct Buffer {
|
||||
@ -2587,8 +2588,15 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
|
||||
if (uav)
|
||||
res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
|
||||
}
|
||||
} else if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
|
||||
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
|
||||
if (nativeBinding.first >= 0) {
|
||||
ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
|
||||
if (uav)
|
||||
res[RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
|
||||
}
|
||||
} else {
|
||||
qWarning("Unordered access only supported at compute stage");
|
||||
qWarning("Unordered access only supported at fragment/compute stage");
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2650,6 +2658,7 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
|
||||
res[RBM_FRAGMENT].buildSamplerBatches(srbD->fsSamplerBatches);
|
||||
res[RBM_COMPUTE].buildSamplerBatches(srbD->csSamplerBatches);
|
||||
|
||||
res[RBM_FRAGMENT].buildUavBatches(srbD->fsUavBatches);
|
||||
res[RBM_COMPUTE].buildUavBatches(srbD->csUavBatches);
|
||||
}
|
||||
|
||||
@ -2771,7 +2780,9 @@ static inline uint clampedResourceCount(uint startSlot, int countSlots, uint max
|
||||
|
||||
void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
|
||||
const uint *dynOfsPairs, int dynOfsPairCount,
|
||||
bool offsetOnlyChange)
|
||||
bool offsetOnlyChange,
|
||||
QD3D11RenderTargetData *rtD,
|
||||
RenderTargetUavUpdateState &rtUavState)
|
||||
{
|
||||
UINT offsets[QD3D11CommandBuffer::MAX_DYNAMIC_OFFSET_COUNT];
|
||||
|
||||
@ -2791,10 +2802,27 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
|
||||
SETSAMPLERBATCH(cs, CS)
|
||||
|
||||
SETUAVBATCH(cs, CS)
|
||||
|
||||
if (srbD->fsUavBatches.present) {
|
||||
for (const auto &batch : srbD->fsUavBatches.uavs.batches) {
|
||||
const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
|
||||
D3D11_1_UAV_SLOT_COUNT, "fs UAV"),
|
||||
uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
|
||||
if (count) {
|
||||
if (rtUavState.update(rtD, batch.resources.constData(), count)) {
|
||||
context->OMSetRenderTargetsAndUnorderedAccessViews(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv,
|
||||
UINT(rtD->colorAttCount), count, batch.resources.constData(), nullptr);
|
||||
}
|
||||
contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
|
||||
int(batch.startBinding + count) - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QRhiD3D11::resetShaderResources()
|
||||
void QRhiD3D11::resetShaderResources(QD3D11RenderTargetData *rtD,
|
||||
RenderTargetUavUpdateState &rtUavState)
|
||||
{
|
||||
// Output cannot be bound on input etc.
|
||||
|
||||
@ -2855,6 +2883,11 @@ void QRhiD3D11::resetShaderResources()
|
||||
}
|
||||
}
|
||||
|
||||
if (contextState.fsHighestActiveUavBinding >= 0) {
|
||||
rtUavState.update(rtD);
|
||||
context->OMSetRenderTargetsAndUnorderedAccessViews(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv, 0, 0, nullptr, nullptr);
|
||||
contextState.fsHighestActiveUavBinding = -1;
|
||||
}
|
||||
if (contextState.csHighestActiveUavBinding >= 0) {
|
||||
const int nulluavCount = contextState.csHighestActiveUavBinding + 1;
|
||||
QVarLengthArray<ID3D11UnorderedAccessView *,
|
||||
@ -2888,6 +2921,10 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD)
|
||||
};
|
||||
int currentShaderMask = 0xFF;
|
||||
|
||||
// Track render target and uav updates during executeCommandBuffer.
|
||||
// Prevents multiple identical OMSetRenderTargetsAndUnorderedAccessViews calls.
|
||||
RenderTargetUavUpdateState rtUavState;
|
||||
|
||||
for (auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
|
||||
const QD3D11CommandBuffer::Command &cmd(*it);
|
||||
switch (cmd.cmd) {
|
||||
@ -2901,7 +2938,9 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD)
|
||||
// it around by issuing a semi-fake OMSetRenderTargets early and
|
||||
// writing the first timestamp only afterwards.
|
||||
QD3D11RenderTargetData *rtD = cmd.args.beginFrame.swapchainData;
|
||||
rtUavState.update(rtD);
|
||||
context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
|
||||
cbD->prevRtD = rtD;
|
||||
}
|
||||
context->End(cmd.args.beginFrame.tsQuery); // no Begin() for D3D11_QUERY_TIMESTAMP
|
||||
}
|
||||
@ -2913,12 +2952,14 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD)
|
||||
context->End(cmd.args.endFrame.tsDisjointQuery);
|
||||
break;
|
||||
case QD3D11CommandBuffer::Command::ResetShaderResources:
|
||||
resetShaderResources();
|
||||
resetShaderResources(cbD->prevRtD, rtUavState);
|
||||
break;
|
||||
case QD3D11CommandBuffer::Command::SetRenderTarget:
|
||||
{
|
||||
QD3D11RenderTargetData *rtD = rtData(cmd.args.setRenderTarget.rt);
|
||||
context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
|
||||
if (rtUavState.update(rtD))
|
||||
context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
|
||||
cbD->prevRtD = rtD;
|
||||
}
|
||||
break;
|
||||
case QD3D11CommandBuffer::Command::Clear:
|
||||
@ -2995,7 +3036,9 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD)
|
||||
bindShaderResources(cmd.args.bindShaderResources.srb,
|
||||
cmd.args.bindShaderResources.dynamicOffsetPairs,
|
||||
cmd.args.bindShaderResources.dynamicOffsetCount,
|
||||
cmd.args.bindShaderResources.offsetOnlyChange);
|
||||
cmd.args.bindShaderResources.offsetOnlyChange,
|
||||
cbD->prevRtD,
|
||||
rtUavState);
|
||||
break;
|
||||
case QD3D11CommandBuffer::Command::StencilRef:
|
||||
stencilRef = cmd.args.stencilRef.ref;
|
||||
@ -5547,4 +5590,31 @@ bool QD3D11SwapChain::createOrResize()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderTargetUavUpdateState::update(QD3D11RenderTargetData *data, ID3D11UnorderedAccessView *const *uavs, int count)
|
||||
{
|
||||
bool ret = false;
|
||||
if (dsv != data->dsv) {
|
||||
dsv = data->dsv;
|
||||
ret = true;
|
||||
}
|
||||
for (int i = 0; i < data->colorAttCount; i++) {
|
||||
ret |= rtv[i] != data->rtv[i];
|
||||
rtv[i] = data->rtv[i];
|
||||
}
|
||||
for (int i = data->colorAttCount; i < QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS; i++) {
|
||||
ret |= rtv[i] != nullptr;
|
||||
rtv[i] = nullptr;
|
||||
}
|
||||
for (int i = 0; i < count; i++) {
|
||||
ret |= uav[i] != uavs[i];
|
||||
uav[i] = uavs[i];
|
||||
}
|
||||
for (int i = count; i < QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS; i++) {
|
||||
ret |= uav[i] != nullptr;
|
||||
uav[i] = nullptr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -180,6 +180,14 @@ struct QD3D11TextureRenderTarget : public QRhiTextureRenderTarget
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct RenderTargetUavUpdateState
|
||||
{
|
||||
ID3D11RenderTargetView *rtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS];
|
||||
ID3D11DepthStencilView *dsv = nullptr;
|
||||
std::array<ID3D11UnorderedAccessView *, QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS> uav;
|
||||
bool update(QD3D11RenderTargetData *data, ID3D11UnorderedAccessView * const *uavs = nullptr, int count = 0);
|
||||
};
|
||||
|
||||
struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
|
||||
{
|
||||
QD3D11ShaderResourceBindings(QRhiImplementation *rhi);
|
||||
@ -285,6 +293,7 @@ struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
|
||||
StageSamplerBatches csSamplerBatches;
|
||||
|
||||
StageUavBatches csUavBatches;
|
||||
StageUavBatches fsUavBatches;
|
||||
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
@ -521,6 +530,7 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
||||
DXGI_FORMAT currentIndexFormat;
|
||||
ID3D11Buffer *currentVertexBuffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
||||
quint32 currentVertexOffsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
||||
QD3D11RenderTargetData *prevRtD;
|
||||
|
||||
QVarLengthArray<QByteArray, 4> dataRetainPool;
|
||||
QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool;
|
||||
@ -549,6 +559,7 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
||||
recordingPass = NoPass;
|
||||
// do not zero lastGpuTime
|
||||
currentTarget = nullptr;
|
||||
prevRtD = nullptr;
|
||||
resetCommands();
|
||||
resetCachedState();
|
||||
}
|
||||
@ -762,10 +773,11 @@ public:
|
||||
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
|
||||
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]);
|
||||
void executeBufferHostWrites(QD3D11Buffer *bufD);
|
||||
|
||||
void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
|
||||
const uint *dynOfsPairs, int dynOfsPairCount,
|
||||
bool offsetOnlyChange);
|
||||
void resetShaderResources();
|
||||
bool offsetOnlyChange, QD3D11RenderTargetData *rtD, RenderTargetUavUpdateState &rtUavState);
|
||||
void resetShaderResources(QD3D11RenderTargetData *rtD, RenderTargetUavUpdateState &rtUavState);
|
||||
void executeCommandBuffer(QD3D11CommandBuffer *cbD);
|
||||
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const;
|
||||
void finishActiveReadbacks();
|
||||
@ -803,6 +815,7 @@ public:
|
||||
int fsHighestActiveSrvBinding = -1;
|
||||
int csHighestActiveSrvBinding = -1;
|
||||
int csHighestActiveUavBinding = -1;
|
||||
int fsHighestActiveUavBinding = -1;
|
||||
QD3D11SwapChain *currentSwapChain = nullptr;
|
||||
} contextState;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user