@@ -120,6 +120,8 @@ private slots:
120120 void renderToTextureArrayMultiView ();
121121 void renderToWindowSimple_data ();
122122 void renderToWindowSimple ();
123+ void continuousReadbackFromWindow_data ();
124+ void continuousReadbackFromWindow ();
123125 void finishWithinSwapchainFrame_data ();
124126 void finishWithinSwapchainFrame ();
125127 void resourceUpdateBatchBufferTextureWithSwapchainFrames_data ();
@@ -4088,6 +4090,84 @@ void tst_QRhi::renderToWindowSimple()
40884090 QVERIFY (redCount < blueCount);
40894091}
40904092
4093+ void tst_QRhi::continuousReadbackFromWindow_data ()
4094+ {
4095+ rhiTestData ();
4096+ }
4097+
4098+ void tst_QRhi::continuousReadbackFromWindow ()
4099+ {
4100+ if (QGuiApplication::platformName ().startsWith (QLatin1String (" offscreen" ), Qt::CaseInsensitive))
4101+ QSKIP (" Offscreen: This fails." );
4102+
4103+ QFETCH (QRhi::Implementation, impl);
4104+ QFETCH (QRhiInitParams *, initParams);
4105+
4106+ QScopedPointer<QRhi> rhi (QRhi::create (impl, initParams, QRhi::Flags (), nullptr ));
4107+ if (!rhi)
4108+ QSKIP (" QRhi could not be created, skipping testing rendering" );
4109+
4110+ QScopedPointer<QWindow> window (new QWindow);
4111+ setWindowType (window.data (), impl);
4112+
4113+ window->setGeometry (0 , 0 , 640 , 480 );
4114+ window->show ();
4115+ QVERIFY (QTest::qWaitForWindowExposed (window.data ()));
4116+
4117+ QScopedPointer<QRhiSwapChain> swapChain (rhi->newSwapChain ());
4118+ swapChain->setWindow (window.data ());
4119+ swapChain->setFlags (QRhiSwapChain::UsedAsTransferSource);
4120+ QScopedPointer<QRhiRenderPassDescriptor> rpDesc (swapChain->newCompatibleRenderPassDescriptor ());
4121+ swapChain->setRenderPassDescriptor (rpDesc.data ());
4122+ QVERIFY (swapChain->createOrResize ());
4123+
4124+ QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch ();
4125+
4126+ QScopedPointer<QRhiBuffer> vbuf (rhi->newBuffer (QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof (triangleVertices)));
4127+ QVERIFY (vbuf->create ());
4128+ updates->uploadStaticBuffer (vbuf.data (), triangleVertices);
4129+
4130+ QScopedPointer<QRhiShaderResourceBindings> srb (rhi->newShaderResourceBindings ());
4131+ QVERIFY (srb->create ());
4132+
4133+ QScopedPointer<QRhiGraphicsPipeline> pipeline (createSimplePipeline (rhi.data (), srb.data (), rpDesc.data ()));
4134+ QVERIFY (pipeline);
4135+
4136+ const int asyncReadbackFrames = rhi->resourceLimit (QRhi::MaxAsyncReadbackFrames);
4137+ const int FRAME_COUNT = asyncReadbackFrames * 10 ;
4138+ QVector<QRhiReadbackResult> readResults (FRAME_COUNT);
4139+ int readbackCompletedCount = 0 ;
4140+
4141+ for (int frameNo = 0 ; frameNo < FRAME_COUNT; ++frameNo) {
4142+ QVERIFY (rhi->beginFrame (swapChain.data ()) == QRhi::FrameOpSuccess);
4143+ QRhiCommandBuffer *cb = swapChain->currentFrameCommandBuffer ();
4144+ QRhiRenderTarget *rt = swapChain->currentFrameRenderTarget ();
4145+ const QSize outputSize = swapChain->currentPixelSize ();
4146+ QRhiViewport viewport (0 , 0 , float (outputSize.width ()), float (outputSize.height ()));
4147+
4148+ cb->beginPass (rt, Qt::blue, { 1 .0f , 0 }, updates);
4149+ updates = nullptr ;
4150+ cb->setGraphicsPipeline (pipeline.data ());
4151+ cb->setViewport (viewport);
4152+ QRhiCommandBuffer::VertexInput vbindings (vbuf.data (), 0 );
4153+ cb->setVertexInput (0 , 1 , &vbindings);
4154+ cb->draw (3 );
4155+
4156+ readResults[frameNo].completed = [&readbackCompletedCount] {
4157+ readbackCompletedCount += 1 ;
4158+ };
4159+ QRhiResourceUpdateBatch *readbackBatch = rhi->nextResourceUpdateBatch ();
4160+ readbackBatch->readBackTexture ({}, &readResults[frameNo]); // read back the current backbuffer
4161+ cb->endPass (readbackBatch);
4162+
4163+ rhi->endFrame (swapChain.data ());
4164+ }
4165+
4166+ QVERIFY (readbackCompletedCount >= FRAME_COUNT - asyncReadbackFrames);
4167+ rhi->finish ();
4168+ QCOMPARE (readbackCompletedCount, FRAME_COUNT);
4169+ }
4170+
40914171void tst_QRhi::finishWithinSwapchainFrame_data ()
40924172{
40934173 rhiTestData ();
0 commit comments