summaryrefslogtreecommitdiffstats
path: root/tests/auto/gui/rhi
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2022-01-05 15:48:46 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2022-01-11 22:38:35 +0100
commitcdfbe7092304c3677e8fae95892f53852a90adfc (patch)
treebd6cb326fd2d0cf3edbb9254021f2d4f36efbb75 /tests/auto/gui/rhi
parent0be28d103089a1c5e196e6e722878f495dfc53ce (diff)
rhi: Improve the handling of HDR capable texture formats
Add some sort of autotest for both RGBA16F and the new RGB10A2. The latter is introduced particularly because ideally we should have a texture format that corresponds to the D3D/Vulkan swapchain color buffer format with HDR10. Change-Id: I1e1bbb7c7e32cb3db89275900811c0bcaeac39d6 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'tests/auto/gui/rhi')
-rw-r--r--tests/auto/gui/rhi/qrhi/BLACKLIST4
-rw-r--r--tests/auto/gui/rhi/qrhi/tst_qrhi.cpp383
2 files changed, 241 insertions, 146 deletions
diff --git a/tests/auto/gui/rhi/qrhi/BLACKLIST b/tests/auto/gui/rhi/qrhi/BLACKLIST
index 4e7b7dbc29..dc2bc57077 100644
--- a/tests/auto/gui/rhi/qrhi/BLACKLIST
+++ b/tests/auto/gui/rhi/qrhi/BLACKLIST
@@ -13,3 +13,7 @@ android
# Ditto
[renderToTextureSampleWithSeparateTextureAndSampler]
android
+[renderToFloatTexture]
+android
+[renderToRgb10Texture]
+android
diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
index 6a06fc4ef5..5c3b2d2ddd 100644
--- a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
+++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
@@ -31,6 +31,8 @@
#include <QFile>
#include <QOffscreenSurface>
#include <QPainter>
+#include <qrgbafloat.h>
+#include <qrgba64.h>
#include <QtGui/private/qrhi_p.h>
#include <QtGui/private/qrhi_p_p.h>
@@ -153,6 +155,11 @@ private slots:
void leakedResourceDestroy_data();
void leakedResourceDestroy();
+ void renderToFloatTexture_data();
+ void renderToFloatTexture();
+ void renderToRgb10Texture_data();
+ void renderToRgb10Texture();
+
private:
void setWindowType(QWindow *window, QRhi::Implementation impl);
@@ -1532,6 +1539,31 @@ void tst_QRhi::renderToTextureSimple_data()
rhiTestData();
}
+static QRhiGraphicsPipeline *createSimplePipeline(QRhi *rhi, QRhiShaderResourceBindings *srb, QRhiRenderPassDescriptor *rpDesc)
+{
+ std::unique_ptr<QRhiGraphicsPipeline> pipeline(rhi->newGraphicsPipeline());
+ QShader vs = loadShader(":/data/simple.vert.qsb");
+ if (!vs.isValid())
+ return nullptr;
+ QShader fs = loadShader(":/data/simple.frag.qsb");
+ if (!fs.isValid())
+ return nullptr;
+ pipeline->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({ { 2 * sizeof(float) } });
+ inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float2, 0 } });
+ pipeline->setVertexInputLayout(inputLayout);
+ pipeline->setShaderResourceBindings(srb);
+ pipeline->setRenderPassDescriptor(rpDesc);
+ return pipeline->create() ? pipeline.release() : nullptr;
+}
+
+static const float triangleVertices[] = {
+ -1.0f, -1.0f,
+ 1.0f, -1.0f,
+ 0.0f, 1.0f
+};
+
void tst_QRhi::renderToTextureSimple()
{
QFETCH(QRhi::Implementation, impl);
@@ -1557,32 +1589,15 @@ void tst_QRhi::renderToTextureSimple()
QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch();
- static const float vertices[] = {
- -1.0f, -1.0f,
- 1.0f, -1.0f,
- 0.0f, 1.0f
- };
- QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices)));
+ QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(triangleVertices)));
QVERIFY(vbuf->create());
- updates->uploadStaticBuffer(vbuf.data(), vertices);
+ updates->uploadStaticBuffer(vbuf.data(), triangleVertices);
QScopedPointer<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
QVERIFY(srb->create());
- QScopedPointer<QRhiGraphicsPipeline> pipeline(rhi->newGraphicsPipeline());
- QShader vs = loadShader(":/data/simple.vert.qsb");
- QVERIFY(vs.isValid());
- QShader fs = loadShader(":/data/simple.frag.qsb");
- QVERIFY(fs.isValid());
- pipeline->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
- QRhiVertexInputLayout inputLayout;
- inputLayout.setBindings({ { 2 * sizeof(float) } });
- inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float2, 0 } });
- pipeline->setVertexInputLayout(inputLayout);
- pipeline->setShaderResourceBindings(srb.data());
- pipeline->setRenderPassDescriptor(rpDesc.data());
-
- QVERIFY(pipeline->create());
+ QScopedPointer<QRhiGraphicsPipeline> pipeline(createSimplePipeline(rhi.data(), srb.data(), rpDesc.data()));
+ QVERIFY(pipeline);
cb->beginPass(rt.data(), Qt::blue, { 1.0f, 0 }, updates);
cb->setGraphicsPipeline(pipeline.data());
@@ -1684,32 +1699,15 @@ void tst_QRhi::renderToTextureMip()
QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch();
- static const float vertices[] = {
- -1.0f, -1.0f,
- 1.0f, -1.0f,
- 0.0f, 1.0f
- };
- QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices)));
+ QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(triangleVertices)));
QVERIFY(vbuf->create());
- updates->uploadStaticBuffer(vbuf.data(), vertices);
+ updates->uploadStaticBuffer(vbuf.data(), triangleVertices);
QScopedPointer<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
QVERIFY(srb->create());
- QScopedPointer<QRhiGraphicsPipeline> pipeline(rhi->newGraphicsPipeline());
- QShader vs = loadShader(":/data/simple.vert.qsb");
- QVERIFY(vs.isValid());
- QShader fs = loadShader(":/data/simple.frag.qsb");
- QVERIFY(fs.isValid());
- pipeline->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
- QRhiVertexInputLayout inputLayout;
- inputLayout.setBindings({ { 2 * sizeof(float) } });
- inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float2, 0 } });
- pipeline->setVertexInputLayout(inputLayout);
- pipeline->setShaderResourceBindings(srb.data());
- pipeline->setRenderPassDescriptor(rpDesc.data());
-
- QVERIFY(pipeline->create());
+ QScopedPointer<QRhiGraphicsPipeline> pipeline(createSimplePipeline(rhi.data(), srb.data(), rpDesc.data()));
+ QVERIFY(pipeline);
cb->beginPass(rt.data(), Qt::blue, { 1.0f, 0 }, updates);
cb->setGraphicsPipeline(pipeline.data());
@@ -1806,32 +1804,15 @@ void tst_QRhi::renderToTextureCubemapFace()
QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch();
- static const float vertices[] = {
- -1.0f, -1.0f,
- 1.0f, -1.0f,
- 0.0f, 1.0f
- };
- QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices)));
+ QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(triangleVertices)));
QVERIFY(vbuf->create());
- updates->uploadStaticBuffer(vbuf.data(), vertices);
+ updates->uploadStaticBuffer(vbuf.data(), triangleVertices);
QScopedPointer<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
QVERIFY(srb->create());
- QScopedPointer<QRhiGraphicsPipeline> pipeline(rhi->newGraphicsPipeline());
- QShader vs = loadShader(":/data/simple.vert.qsb");
- QVERIFY(vs.isValid());
- QShader fs = loadShader(":/data/simple.frag.qsb");
- QVERIFY(fs.isValid());
- pipeline->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
- QRhiVertexInputLayout inputLayout;
- inputLayout.setBindings({ { 2 * sizeof(float) } });
- inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float2, 0 } });
- pipeline->setVertexInputLayout(inputLayout);
- pipeline->setShaderResourceBindings(srb.data());
- pipeline->setRenderPassDescriptor(rpDesc.data());
-
- QVERIFY(pipeline->create());
+ QScopedPointer<QRhiGraphicsPipeline> pipeline(createSimplePipeline(rhi.data(), srb.data(), rpDesc.data()));
+ QVERIFY(pipeline);
cb->beginPass(rt.data(), Qt::blue, { 1.0f, 0 }, updates);
cb->setGraphicsPipeline(pipeline.data());
@@ -1949,32 +1930,15 @@ void tst_QRhi::renderToTextureTextureArray()
QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch();
- static const float vertices[] = {
- -1.0f, -1.0f,
- 1.0f, -1.0f,
- 0.0f, 1.0f
- };
- QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices)));
+ QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(triangleVertices)));
QVERIFY(vbuf->create());
- updates->uploadStaticBuffer(vbuf.data(), vertices);
+ updates->uploadStaticBuffer(vbuf.data(), triangleVertices);
QScopedPointer<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
QVERIFY(srb->create());
- QScopedPointer<QRhiGraphicsPipeline> pipeline(rhi->newGraphicsPipeline());
- QShader vs = loadShader(":/data/simple.vert.qsb");
- QVERIFY(vs.isValid());
- QShader fs = loadShader(":/data/simple.frag.qsb");
- QVERIFY(fs.isValid());
- pipeline->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
- QRhiVertexInputLayout inputLayout;
- inputLayout.setBindings({ { 2 * sizeof(float) } });
- inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float2, 0 } });
- pipeline->setVertexInputLayout(inputLayout);
- pipeline->setShaderResourceBindings(srb.data());
- pipeline->setRenderPassDescriptor(rpDesc.data());
-
- QVERIFY(pipeline->create());
+ QScopedPointer<QRhiGraphicsPipeline> pipeline(createSimplePipeline(rhi.data(), srb.data(), rpDesc.data()));
+ QVERIFY(pipeline);
cb->beginPass(rt.data(), Qt::blue, { 1.0f, 0 }, updates);
cb->setGraphicsPipeline(pipeline.data());
@@ -3330,18 +3294,13 @@ void tst_QRhi::renderToTextureIndexedDraw()
QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch();
- static const float vertices[] = {
- -1.0f, -1.0f,
- 1.0f, -1.0f,
- 0.0f, 1.0f
- };
static const quint16 indices[] = {
0, 1, 2
};
- QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices)));
+ QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(triangleVertices)));
QVERIFY(vbuf->create());
- updates->uploadStaticBuffer(vbuf.data(), vertices);
+ updates->uploadStaticBuffer(vbuf.data(), triangleVertices);
QScopedPointer<QRhiBuffer> ibuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices)));
QVERIFY(ibuf->create());
@@ -3350,20 +3309,8 @@ void tst_QRhi::renderToTextureIndexedDraw()
QScopedPointer<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
QVERIFY(srb->create());
- QScopedPointer<QRhiGraphicsPipeline> pipeline(rhi->newGraphicsPipeline());
- QShader vs = loadShader(":/data/simple.vert.qsb");
- QVERIFY(vs.isValid());
- QShader fs = loadShader(":/data/simple.frag.qsb");
- QVERIFY(fs.isValid());
- pipeline->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
- QRhiVertexInputLayout inputLayout;
- inputLayout.setBindings({ { 2 * sizeof(float) } });
- inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float2, 0 } });
- pipeline->setVertexInputLayout(inputLayout);
- pipeline->setShaderResourceBindings(srb.data());
- pipeline->setRenderPassDescriptor(rpDesc.data());
-
- QVERIFY(pipeline->create());
+ QScopedPointer<QRhiGraphicsPipeline> pipeline(createSimplePipeline(rhi.data(), srb.data(), rpDesc.data()));
+ QVERIFY(pipeline);
QRhiCommandBuffer::VertexInput vbindings(vbuf.data(), 0);
@@ -3470,32 +3417,15 @@ void tst_QRhi::renderToWindowSimple()
QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch();
- static const float vertices[] = {
- -1.0f, -1.0f,
- 1.0f, -1.0f,
- 0.0f, 1.0f
- };
- QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices)));
+ QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(triangleVertices)));
QVERIFY(vbuf->create());
- updates->uploadStaticBuffer(vbuf.data(), vertices);
+ updates->uploadStaticBuffer(vbuf.data(), triangleVertices);
QScopedPointer<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
QVERIFY(srb->create());
- QScopedPointer<QRhiGraphicsPipeline> pipeline(rhi->newGraphicsPipeline());
- QShader vs = loadShader(":/data/simple.vert.qsb");
- QVERIFY(vs.isValid());
- QShader fs = loadShader(":/data/simple.frag.qsb");
- QVERIFY(fs.isValid());
- pipeline->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
- QRhiVertexInputLayout inputLayout;
- inputLayout.setBindings({ { 2 * sizeof(float) } });
- inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float2, 0 } });
- pipeline->setVertexInputLayout(inputLayout);
- pipeline->setShaderResourceBindings(srb.data());
- pipeline->setRenderPassDescriptor(rpDesc.data());
-
- QVERIFY(pipeline->create());
+ QScopedPointer<QRhiGraphicsPipeline> pipeline(createSimplePipeline(rhi.data(), srb.data(), rpDesc.data()));
+ QVERIFY(pipeline);
const int asyncReadbackFrames = rhi->resourceLimit(QRhi::MaxAsyncReadbackFrames);
// one frame issues the readback, then we do MaxAsyncReadbackFrames more to ensure the readback completes
@@ -3609,26 +3539,10 @@ void tst_QRhi::finishWithinSwapchainFrame()
QScopedPointer<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
QVERIFY(srb->create());
- QScopedPointer<QRhiGraphicsPipeline> pipeline(rhi->newGraphicsPipeline());
- QShader vs = loadShader(":/data/simple.vert.qsb");
- QVERIFY(vs.isValid());
- QShader fs = loadShader(":/data/simple.frag.qsb");
- QVERIFY(fs.isValid());
- pipeline->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
- QRhiVertexInputLayout inputLayout;
- inputLayout.setBindings({ { 2 * sizeof(float) } });
- inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float2, 0 } });
- pipeline->setVertexInputLayout(inputLayout);
- pipeline->setShaderResourceBindings(srb.data());
- pipeline->setRenderPassDescriptor(rpDesc.data());
- QVERIFY(pipeline->create());
+ QScopedPointer<QRhiGraphicsPipeline> pipeline(createSimplePipeline(rhi.data(), srb.data(), rpDesc.data()));
+ QVERIFY(pipeline);
- static const float vertices[] = {
- -1.0f, -1.0f,
- 1.0f, -1.0f,
- 0.0f, 1.0f
- };
- QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices)));
+ QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(triangleVertices)));
QVERIFY(vbuf->create());
// exercise begin/endExternal() just a little bit, note ExternalContent for beginPass()
@@ -3641,7 +3555,7 @@ void tst_QRhi::finishWithinSwapchainFrame()
// times within the same frame
for (int i = 0; i < 5; ++i) {
QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch();
- updates->uploadStaticBuffer(vbuf.data(), vertices);
+ updates->uploadStaticBuffer(vbuf.data(), triangleVertices);
cb->beginPass(rt, Qt::blue, { 1.0f, 0 }, updates, QRhiCommandBuffer::ExternalContent);
@@ -4783,5 +4697,182 @@ void tst_QRhi::leakedResourceDestroy()
// let the scoped ptr do its job with the resources
}
+void tst_QRhi::renderToFloatTexture_data()
+{
+ rhiTestData();
+}
+
+void tst_QRhi::renderToFloatTexture()
+{
+ QFETCH(QRhi::Implementation, impl);
+ QFETCH(QRhiInitParams *, initParams);
+
+ QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr));
+ if (!rhi)
+ QSKIP("QRhi could not be created, skipping testing rendering");
+
+ if (!rhi->isTextureFormatSupported(QRhiTexture::RGBA16F))
+ QSKIP("RGBA16F is not supported, skipping test");
+
+ const QSize outputSize(1920, 1080);
+ QScopedPointer<QRhiTexture> texture(rhi->newTexture(QRhiTexture::RGBA16F, outputSize, 1,
+ QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
+ QVERIFY(texture->create());
+
+ QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ texture.data() }));
+ QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor());
+ rt->setRenderPassDescriptor(rpDesc.data());
+ QVERIFY(rt->create());
+
+ QRhiCommandBuffer *cb = nullptr;
+ QVERIFY(rhi->beginOffscreenFrame(&cb) == QRhi::FrameOpSuccess);
+ QVERIFY(cb);
+
+ QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch();
+
+ QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(triangleVertices)));
+ QVERIFY(vbuf->create());
+ updates->uploadStaticBuffer(vbuf.data(), triangleVertices);
+
+ QScopedPointer<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
+ QVERIFY(srb->create());
+
+ QScopedPointer<QRhiGraphicsPipeline> pipeline(createSimplePipeline(rhi.data(), srb.data(), rpDesc.data()));
+ QVERIFY(pipeline);
+
+ cb->beginPass(rt.data(), Qt::blue, { 1.0f, 0 }, updates);
+ cb->setGraphicsPipeline(pipeline.data());
+ cb->setViewport({ 0, 0, float(outputSize.width()), float(outputSize.height()) });
+ QRhiCommandBuffer::VertexInput vbindings(vbuf.data(), 0);
+ cb->setVertexInput(0, 1, &vbindings);
+ cb->draw(3);
+
+ QRhiReadbackResult readResult;
+ QImage result;
+ readResult.completed = [&readResult, &result] {
+ result = QImage(reinterpret_cast<const uchar *>(readResult.data.constData()),
+ readResult.pixelSize.width(), readResult.pixelSize.height(),
+ QImage::Format_RGBA16FPx4);
+ };
+ QRhiResourceUpdateBatch *readbackBatch = rhi->nextResourceUpdateBatch();
+ readbackBatch->readBackTexture({ texture.data() }, &readResult);
+ cb->endPass(readbackBatch);
+
+ rhi->endOffscreenFrame();
+ QCOMPARE(result.size(), texture->pixelSize());
+
+ if (impl == QRhi::Null)
+ return;
+
+ if (rhi->isYUpInFramebuffer() != rhi->isYUpInNDC())
+ result = std::move(result).mirrored();
+
+ // Now we have a red rectangle on blue background.
+ const int y = 100;
+ const QRgbaFloat16 *p = reinterpret_cast<const QRgbaFloat16 *>(result.constScanLine(y));
+ int redCount = 0;
+ int blueCount = 0;
+ int x = result.width() - 1;
+ while (x-- >= 0) {
+ QRgbaFloat16 c = *p++;
+ if (c.red() >= 0.95f && qFuzzyIsNull(c.green()) && qFuzzyIsNull(c.blue()))
+ ++redCount;
+ else if (qFuzzyIsNull(c.red()) && qFuzzyIsNull(c.green()) && c.blue() >= 0.95f)
+ ++blueCount;
+ else
+ QFAIL("Encountered a pixel that is neither red or blue");
+ }
+ QCOMPARE(redCount + blueCount, texture->pixelSize().width());
+ QVERIFY(redCount > blueCount); // 1742 > 178
+}
+
+void tst_QRhi::renderToRgb10Texture_data()
+{
+ rhiTestData();
+}
+
+void tst_QRhi::renderToRgb10Texture()
+{
+ QFETCH(QRhi::Implementation, impl);
+ QFETCH(QRhiInitParams *, initParams);
+
+ QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr));
+ if (!rhi)
+ QSKIP("QRhi could not be created, skipping testing rendering");
+
+ if (!rhi->isTextureFormatSupported(QRhiTexture::RGB10A2))
+ QSKIP("RGB10A2 is not supported, skipping test");
+
+ const QSize outputSize(1920, 1080);
+ QScopedPointer<QRhiTexture> texture(rhi->newTexture(QRhiTexture::RGB10A2, outputSize, 1,
+ QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
+ QVERIFY(texture->create());
+
+ QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ texture.data() }));
+ QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor());
+ rt->setRenderPassDescriptor(rpDesc.data());
+ QVERIFY(rt->create());
+
+ QRhiCommandBuffer *cb = nullptr;
+ QVERIFY(rhi->beginOffscreenFrame(&cb) == QRhi::FrameOpSuccess);
+ QVERIFY(cb);
+
+ QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch();
+
+ QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(triangleVertices)));
+ QVERIFY(vbuf->create());
+ updates->uploadStaticBuffer(vbuf.data(), triangleVertices);
+
+ QScopedPointer<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
+ QVERIFY(srb->create());
+
+ QScopedPointer<QRhiGraphicsPipeline> pipeline(createSimplePipeline(rhi.data(), srb.data(), rpDesc.data()));
+ QVERIFY(pipeline);
+
+ cb->beginPass(rt.data(), Qt::blue, { 1.0f, 0 }, updates);
+ cb->setGraphicsPipeline(pipeline.data());
+ cb->setViewport({ 0, 0, float(outputSize.width()), float(outputSize.height()) });
+ QRhiCommandBuffer::VertexInput vbindings(vbuf.data(), 0);
+ cb->setVertexInput(0, 1, &vbindings);
+ cb->draw(3);
+
+ QRhiReadbackResult readResult;
+ QImage result;
+ readResult.completed = [&readResult, &result] {
+ result = QImage(reinterpret_cast<const uchar *>(readResult.data.constData()),
+ readResult.pixelSize.width(), readResult.pixelSize.height(),
+ QImage::Format_A2BGR30_Premultiplied);
+ };
+ QRhiResourceUpdateBatch *readbackBatch = rhi->nextResourceUpdateBatch();
+ readbackBatch->readBackTexture({ texture.data() }, &readResult);
+ cb->endPass(readbackBatch);
+
+ rhi->endOffscreenFrame();
+ QCOMPARE(result.size(), texture->pixelSize());
+
+ if (impl == QRhi::Null)
+ return;
+
+ if (rhi->isYUpInFramebuffer() != rhi->isYUpInNDC())
+ result = std::move(result).mirrored();
+
+ // Now we have a red rectangle on blue background.
+ const int y = 100;
+ int redCount = 0;
+ int blueCount = 0;
+ const int maxFuzz = 1;
+ for (int x = 0; x < result.width(); ++x) {
+ QRgb c = result.pixel(x, y);
+ if (qRed(c) >= (255 - maxFuzz) && qGreen(c) == 0 && qBlue(c) == 0)
+ ++redCount;
+ else if (qRed(c) == 0 && qGreen(c) == 0 && qBlue(c) >= (255 - maxFuzz))
+ ++blueCount;
+ else
+ QFAIL("Encountered a pixel that is neither red or blue");
+ }
+ QCOMPARE(redCount + blueCount, texture->pixelSize().width());
+ QVERIFY(redCount > blueCount); // 1742 > 178
+}
+
#include <tst_qrhi.moc>
QTEST_MAIN(tst_QRhi)