summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/gui/rhi/qrhi/BLACKLIST3
-rw-r--r--tests/auto/gui/rhi/qrhi/tst_qrhi.cpp132
-rw-r--r--tests/manual/rhi/CMakeLists.txt1
-rw-r--r--tests/manual/rhi/shared/buildshaders.bat2
-rw-r--r--tests/manual/rhi/shared/examplefw.h14
-rw-r--r--tests/manual/rhi/shared/texture_arr.frag19
-rw-r--r--tests/manual/rhi/shared/texture_arr.frag.qsbbin0 -> 1448 bytes
-rw-r--r--tests/manual/rhi/shared/texture_arr.vert20
-rw-r--r--tests/manual/rhi/shared/texture_arr.vert.qsbbin0 -> 1404 bytes
-rw-r--r--tests/manual/rhi/texturearray/CMakeLists.txt26
-rw-r--r--tests/manual/rhi/texturearray/texturearray.cpp198
11 files changed, 413 insertions, 2 deletions
diff --git a/tests/auto/gui/rhi/qrhi/BLACKLIST b/tests/auto/gui/rhi/qrhi/BLACKLIST
index 68621ac66b..65c9e4834b 100644
--- a/tests/auto/gui/rhi/qrhi/BLACKLIST
+++ b/tests/auto/gui/rhi/qrhi/BLACKLIST
@@ -7,3 +7,6 @@ android
# Skip 3D textures with Android emulator, the sw-based GL there is no good
[threeDimTexture]
android
+# Same here, GLES 3.0 features seem hopeless
+[renderToTextureTextureArray]
+android
diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
index 24d6ad2d7c..eba9b9ce30 100644
--- a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
+++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
@@ -113,6 +113,8 @@ private slots:
void renderToTextureMip();
void renderToTextureCubemapFace_data();
void renderToTextureCubemapFace();
+ void renderToTextureTextureArray_data();
+ void renderToTextureTextureArray();
void renderToTextureTexturedQuad_data();
void renderToTextureTexturedQuad();
void renderToTextureArrayOfTexturedQuad_data();
@@ -336,10 +338,13 @@ void tst_QRhi::create()
const int texMax = rhi->resourceLimit(QRhi::TextureSizeMax);
const int maxAtt = rhi->resourceLimit(QRhi::MaxColorAttachments);
const int framesInFlight = rhi->resourceLimit(QRhi::FramesInFlight);
+ const int texArrayMax = rhi->resourceLimit(QRhi::TextureArraySizeMax);
QVERIFY(texMin >= 1);
QVERIFY(texMax >= texMin);
QVERIFY(maxAtt >= 1);
QVERIFY(framesInFlight >= 1);
+ if (rhi->isFeatureSupported(QRhi::TextureArrays))
+ QVERIFY(texArrayMax > 1);
QVERIFY(rhi->nativeHandles());
QVERIFY(rhi->profiler());
@@ -1880,6 +1885,133 @@ void tst_QRhi::renderToTextureCubemapFace()
QFAIL("Encountered a pixel that is neither red or blue");
}
+ QVERIFY(redCount > 0 && blueCount > 0);
+ QCOMPARE(redCount + blueCount, outputSize.width());
+
+ if (rhi->isYUpInFramebuffer() == rhi->isYUpInNDC())
+ QVERIFY(redCount < blueCount); // 100, 412
+ else
+ QVERIFY(redCount > blueCount); // 412, 100
+}
+
+void tst_QRhi::renderToTextureTextureArray_data()
+{
+ rhiTestData();
+}
+
+void tst_QRhi::renderToTextureTextureArray()
+{
+ 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->isFeatureSupported(QRhi::TextureArrays))
+ QSKIP("TextureArrays is not supported with this backend, skipping test");
+
+ const QSize outputSize(512, 256);
+ const int ARRAY_SIZE = 8;
+ QScopedPointer<QRhiTexture> texture(rhi->newTextureArray(QRhiTexture::RGBA8,
+ ARRAY_SIZE,
+ outputSize,
+ 1,
+ QRhiTexture::RenderTarget
+ | QRhiTexture::UsedAsTransferSource));
+ QVERIFY(texture->create());
+
+ const int LAYER = 5; // render into element #5
+
+ QRhiColorAttachment colorAtt(texture.data());
+ colorAtt.setLayer(LAYER);
+ QRhiTextureRenderTargetDescription rtDesc(colorAtt);
+ QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(rtDesc));
+ QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor());
+ rt->setRenderPassDescriptor(rpDesc.data());
+ QVERIFY(rt->create());
+
+ QCOMPARE(rt->pixelSize(), texture->pixelSize());
+ QCOMPARE(rt->pixelSize(), outputSize);
+
+ QRhiCommandBuffer *cb = nullptr;
+ QVERIFY(rhi->beginOffscreenFrame(&cb) == QRhi::FrameOpSuccess);
+ QVERIFY(cb);
+
+ 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)));
+ QVERIFY(vbuf->create());
+ updates->uploadStaticBuffer(vbuf.data(), vertices);
+
+ 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());
+
+ cb->beginPass(rt.data(), Qt::blue, { 1.0f, 0 }, updates);
+ cb->setGraphicsPipeline(pipeline.data());
+ cb->setViewport({ 0, 0, float(rt->pixelSize().width()), float(rt->pixelSize().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_RGBA8888);
+ };
+ QRhiResourceUpdateBatch *readbackBatch = rhi->nextResourceUpdateBatch();
+ QRhiReadbackDescription readbackDescription(texture.data());
+ readbackDescription.setLayer(LAYER);
+ readbackBatch->readBackTexture(readbackDescription, &readResult);
+
+ cb->endPass(readbackBatch);
+
+ rhi->endOffscreenFrame();
+
+ QCOMPARE(result.size(), outputSize);
+
+ if (impl == QRhi::Null)
+ return;
+
+ const int y = 100;
+ const quint32 *p = reinterpret_cast<const quint32 *>(result.constScanLine(y));
+ int x = result.width() - 1;
+ int redCount = 0;
+ int blueCount = 0;
+ const int maxFuzz = 1;
+ while (x-- >= 0) {
+ const QRgb c(*p++);
+ 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");
+ }
+
+ QVERIFY(redCount > 0 && blueCount > 0);
QCOMPARE(redCount + blueCount, outputSize.width());
if (rhi->isYUpInFramebuffer() == rhi->isYUpInNDC())
diff --git a/tests/manual/rhi/CMakeLists.txt b/tests/manual/rhi/CMakeLists.txt
index f8879bbd0f..11117a00ae 100644
--- a/tests/manual/rhi/CMakeLists.txt
+++ b/tests/manual/rhi/CMakeLists.txt
@@ -22,6 +22,7 @@ add_subdirectory(computeimage)
add_subdirectory(instancing)
add_subdirectory(noninstanced)
add_subdirectory(tex3d)
+add_subdirectory(texturearray)
if(QT_FEATURE_widgets)
add_subdirectory(qrhiprof)
endif()
diff --git a/tests/manual/rhi/shared/buildshaders.bat b/tests/manual/rhi/shared/buildshaders.bat
index 7974683bd7..d0212bc7a7 100644
--- a/tests/manual/rhi/shared/buildshaders.bat
+++ b/tests/manual/rhi/shared/buildshaders.bat
@@ -3,3 +3,5 @@ qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c color.frag -o color.frag.qsb
qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c texture.vert -o texture.vert.qsb
qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c texture.frag -o texture.frag.qsb
qsb --glsl "310 es,150" --hlsl 50 --msl 12 -c texture_ms4.frag -o texture_ms4.frag.qsb
+qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 -c texture_arr.vert -o texture_arr.vert.qsb
+qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 -c texture_arr.frag -o texture_arr.frag.qsb
diff --git a/tests/manual/rhi/shared/examplefw.h b/tests/manual/rhi/shared/examplefw.h
index 83b5a73514..e7bc3e6b5d 100644
--- a/tests/manual/rhi/shared/examplefw.h
+++ b/tests/manual/rhi/shared/examplefw.h
@@ -109,7 +109,7 @@ QString graphicsApiName()
case Null:
return QLatin1String("Null (no output)");
case OpenGL:
- return QLatin1String("OpenGL 2.x");
+ return QLatin1String("OpenGL");
case Vulkan:
return QLatin1String("Vulkan");
case D3D11:
@@ -462,7 +462,7 @@ int main(int argc, char **argv)
cmdLineParser.addHelpOption();
QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null"));
cmdLineParser.addOption(nullOption);
- QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)"));
+ QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL"));
cmdLineParser.addOption(glOption);
QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
cmdLineParser.addOption(vkOption);
@@ -475,6 +475,8 @@ int main(int argc, char **argv)
// Use this parameter for the latter.
QCommandLineOption sdOption({ "s", "self-destruct" }, QLatin1String("Self-destruct after 5 seconds."));
cmdLineParser.addOption(sdOption);
+ QCommandLineOption coreProfOption({ "c", "core" }, QLatin1String("Request a core profile context for OpenGL"));
+ cmdLineParser.addOption(coreProfOption);
// Attempt testing device lost situations on D3D at least.
QCommandLineOption tdrOption(QLatin1String("curse"), QLatin1String("Curse the graphics device. "
"(generate a device reset every <count> frames when on D3D11)"),
@@ -517,6 +519,14 @@ int main(int argc, char **argv)
QSurfaceFormat fmt;
fmt.setDepthBufferSize(24);
fmt.setStencilBufferSize(8);
+ if (cmdLineParser.isSet(coreProfOption)) {
+#ifdef Q_OS_DARWIN
+ fmt.setVersion(4, 1);
+#else
+ fmt.setVersion(4, 3);
+#endif
+ fmt.setProfile(QSurfaceFormat::CoreProfile);
+ }
if (sampleCount > 1)
fmt.setSamples(sampleCount);
if (scFlags.testFlag(QRhiSwapChain::NoVSync))
diff --git a/tests/manual/rhi/shared/texture_arr.frag b/tests/manual/rhi/shared/texture_arr.frag
new file mode 100644
index 0000000000..0a2631e2bd
--- /dev/null
+++ b/tests/manual/rhi/shared/texture_arr.frag
@@ -0,0 +1,19 @@
+#version 440
+
+layout(location = 0) in vec2 v_texcoord;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ int flip;
+ int array_index;
+};
+
+layout(binding = 1) uniform sampler2DArray texArr;
+
+void main()
+{
+ vec4 c = texture(texArr, vec3(v_texcoord, float(array_index)));
+ fragColor = vec4(c.rgb * c.a, c.a);
+}
diff --git a/tests/manual/rhi/shared/texture_arr.frag.qsb b/tests/manual/rhi/shared/texture_arr.frag.qsb
new file mode 100644
index 0000000000..3674fdad1d
--- /dev/null
+++ b/tests/manual/rhi/shared/texture_arr.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/shared/texture_arr.vert b/tests/manual/rhi/shared/texture_arr.vert
new file mode 100644
index 0000000000..137263e080
--- /dev/null
+++ b/tests/manual/rhi/shared/texture_arr.vert
@@ -0,0 +1,20 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec2 texcoord;
+
+layout(location = 0) out vec2 v_texcoord;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ int flip;
+ int array_index;
+};
+
+void main()
+{
+ v_texcoord = vec2(texcoord.x, texcoord.y);
+ if (flip != 0)
+ v_texcoord.y = 1.0 - v_texcoord.y;
+ gl_Position = mvp * position;
+}
diff --git a/tests/manual/rhi/shared/texture_arr.vert.qsb b/tests/manual/rhi/shared/texture_arr.vert.qsb
new file mode 100644
index 0000000000..fe46d2c385
--- /dev/null
+++ b/tests/manual/rhi/shared/texture_arr.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/texturearray/CMakeLists.txt b/tests/manual/rhi/texturearray/CMakeLists.txt
new file mode 100644
index 0000000000..39e49d5287
--- /dev/null
+++ b/tests/manual/rhi/texturearray/CMakeLists.txt
@@ -0,0 +1,26 @@
+qt_internal_add_manual_test(texturearray
+ GUI
+ SOURCES
+ texturearray.cpp
+ PUBLIC_LIBRARIES
+ Qt::Gui
+ Qt::GuiPrivate
+)
+
+set_source_files_properties("../shared/texture_arr.vert.qsb"
+ PROPERTIES QT_RESOURCE_ALIAS "texture_arr.vert.qsb"
+)
+set_source_files_properties("../shared/texture_arr.frag.qsb"
+ PROPERTIES QT_RESOURCE_ALIAS "texture_arr.frag.qsb"
+)
+set(texturearray_resource_files
+ "../shared/texture_arr.vert.qsb"
+ "../shared/texture_arr.frag.qsb"
+)
+
+qt_internal_add_resource(texturearray "texturearray"
+ PREFIX
+ "/"
+ FILES
+ ${texturearray_resource_files}
+)
diff --git a/tests/manual/rhi/texturearray/texturearray.cpp b/tests/manual/rhi/texturearray/texturearray.cpp
new file mode 100644
index 0000000000..206730464e
--- /dev/null
+++ b/tests/manual/rhi/texturearray/texturearray.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+#include <QElapsedTimer>
+
+// Creates a texture array object with size 4, uploads a different
+// image to each, and cycles through them on-screen.
+
+static const int ARRAY_SIZE = 4;
+static const int UBUF_SIZE = 72;
+
+static float vertexData[] =
+{ // Y up, CCW
+ -0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 1.0f, 0.0f
+};
+
+static quint16 indexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+struct {
+ QList<QRhiResource *> releasePool;
+ QRhiTexture *texArr = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ QMatrix4x4 winProj;
+ QElapsedTimer t;
+ int arrayIndex = 0;
+} d;
+
+void Window::customInit()
+{
+ if (!m_r->isFeatureSupported(QRhi::TextureArrays))
+ qFatal("Texture array objects are not supported by this backend");
+
+ d.texArr = m_r->newTextureArray(QRhiTexture::RGBA8, ARRAY_SIZE, QSize(512, 512));
+ d.releasePool << d.texArr;
+ d.texArr->create();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+
+ QImage img(512, 512, QImage::Format_RGBA8888);
+ img.fill(Qt::red);
+ d.initialUpdates->uploadTexture(d.texArr, QRhiTextureUploadDescription(QRhiTextureUploadEntry(0, 0, QRhiTextureSubresourceUploadDescription(img))));
+ img.fill(Qt::green);
+ d.initialUpdates->uploadTexture(d.texArr, QRhiTextureUploadDescription(QRhiTextureUploadEntry(1, 0, QRhiTextureSubresourceUploadDescription(img))));
+ img.fill(Qt::blue);
+ d.initialUpdates->uploadTexture(d.texArr, QRhiTextureUploadDescription(QRhiTextureUploadEntry(2, 0, QRhiTextureSubresourceUploadDescription(img))));
+ img.fill(Qt::yellow);
+ d.initialUpdates->uploadTexture(d.texArr, QRhiTextureUploadDescription(QRhiTextureUploadEntry(3, 0, QRhiTextureSubresourceUploadDescription(img))));
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.sampler;
+ d.sampler->create();
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, UBUF_SIZE);
+ d.releasePool << d.ubuf;
+ d.ubuf->create();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf, 0, UBUF_SIZE),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.texArr, d.sampler)
+ });
+ d.srb->create();
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ d.releasePool << d.vbuf;
+ d.vbuf->create();
+
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indexData));
+ d.releasePool << d.ibuf;
+ d.ibuf->create();
+
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, 0, sizeof(vertexData), vertexData);
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, indexData);
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/texture_arr.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture_arr.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({ { 4 * sizeof(float) } });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, quint32(2 * sizeof(float)) }
+ });
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+ d.ps->create();
+
+ d.t.start();
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ if (d.winProj != m_proj) {
+ d.winProj = m_proj;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(2);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ const qint32 flip = 0;
+ u->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+ u->updateDynamicBuffer(d.ubuf, 68, 4, &d.arrayIndex);
+ }
+
+ if (d.t.elapsed() > 2000) {
+ d.t.restart();
+ d.arrayIndex = (d.arrayIndex + 1) % ARRAY_SIZE;
+ u->updateDynamicBuffer(d.ubuf, 68, 4, &d.arrayIndex);
+ }
+
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ cb->beginPass(m_sc->currentFrameRenderTarget(), m_clearColor, { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(6);
+ cb->endPass();
+}