rhi: gl: Fix an srb tracking issue

Have two pipelines that are used with the same srb:

setPipeline(a);
setShaderResources(s);
draw
setPipeline(b);
setShaderResources(s);
draw

If this is repeated each frame, then on the second an subsequent frames
the uniforms for the program behind pipeline b will not be set,
i.e. the glUniformxx calls will be missing.

This is due to the pipeline's own srb tracking
(currentSrb/currentSrbgeneration) works: in the second frame
setShaderResources(s) for pipeline b will do nothing, since
the command buffer's tracked current srb is already s, and
also b's currentSrb is already s.

The problem remains hidden usually because Quick or Quick 3D
does not generate sequences like the above (same srb with different
pipelines).

Pick-to: 6.9 6.8
Change-Id: I56b962f0ba12370e0de7c87fb7178a0b9e4b0178
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
Laszlo Agocs 2025-03-03 17:04:17 +01:00 committed by Laszlo Agocs
parent 25394fab9a
commit e9fa3e4244
2 changed files with 14 additions and 4 deletions

View File

@ -1893,6 +1893,11 @@ void QRhiGles2::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
cbD->currentGraphicsPipeline = ps;
cbD->currentComputePipeline = nullptr;
cbD->currentPipelineGeneration = psD->generation;
if (psD->lastUsedInFrameNo != frameNo) {
psD->lastUsedInFrameNo = frameNo;
psD->currentSrb = nullptr;
psD->currentSrbGeneration = 0;
}
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::BindGraphicsPipeline;
@ -2288,6 +2293,7 @@ QRhi::FrameOpResult QRhiGles2::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginF
executeDeferredReleases();
swapChainD->cb.resetState();
frameNo += 1;
if (swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex]) {
double elapsedSec = 0;
@ -2331,7 +2337,6 @@ QRhi::FrameOpResult QRhiGles2::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
f->glFlush();
}
swapChainD->frameCount += 1;
currentSwapChain = nullptr;
ctx->handle()->endFrame();
@ -4906,6 +4911,11 @@ void QRhiGles2::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *p
cbD->currentGraphicsPipeline = nullptr;
cbD->currentComputePipeline = ps;
cbD->currentPipelineGeneration = psD->generation;
if (psD->lastUsedInFrameNo != frameNo) {
psD->lastUsedInFrameNo = frameNo;
psD->currentSrb = nullptr;
psD->currentSrbGeneration = 0;
}
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::BindComputePipeline;
@ -6862,8 +6872,6 @@ bool QGles2SwapChain::createOrResize()
rtRight.d.stereoTarget = QRhiSwapChain::RightBuffer;
}
frameCount = 0;
QRHI_RES_RHI(QRhiGles2);
if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps) && rhiD->caps.timestamps)
timestamps.prepare(rhiD);

View File

@ -279,6 +279,7 @@ struct QGles2GraphicsPipeline : public QRhiGraphicsPipeline
QGles2UniformState uniformState[QGles2UniformState::MAX_TRACKED_LOCATION + 1];
QRhiShaderResourceBindings *currentSrb = nullptr;
uint currentSrbGeneration = 0;
uint lastUsedInFrameNo = 0;
uint generation = 0;
friend class QRhiGles2;
};
@ -296,6 +297,7 @@ struct QGles2ComputePipeline : public QRhiComputePipeline
QGles2UniformState uniformState[QGles2UniformState::MAX_TRACKED_LOCATION + 1];
QRhiShaderResourceBindings *currentSrb = nullptr;
uint currentSrbGeneration = 0;
uint lastUsedInFrameNo = 0;
uint generation = 0;
friend class QRhiGles2;
};
@ -754,7 +756,6 @@ struct QGles2SwapChain : public QRhiSwapChain
QGles2SwapChainRenderTarget rtLeft;
QGles2SwapChainRenderTarget rtRight;
QGles2CommandBuffer cb;
int frameCount = 0;
QGles2SwapChainTimestamps timestamps;
int currentTimestampPairIndex = 0;
};
@ -1096,6 +1097,7 @@ public:
QRhiGles2NativeHandles nativeHandlesStruct;
QRhiDriverInfo driverInfoStruct;
mutable bool contextLost = false;
uint frameNo = 0;
struct DeferredReleaseEntry {
enum Type {