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->csSamplerBatches.clear();
|
||||||
|
|
||||||
srbD->csUavBatches.clear();
|
srbD->csUavBatches.clear();
|
||||||
|
srbD->fsUavBatches.clear();
|
||||||
|
|
||||||
struct Stage {
|
struct Stage {
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
@ -2587,8 +2588,15 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
|
|||||||
if (uav)
|
if (uav)
|
||||||
res[RBM_COMPUTE].uavs.append({ nativeBinding.first, 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 {
|
} else {
|
||||||
qWarning("Unordered access only supported at compute stage");
|
qWarning("Unordered access only supported at fragment/compute stage");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2650,6 +2658,7 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
|
|||||||
res[RBM_FRAGMENT].buildSamplerBatches(srbD->fsSamplerBatches);
|
res[RBM_FRAGMENT].buildSamplerBatches(srbD->fsSamplerBatches);
|
||||||
res[RBM_COMPUTE].buildSamplerBatches(srbD->csSamplerBatches);
|
res[RBM_COMPUTE].buildSamplerBatches(srbD->csSamplerBatches);
|
||||||
|
|
||||||
|
res[RBM_FRAGMENT].buildUavBatches(srbD->fsUavBatches);
|
||||||
res[RBM_COMPUTE].buildUavBatches(srbD->csUavBatches);
|
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,
|
void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
|
||||||
const uint *dynOfsPairs, int dynOfsPairCount,
|
const uint *dynOfsPairs, int dynOfsPairCount,
|
||||||
bool offsetOnlyChange)
|
bool offsetOnlyChange,
|
||||||
|
QD3D11RenderTargetData *rtD,
|
||||||
|
RenderTargetUavUpdateState &rtUavState)
|
||||||
{
|
{
|
||||||
UINT offsets[QD3D11CommandBuffer::MAX_DYNAMIC_OFFSET_COUNT];
|
UINT offsets[QD3D11CommandBuffer::MAX_DYNAMIC_OFFSET_COUNT];
|
||||||
|
|
||||||
@ -2791,10 +2802,27 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
|
|||||||
SETSAMPLERBATCH(cs, CS)
|
SETSAMPLERBATCH(cs, CS)
|
||||||
|
|
||||||
SETUAVBATCH(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.
|
// 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) {
|
if (contextState.csHighestActiveUavBinding >= 0) {
|
||||||
const int nulluavCount = contextState.csHighestActiveUavBinding + 1;
|
const int nulluavCount = contextState.csHighestActiveUavBinding + 1;
|
||||||
QVarLengthArray<ID3D11UnorderedAccessView *,
|
QVarLengthArray<ID3D11UnorderedAccessView *,
|
||||||
@ -2888,6 +2921,10 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD)
|
|||||||
};
|
};
|
||||||
int currentShaderMask = 0xFF;
|
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) {
|
for (auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
|
||||||
const QD3D11CommandBuffer::Command &cmd(*it);
|
const QD3D11CommandBuffer::Command &cmd(*it);
|
||||||
switch (cmd.cmd) {
|
switch (cmd.cmd) {
|
||||||
@ -2901,7 +2938,9 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD)
|
|||||||
// 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.
|
||||||
QD3D11RenderTargetData *rtD = cmd.args.beginFrame.swapchainData;
|
QD3D11RenderTargetData *rtD = cmd.args.beginFrame.swapchainData;
|
||||||
|
rtUavState.update(rtD);
|
||||||
context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
|
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
|
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);
|
context->End(cmd.args.endFrame.tsDisjointQuery);
|
||||||
break;
|
break;
|
||||||
case QD3D11CommandBuffer::Command::ResetShaderResources:
|
case QD3D11CommandBuffer::Command::ResetShaderResources:
|
||||||
resetShaderResources();
|
resetShaderResources(cbD->prevRtD, rtUavState);
|
||||||
break;
|
break;
|
||||||
case QD3D11CommandBuffer::Command::SetRenderTarget:
|
case QD3D11CommandBuffer::Command::SetRenderTarget:
|
||||||
{
|
{
|
||||||
QD3D11RenderTargetData *rtD = rtData(cmd.args.setRenderTarget.rt);
|
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;
|
break;
|
||||||
case QD3D11CommandBuffer::Command::Clear:
|
case QD3D11CommandBuffer::Command::Clear:
|
||||||
@ -2995,7 +3036,9 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD)
|
|||||||
bindShaderResources(cmd.args.bindShaderResources.srb,
|
bindShaderResources(cmd.args.bindShaderResources.srb,
|
||||||
cmd.args.bindShaderResources.dynamicOffsetPairs,
|
cmd.args.bindShaderResources.dynamicOffsetPairs,
|
||||||
cmd.args.bindShaderResources.dynamicOffsetCount,
|
cmd.args.bindShaderResources.dynamicOffsetCount,
|
||||||
cmd.args.bindShaderResources.offsetOnlyChange);
|
cmd.args.bindShaderResources.offsetOnlyChange,
|
||||||
|
cbD->prevRtD,
|
||||||
|
rtUavState);
|
||||||
break;
|
break;
|
||||||
case QD3D11CommandBuffer::Command::StencilRef:
|
case QD3D11CommandBuffer::Command::StencilRef:
|
||||||
stencilRef = cmd.args.stencilRef.ref;
|
stencilRef = cmd.args.stencilRef.ref;
|
||||||
@ -5547,4 +5590,31 @@ bool QD3D11SwapChain::createOrResize()
|
|||||||
return true;
|
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
|
QT_END_NAMESPACE
|
||||||
|
@ -180,6 +180,14 @@ struct QD3D11TextureRenderTarget : public QRhiTextureRenderTarget
|
|||||||
friend class QRhiD3D11;
|
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
|
struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
|
||||||
{
|
{
|
||||||
QD3D11ShaderResourceBindings(QRhiImplementation *rhi);
|
QD3D11ShaderResourceBindings(QRhiImplementation *rhi);
|
||||||
@ -285,6 +293,7 @@ struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
|
|||||||
StageSamplerBatches csSamplerBatches;
|
StageSamplerBatches csSamplerBatches;
|
||||||
|
|
||||||
StageUavBatches csUavBatches;
|
StageUavBatches csUavBatches;
|
||||||
|
StageUavBatches fsUavBatches;
|
||||||
|
|
||||||
friend class QRhiD3D11;
|
friend class QRhiD3D11;
|
||||||
};
|
};
|
||||||
@ -521,6 +530,7 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
|||||||
DXGI_FORMAT currentIndexFormat;
|
DXGI_FORMAT currentIndexFormat;
|
||||||
ID3D11Buffer *currentVertexBuffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
ID3D11Buffer *currentVertexBuffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
||||||
quint32 currentVertexOffsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
quint32 currentVertexOffsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
||||||
|
QD3D11RenderTargetData *prevRtD;
|
||||||
|
|
||||||
QVarLengthArray<QByteArray, 4> dataRetainPool;
|
QVarLengthArray<QByteArray, 4> dataRetainPool;
|
||||||
QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool;
|
QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool;
|
||||||
@ -549,6 +559,7 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
|||||||
recordingPass = NoPass;
|
recordingPass = NoPass;
|
||||||
// do not zero lastGpuTime
|
// do not zero lastGpuTime
|
||||||
currentTarget = nullptr;
|
currentTarget = nullptr;
|
||||||
|
prevRtD = nullptr;
|
||||||
resetCommands();
|
resetCommands();
|
||||||
resetCachedState();
|
resetCachedState();
|
||||||
}
|
}
|
||||||
@ -762,10 +773,11 @@ public:
|
|||||||
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
|
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
|
||||||
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]);
|
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]);
|
||||||
void executeBufferHostWrites(QD3D11Buffer *bufD);
|
void executeBufferHostWrites(QD3D11Buffer *bufD);
|
||||||
|
|
||||||
void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
|
void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
|
||||||
const uint *dynOfsPairs, int dynOfsPairCount,
|
const uint *dynOfsPairs, int dynOfsPairCount,
|
||||||
bool offsetOnlyChange);
|
bool offsetOnlyChange, QD3D11RenderTargetData *rtD, RenderTargetUavUpdateState &rtUavState);
|
||||||
void resetShaderResources();
|
void resetShaderResources(QD3D11RenderTargetData *rtD, RenderTargetUavUpdateState &rtUavState);
|
||||||
void executeCommandBuffer(QD3D11CommandBuffer *cbD);
|
void executeCommandBuffer(QD3D11CommandBuffer *cbD);
|
||||||
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const;
|
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const;
|
||||||
void finishActiveReadbacks();
|
void finishActiveReadbacks();
|
||||||
@ -803,6 +815,7 @@ public:
|
|||||||
int fsHighestActiveSrvBinding = -1;
|
int fsHighestActiveSrvBinding = -1;
|
||||||
int csHighestActiveSrvBinding = -1;
|
int csHighestActiveSrvBinding = -1;
|
||||||
int csHighestActiveUavBinding = -1;
|
int csHighestActiveUavBinding = -1;
|
||||||
|
int fsHighestActiveUavBinding = -1;
|
||||||
QD3D11SwapChain *currentSwapChain = nullptr;
|
QD3D11SwapChain *currentSwapChain = nullptr;
|
||||||
} contextState;
|
} contextState;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user