diff options
Diffstat (limited to 'src/gui/doc/snippets/rhioffscreen')
-rw-r--r-- | src/gui/doc/snippets/rhioffscreen/color.frag | 16 | ||||
-rw-r--r-- | src/gui/doc/snippets/rhioffscreen/color.vert | 18 | ||||
-rw-r--r-- | src/gui/doc/snippets/rhioffscreen/main.cpp | 151 |
3 files changed, 185 insertions, 0 deletions
diff --git a/src/gui/doc/snippets/rhioffscreen/color.frag b/src/gui/doc/snippets/rhioffscreen/color.frag new file mode 100644 index 0000000000..ad9d953d02 --- /dev/null +++ b/src/gui/doc/snippets/rhioffscreen/color.frag @@ -0,0 +1,16 @@ +//! [0] +#version 440 + +layout(location = 0) in vec3 v_color; +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform buf { + mat4 mvp; + float opacity; +}; + +void main() +{ + fragColor = vec4(v_color * opacity, opacity); +} +//! [0] diff --git a/src/gui/doc/snippets/rhioffscreen/color.vert b/src/gui/doc/snippets/rhioffscreen/color.vert new file mode 100644 index 0000000000..0010e55561 --- /dev/null +++ b/src/gui/doc/snippets/rhioffscreen/color.vert @@ -0,0 +1,18 @@ +//! [0] +#version 440 + +layout(location = 0) in vec4 position; +layout(location = 1) in vec3 color; +layout(location = 0) out vec3 v_color; + +layout(std140, binding = 0) uniform buf { + mat4 mvp; + float opacity; +}; + +void main() +{ + v_color = color; + gl_Position = mvp * position; +} +//! [0] diff --git a/src/gui/doc/snippets/rhioffscreen/main.cpp b/src/gui/doc/snippets/rhioffscreen/main.cpp new file mode 100644 index 0000000000..c2c6f74dc1 --- /dev/null +++ b/src/gui/doc/snippets/rhioffscreen/main.cpp @@ -0,0 +1,151 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +//! [0] +#include <QGuiApplication> +#include <QImage> +#include <QFile> +#include <rhi/qrhi.h> + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + +#if QT_CONFIG(vulkan) + QVulkanInstance inst; +#endif + std::unique_ptr<QRhi> rhi; +#if defined(Q_OS_WIN) + QRhiD3D12InitParams params; + rhi.reset(QRhi::create(QRhi::D3D12, ¶ms)); +#elif QT_CONFIG(metal) + QRhiMetalInitParams params; + rhi.reset(QRhi::create(QRhi::Metal, ¶ms)); +#elif QT_CONFIG(vulkan) + inst.setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions()); + if (inst.create()) { + QRhiVulkanInitParams params; + params.inst = &inst; + rhi.reset(QRhi::create(QRhi::Vulkan, ¶ms)); + } else { + qFatal("Failed to create Vulkan instance"); + } +#endif + if (rhi) + qDebug() << rhi->backendName() << rhi->driverInfo(); + else + qFatal("Failed to initialize RHI"); + + float rotation = 0.0f; + float opacity = 1.0f; + int opacityDir = 1; + + std::unique_ptr<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8, + QSize(1280, 720), + 1, + QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource)); + tex->create(); + std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ tex.get() })); + std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor()); + rt->setRenderPassDescriptor(rp.get()); + rt->create(); + + QMatrix4x4 viewProjection = rhi->clipSpaceCorrMatrix(); + viewProjection.perspective(45.0f, 1280 / 720.f, 0.01f, 1000.0f); + viewProjection.translate(0, 0, -4); + + static float vertexData[] = { // Y up, CCW + 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, + }; + + std::unique_ptr<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, + QRhiBuffer::VertexBuffer, + sizeof(vertexData))); + vbuf->create(); + + std::unique_ptr<QRhiBuffer> ubuf(rhi->newBuffer(QRhiBuffer::Dynamic, + QRhiBuffer::UniformBuffer, + 64 + 4)); + ubuf->create(); + + std::unique_ptr<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings()); + srb->setBindings({ + QRhiShaderResourceBinding::uniformBuffer(0, + QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, + ubuf.get()) + }); + srb->create(); + + std::unique_ptr<QRhiGraphicsPipeline> ps(rhi->newGraphicsPipeline()); + QRhiGraphicsPipeline::TargetBlend premulAlphaBlend; + premulAlphaBlend.enable = true; + ps->setTargetBlends({ premulAlphaBlend }); + static auto getShader = [](const QString &name) { + QFile f(name); + return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader(); + }; + ps->setShaderStages({ + { QRhiShaderStage::Vertex, getShader(QLatin1String("color.vert.qsb")) }, + { QRhiShaderStage::Fragment, getShader(QLatin1String("color.frag.qsb")) } + }); + QRhiVertexInputLayout inputLayout; + inputLayout.setBindings({ + { 5 * sizeof(float) } + }); + inputLayout.setAttributes({ + { 0, 0, QRhiVertexInputAttribute::Float2, 0 }, + { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) } + }); + ps->setVertexInputLayout(inputLayout); + ps->setShaderResourceBindings(srb.get()); + ps->setRenderPassDescriptor(rp.get()); + ps->create(); + + QRhiCommandBuffer *cb; + for (int frame = 0; frame < 20; ++frame) { + rhi->beginOffscreenFrame(&cb); + + QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch(); + if (frame == 0) + u->uploadStaticBuffer(vbuf.get(), vertexData); + + QMatrix4x4 mvp = viewProjection; + mvp.rotate(rotation, 0, 1, 0); + u->updateDynamicBuffer(ubuf.get(), 0, 64, mvp.constData()); + rotation += 5.0f; + + u->updateDynamicBuffer(ubuf.get(), 64, 4, &opacity); + opacity += opacityDir * 0.2f; + if (opacity < 0.0f || opacity > 1.0f) { + opacityDir *= -1; + opacity = qBound(0.0f, opacity, 1.0f); + } + + cb->beginPass(rt.get(), Qt::green, { 1.0f, 0 }, u); + cb->setGraphicsPipeline(ps.get()); + cb->setViewport({ 0, 0, 1280, 720 }); + cb->setShaderResources(); + const QRhiCommandBuffer::VertexInput vbufBinding(vbuf.get(), 0); + cb->setVertexInput(0, 1, &vbufBinding); + cb->draw(3); + QRhiReadbackResult readbackResult; + u = rhi->nextResourceUpdateBatch(); + u->readBackTexture({ tex.get() }, &readbackResult); + cb->endPass(u); + + rhi->endOffscreenFrame(); + + QImage image(reinterpret_cast<const uchar *>(readbackResult.data.constData()), + readbackResult.pixelSize.width(), + readbackResult.pixelSize.height(), + QImage::Format_RGBA8888_Premultiplied); + if (rhi->isYUpInFramebuffer()) + image = image.mirrored(); + image.save(QString::asprintf("frame%d.png", frame)); + } + + return 0; +} +//! [0] |