summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2020-09-22 11:01:24 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2020-09-23 16:59:06 +0200
commitfe3a1617afd71e5ea2fced740a69b3d27958e2d7 (patch)
tree66a758c9c0de7f18734c14adebca7a6f03867623 /tests
parent9d55eee8da758cb9ea535cd35f12bf0789cb3b32 (diff)
rhi: d3d: Fix dynamic offsets with multiple buffers
Fixes: QTBUG-86821 Change-Id: I57f86bf0f7e95b92f5b2c5fee587112ecf0fc8e6 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/gui/rhi/qrhi/data/buildshaders.bat2
-rw-r--r--tests/auto/gui/rhi/qrhi/data/simple.frag.qsbbin740 -> 719 bytes
-rw-r--r--tests/auto/gui/rhi/qrhi/data/simple.vert.qsbbin786 -> 747 bytes
-rw-r--r--tests/auto/gui/rhi/qrhi/data/simpletextured.frag.qsbbin1206 -> 1177 bytes
-rw-r--r--tests/auto/gui/rhi/qrhi/data/simpletextured.vert.qsbbin983 -> 918 bytes
-rw-r--r--tests/auto/gui/rhi/qrhi/data/simpletextured_array.frag.qsbbin1693 -> 1646 bytes
-rw-r--r--tests/auto/gui/rhi/qrhi/data/textured.frag.qsbbin1590 -> 1503 bytes
-rw-r--r--tests/auto/gui/rhi/qrhi/data/textured.vert.qsbbin1368 -> 1277 bytes
-rw-r--r--tests/auto/gui/rhi/qrhi/data/textured_multiubuf.frag18
-rw-r--r--tests/auto/gui/rhi/qrhi/data/textured_multiubuf.frag.qsbbin0 -> 1422 bytes
-rw-r--r--tests/auto/gui/rhi/qrhi/data/textured_multiubuf.vert18
-rw-r--r--tests/auto/gui/rhi/qrhi/data/textured_multiubuf.vert.qsbbin0 -> 1223 bytes
-rw-r--r--tests/auto/gui/rhi/qrhi/tst_qrhi.cpp171
13 files changed, 209 insertions, 0 deletions
diff --git a/tests/auto/gui/rhi/qrhi/data/buildshaders.bat b/tests/auto/gui/rhi/qrhi/data/buildshaders.bat
index f4ebae070b..0102457b8a 100644
--- a/tests/auto/gui/rhi/qrhi/data/buildshaders.bat
+++ b/tests/auto/gui/rhi/qrhi/data/buildshaders.bat
@@ -44,3 +44,5 @@ qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o simpletextured.frag.qsb sim
qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 20 -o simpletextured_array.frag.qsb simpletextured_array.frag
qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o textured.vert.qsb textured.vert
qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o textured.frag.qsb textured.frag
+qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o textured_multiubuf.vert.qsb textured_multiubuf.vert
+qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o textured_multiubuf.frag.qsb textured_multiubuf.frag
diff --git a/tests/auto/gui/rhi/qrhi/data/simple.frag.qsb b/tests/auto/gui/rhi/qrhi/data/simple.frag.qsb
index 43edbdffd9..d398c81e0a 100644
--- a/tests/auto/gui/rhi/qrhi/data/simple.frag.qsb
+++ b/tests/auto/gui/rhi/qrhi/data/simple.frag.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qrhi/data/simple.vert.qsb b/tests/auto/gui/rhi/qrhi/data/simple.vert.qsb
index 06af5df492..c17286c38d 100644
--- a/tests/auto/gui/rhi/qrhi/data/simple.vert.qsb
+++ b/tests/auto/gui/rhi/qrhi/data/simple.vert.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qrhi/data/simpletextured.frag.qsb b/tests/auto/gui/rhi/qrhi/data/simpletextured.frag.qsb
index 7749f3caad..e3f57f41d4 100644
--- a/tests/auto/gui/rhi/qrhi/data/simpletextured.frag.qsb
+++ b/tests/auto/gui/rhi/qrhi/data/simpletextured.frag.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qrhi/data/simpletextured.vert.qsb b/tests/auto/gui/rhi/qrhi/data/simpletextured.vert.qsb
index c87d4b2fc1..22e2c7c3ec 100644
--- a/tests/auto/gui/rhi/qrhi/data/simpletextured.vert.qsb
+++ b/tests/auto/gui/rhi/qrhi/data/simpletextured.vert.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qrhi/data/simpletextured_array.frag.qsb b/tests/auto/gui/rhi/qrhi/data/simpletextured_array.frag.qsb
index 362e220d25..b7ae790fd4 100644
--- a/tests/auto/gui/rhi/qrhi/data/simpletextured_array.frag.qsb
+++ b/tests/auto/gui/rhi/qrhi/data/simpletextured_array.frag.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qrhi/data/textured.frag.qsb b/tests/auto/gui/rhi/qrhi/data/textured.frag.qsb
index f669152c9c..0935a1ab2c 100644
--- a/tests/auto/gui/rhi/qrhi/data/textured.frag.qsb
+++ b/tests/auto/gui/rhi/qrhi/data/textured.frag.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qrhi/data/textured.vert.qsb b/tests/auto/gui/rhi/qrhi/data/textured.vert.qsb
index d4ba474777..22f014ff91 100644
--- a/tests/auto/gui/rhi/qrhi/data/textured.vert.qsb
+++ b/tests/auto/gui/rhi/qrhi/data/textured.vert.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qrhi/data/textured_multiubuf.frag b/tests/auto/gui/rhi/qrhi/data/textured_multiubuf.frag
new file mode 100644
index 0000000000..c1b707a1bb
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/data/textured_multiubuf.frag
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec2 uv;
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 1) uniform buf {
+ float opacity;
+} fubuf;
+
+layout(binding = 2) uniform sampler2D tex;
+
+void main()
+{
+ vec4 c = texture(tex, uv);
+ c.a *= fubuf.opacity;
+ c.rgb *= c.a;
+ fragColor = c;
+}
diff --git a/tests/auto/gui/rhi/qrhi/data/textured_multiubuf.frag.qsb b/tests/auto/gui/rhi/qrhi/data/textured_multiubuf.frag.qsb
new file mode 100644
index 0000000000..728ecaf312
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/data/textured_multiubuf.frag.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qrhi/data/textured_multiubuf.vert b/tests/auto/gui/rhi/qrhi/data/textured_multiubuf.vert
new file mode 100644
index 0000000000..88dd4e45b6
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/data/textured_multiubuf.vert
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec2 texcoord;
+
+layout(location = 0) out vec2 uv;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 matrix;
+} vubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ uv = texcoord;
+ gl_Position = vubuf.matrix * position;
+}
diff --git a/tests/auto/gui/rhi/qrhi/data/textured_multiubuf.vert.qsb b/tests/auto/gui/rhi/qrhi/data/textured_multiubuf.vert.qsb
new file mode 100644
index 0000000000..3cc009d549
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/data/textured_multiubuf.vert.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
index a20bea7ace..568e77fd61 100644
--- a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
+++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
@@ -112,6 +112,8 @@ private slots:
void renderToTextureTexturedQuadAndUniformBuffer();
void renderToTextureDeferredSrb_data();
void renderToTextureDeferredSrb();
+ void renderToTextureMultipleUniformBuffersAndDynamicOffset_data();
+ void renderToTextureMultipleUniformBuffersAndDynamicOffset();
void renderToWindowSimple_data();
void renderToWindowSimple();
void finishWithinSwapchainFrame_data();
@@ -2354,6 +2356,175 @@ void tst_QRhi::renderToTextureDeferredSrb()
QCOMPARE(result.pixel(4, 227), empty);
}
+void tst_QRhi::renderToTextureMultipleUniformBuffersAndDynamicOffset_data()
+{
+ rhiTestData();
+}
+
+void tst_QRhi::renderToTextureMultipleUniformBuffersAndDynamicOffset()
+{
+ 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");
+
+ QImage inputImage;
+ inputImage.load(QLatin1String(":/data/qt256.png"));
+ QVERIFY(!inputImage.isNull());
+
+ QScopedPointer<QRhiTexture> texture(rhi->newTexture(QRhiTexture::RGBA8, inputImage.size(), 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();
+
+ static const float verticesUvs[] = {
+ -1.0f, -1.0f, 0.0f, 0.0f,
+ 1.0f, -1.0f, 1.0f, 0.0f,
+ -1.0f, 1.0f, 0.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f
+ };
+ QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(verticesUvs)));
+ QVERIFY(vbuf->create());
+ updates->uploadStaticBuffer(vbuf.data(), verticesUvs);
+
+ QScopedPointer<QRhiTexture> inputTexture(rhi->newTexture(QRhiTexture::RGBA8, inputImage.size()));
+ QVERIFY(inputTexture->create());
+ updates->uploadTexture(inputTexture.data(), inputImage);
+
+ QScopedPointer<QRhiSampler> sampler(rhi->newSampler(QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge));
+ QVERIFY(sampler->create());
+
+ const int MATRIX_COUNT = 4; // put 4 mat4s into the buffer, will only use one
+ const int ubufElemSize = rhi->ubufAligned(64);
+ QVERIFY(ubufElemSize >= 64);
+ QScopedPointer<QRhiBuffer> ubuf(rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, MATRIX_COUNT * ubufElemSize));
+ QVERIFY(ubuf->create());
+
+ float zeroes[16];
+ memset(zeroes, 0, sizeof(zeroes));
+ updates->updateDynamicBuffer(ubuf.data(), 0, 64, zeroes);
+ updates->updateDynamicBuffer(ubuf.data(), ubufElemSize, 64, zeroes);
+ // the only correct matrix is the third one
+ QMatrix4x4 matrix;
+ updates->updateDynamicBuffer(ubuf.data(), ubufElemSize * 2, 64, matrix.constData());
+ updates->updateDynamicBuffer(ubuf.data(), ubufElemSize * 3, 64, zeroes);
+
+ const int OPACITY_COUNT = 6; // put 6 floats into the buffer, will only use one
+ const int ubuf2ElemSize = rhi->ubufAligned(4);
+ QVERIFY(ubuf2ElemSize >= 4);
+ QScopedPointer<QRhiBuffer> ubuf2(rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, OPACITY_COUNT * ubuf2ElemSize));
+ QVERIFY(ubuf2->create());
+
+ updates->updateDynamicBuffer(ubuf2.data(), 0, 4, &zeroes[0]);
+ updates->updateDynamicBuffer(ubuf2.data(), ubuf2ElemSize, 4, &zeroes[0]);
+ updates->updateDynamicBuffer(ubuf2.data(), ubuf2ElemSize * 2, 4, &zeroes[0]);
+ // the only correct opacity value is the fourth one
+ float opacity = 0.5f;
+ updates->updateDynamicBuffer(ubuf2.data(), ubuf2ElemSize * 3, 4, &opacity);
+ updates->updateDynamicBuffer(ubuf2.data(), ubuf2ElemSize * 4, 4, &zeroes[0]);
+ updates->updateDynamicBuffer(ubuf2.data(), ubuf2ElemSize * 5, 4, &zeroes[0]);
+
+ const QRhiShaderResourceBinding::StageFlags commonVisibility = QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage;
+ QScopedPointer<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
+ srb->setBindings({
+ QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(0, commonVisibility, ubuf.data(), 64),
+ QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(1, commonVisibility, ubuf2.data(), 4),
+ QRhiShaderResourceBinding::sampledTexture(2, QRhiShaderResourceBinding::FragmentStage, inputTexture.data(), sampler.data())
+ });
+ QVERIFY(srb->create());
+
+ QScopedPointer<QRhiGraphicsPipeline> pipeline(rhi->newGraphicsPipeline());
+ pipeline->setTopology(QRhiGraphicsPipeline::TriangleStrip);
+ QShader vs = loadShader(":/data/textured_multiubuf.vert.qsb");
+ QVERIFY(vs.isValid());
+ QShader fs = loadShader(":/data/textured_multiubuf.frag.qsb");
+ QVERIFY(fs.isValid());
+ pipeline->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({ { 4 * sizeof(float) } });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) }
+ });
+ pipeline->setVertexInputLayout(inputLayout);
+ pipeline->setShaderResourceBindings(srb.data());
+ pipeline->setRenderPassDescriptor(rpDesc.data());
+
+ QVERIFY(pipeline->create());
+
+ cb->beginPass(rt.data(), Qt::black, { 1.0f, 0 }, updates);
+ cb->setGraphicsPipeline(pipeline.data());
+
+ // Now the magic, expose the 3rd matrix and 4th opacity value to the shader.
+ // If the handling of dynamic offsets were broken, the shaders would likely
+ // "see" an all zero matrix and zero opacity, thus leading to different
+ // rendering output. This way we can verify if using dynamic offsets, and
+ // more than one at the same time, is functional.
+ QVarLengthArray<QPair<int, quint32>, 2> dynamicOffset = {
+ { 0, quint32(ubufElemSize * 2) },
+ { 1, quint32(ubuf2ElemSize * 3) },
+ };
+ cb->setShaderResources(srb.data(), 2, dynamicOffset.constData());
+
+ cb->setViewport({ 0, 0, float(texture->pixelSize().width()), float(texture->pixelSize().height()) });
+ QRhiCommandBuffer::VertexInput vbindings(vbuf.data(), 0);
+ cb->setVertexInput(0, 1, &vbindings);
+ cb->draw(4);
+
+ 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_RGBA8888_Premultiplied);
+ };
+ QRhiResourceUpdateBatch *readbackBatch = rhi->nextResourceUpdateBatch();
+ readbackBatch->readBackTexture({ texture.data() }, &readResult);
+ cb->endPass(readbackBatch);
+
+ rhi->endOffscreenFrame();
+
+ QVERIFY(!result.isNull());
+
+ if (impl == QRhi::Null)
+ return;
+
+ if (rhi->isYUpInFramebuffer() != rhi->isYUpInNDC())
+ result = std::move(result).mirrored();
+
+ // opacity 0.5 (premultiplied)
+ static const auto checkSemiWhite = [](const QRgb &c) {
+ QRgb semiWhite127 = qPremultiply(qRgba(255, 255, 255, 127));
+ QRgb semiWhite128 = qPremultiply(qRgba(255, 255, 255, 128));
+ return c == semiWhite127 || c == semiWhite128;
+ };
+ QVERIFY(checkSemiWhite(result.pixel(79, 77)));
+ QVERIFY(checkSemiWhite(result.pixel(124, 81)));
+ QVERIFY(checkSemiWhite(result.pixel(128, 149)));
+ QVERIFY(checkSemiWhite(result.pixel(120, 189)));
+ QVERIFY(checkSemiWhite(result.pixel(116, 185)));
+ QVERIFY(checkSemiWhite(result.pixel(191, 172)));
+
+ QRgb empty = qRgba(0, 0, 0, 0);
+ QCOMPARE(result.pixel(11, 45), empty);
+ QCOMPARE(result.pixel(246, 202), empty);
+ QCOMPARE(result.pixel(130, 18), empty);
+ QCOMPARE(result.pixel(4, 227), empty);
+}
+
void tst_QRhi::setWindowType(QWindow *window, QRhi::Implementation impl)
{
switch (impl) {