1// Copyright (C) 2008-2012 NVIDIA Corporation.
2// Copyright (C) 2020 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4
5#include <QtQuick3DRuntimeRender/private/qssgrhiquadrenderer_p.h>
6#include <QtQuick3DUtils/private/qquick3dprofiler_p.h>
7
8QT_BEGIN_NAMESPACE
9
10static const QVector3D g_fullScreenRectFaces[] = {
11 QVector3D(-1, -1, 0),
12 QVector3D(-1, 1, 0),
13 QVector3D(1, 1, 0),
14 QVector3D(1, -1, 0),
15
16 QVector3D(-1, -1, 1),
17 QVector3D(-1, 1, 1),
18 QVector3D(1, 1, 1),
19 QVector3D(1, -1, 1),
20
21 QVector3D(-1, -1, -1),
22 QVector3D(-1, 1, -1),
23 QVector3D(1, 1, -1),
24 QVector3D(1, -1, -1),
25};
26
27static const QVector2D g_fullScreenRectUVs[] = {
28 QVector2D(0, 0),
29 QVector2D(0, 1),
30 QVector2D(1, 1),
31 QVector2D(1, 0)
32};
33
34static const quint16 g_rectIndex[] = {
35 0, 1, 2, 0, 2, 3, // front face - 0, 1, 2, 3
36 0, 4, 5, 0, 5, 1, // left face - 0, 4, 5, 1
37 1, 5, 6, 1, 6, 2, // top face - 1, 5, 6, 2
38 3, 2, 6, 3, 6, 7, // right face - 3, 2, 6, 7
39 0, 3, 7, 0, 7, 4, // bottom face - 0, 3, 7, 4
40 7, 6, 5, 7, 5, 4 // back face - 7, 6, 5, 4
41};
42
43void QSSGRhiQuadRenderer::ensureBuffers(QSSGRhiContext *rhiCtx, QRhiResourceUpdateBatch *rub)
44{
45 if (!m_vbuf) {
46 constexpr int vertexCount = 8;
47 m_vbuf = std::make_shared<QSSGRhiBuffer>(args&: *rhiCtx,
48 args: QRhiBuffer::Immutable,
49 args: QRhiBuffer::VertexBuffer,
50 args: quint32(5 * sizeof(float)),
51 args: 5 * vertexCount * sizeof(float));
52 m_vbuf->buffer()->setName(QByteArrayLiteral("quad vertex buffer"));
53 float buf[5 * vertexCount];
54 float *p = buf;
55 for (int i = 0; i < vertexCount; ++i) {
56 *p++ = g_fullScreenRectFaces[i].x();
57 *p++ = g_fullScreenRectFaces[i].y();
58 *p++ = g_fullScreenRectFaces[i].z();
59 *p++ = g_fullScreenRectUVs[i % 4].x();
60 *p++ = g_fullScreenRectUVs[i % 4].y();
61 }
62 rub->uploadStaticBuffer(buf: m_vbuf->buffer(), data: buf);
63 }
64 if (!m_ibuf) {
65 m_ibuf = std::make_shared<QSSGRhiBuffer>(args&: *rhiCtx,
66 args: QRhiBuffer::Immutable,
67 args: QRhiBuffer::IndexBuffer,
68 args: 0,
69 args: 6 * sizeof(quint16),
70 args: QRhiCommandBuffer::IndexUInt16);
71 m_ibuf->buffer()->setName(QByteArrayLiteral("quad index buffer"));
72 const quint16 buf[] = { 0, 1, 2, 0, 2, 3 };
73 rub->uploadStaticBuffer(buf: m_ibuf->buffer(), data: buf);
74 }
75}
76
77void QSSGRhiQuadRenderer::prepareQuad(QSSGRhiContext *rhiCtx, QRhiResourceUpdateBatch *maybeRub)
78{
79 QRhiResourceUpdateBatch *rub = maybeRub ? maybeRub : rhiCtx->rhi()->nextResourceUpdateBatch();
80 ensureBuffers(rhiCtx, rub);
81 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates: rub);
82}
83
84void QSSGRhiQuadRenderer::recordRenderQuad(QSSGRhiContext *rhiCtx,
85 QSSGRhiGraphicsPipelineState *ps, QRhiShaderResourceBindings *srb,
86 QRhiRenderPassDescriptor *rpDesc, Flags flags)
87{
88 // ps must have viewport and shaderPipeline set already
89 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(ps&: *ps);
90 if (flags.testFlag(flag: UvCoords)) {
91 ia.inputLayout.setAttributes({
92 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
93 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
94 });
95 ia.inputs << QSSGRhiInputAssemblerState::PositionSemantic << QSSGRhiInputAssemblerState::TexCoord0Semantic;
96 } else {
97 ia.inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float3, 0 } });
98 ia.inputs << QSSGRhiInputAssemblerState::PositionSemantic;
99 }
100 ia.inputLayout.setBindings({ 5 * sizeof(float) });
101 ia.topology = QRhiGraphicsPipeline::Triangles;
102
103 ps->flags.setFlag(flag: QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, on: flags.testFlag(flag: DepthTest));
104 ps->flags.setFlag(flag: QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled, on: flags.testFlag(flag: DepthWrite));
105 ps->cullMode = QRhiGraphicsPipeline::None;
106 if (flags.testFlag(flag: PremulBlend)) {
107 ps->flags |= QSSGRhiGraphicsPipelineState::Flag::BlendEnabled;
108 ps->targetBlend.srcColor = QRhiGraphicsPipeline::One;
109 ps->targetBlend.dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha;
110 ps->targetBlend.srcAlpha = QRhiGraphicsPipeline::One;
111 ps->targetBlend.dstAlpha = QRhiGraphicsPipeline::OneMinusSrcAlpha;
112 } else { // set to default, since we may not have had a renderable previously
113 ps->targetBlend.srcColor = QRhiGraphicsPipeline::SrcAlpha;
114 ps->targetBlend.dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha;
115 ps->targetBlend.srcAlpha = QRhiGraphicsPipeline::One;
116 ps->targetBlend.dstAlpha = QRhiGraphicsPipeline::OneMinusSrcAlpha;
117 }
118
119 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(q: rhiCtx);
120 QRhiGraphicsPipeline *pipeline = rhiCtxD->pipeline(ps: *ps, rpDesc, srb);
121 // Make sure that we were able to create the pipeline before trying to use it
122 // When GraphicsPipeline creation fails it should return nullptr and print a warning
123 if (!pipeline)
124 return;
125
126 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
127 cb->setGraphicsPipeline(pipeline);
128 cb->setShaderResources(srb);
129 cb->setViewport(ps->viewport);
130
131 quint32 vertexOffset = flags.testAnyFlags(flags: RenderBehind) ? 5 * 4 * sizeof(float) : 0;
132
133 QRhiCommandBuffer::VertexInput vb(m_vbuf->buffer(), vertexOffset);
134 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderCall);
135 cb->setVertexInput(startBinding: 0, bindingCount: 1, bindings: &vb, indexBuf: m_ibuf->buffer(), indexOffset: m_ibuf->indexFormat());
136 cb->drawIndexed(indexCount: 6);
137 QSSGRHICTX_STAT(rhiCtx, drawIndexed(6, 1));
138 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderCall, 36llu | (1llu << 32), QByteArrayLiteral("render_quad"));
139}
140
141void QSSGRhiQuadRenderer::recordRenderQuadPass(QSSGRhiContext *rhiCtx,
142 QSSGRhiGraphicsPipelineState *ps, QRhiShaderResourceBindings *srb,
143 QRhiTextureRenderTarget *rt, Flags flags)
144{
145 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
146 cb->beginPass(rt, colorClearValue: Qt::black, depthStencilClearValue: { 1.0f, 0 }, resourceUpdates: nullptr, flags: rhiCtx->commonPassFlags());
147 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rt));
148 recordRenderQuad(rhiCtx, ps, srb, rpDesc: rt->renderPassDescriptor(), flags);
149 cb->endPass();
150 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
151}
152
153void QSSGRhiCubeRenderer::prepareCube(QSSGRhiContext *rhiCtx, QRhiResourceUpdateBatch *maybeRub)
154{
155 QRhiResourceUpdateBatch *rub = maybeRub ? maybeRub : rhiCtx->rhi()->nextResourceUpdateBatch();
156 ensureBuffers(rhiCtx, rub);
157 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates: rub);
158}
159
160//### The flags UvCoords and RenderBehind are ignored
161void QSSGRhiCubeRenderer::recordRenderCube(QSSGRhiContext *rhiCtx, QSSGRhiGraphicsPipelineState *ps, QRhiShaderResourceBindings *srb, QRhiRenderPassDescriptor *rpDesc, QSSGRhiQuadRenderer::Flags flags)
162{
163 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(ps&: *ps);
164 // ps must have viewport and shaderPipeline set already
165 ia.inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float3, 0 } });
166 ia.inputs << QSSGRhiInputAssemblerState::PositionSemantic;
167 ia.inputLayout.setBindings({ 3 * sizeof(float) });
168 ia.topology = QRhiGraphicsPipeline::Triangles;
169
170 ps->flags.setFlag(flag: QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, on: flags.testFlag(flag: QSSGRhiQuadRenderer::DepthTest));
171 ps->flags.setFlag(flag: QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled, on: flags.testFlag(flag: QSSGRhiQuadRenderer::DepthWrite));
172 ps->cullMode = QRhiGraphicsPipeline::None;
173 if (flags.testFlag(flag: QSSGRhiQuadRenderer::PremulBlend)) {
174 ps->flags |= QSSGRhiGraphicsPipelineState::Flag::BlendEnabled;
175 ps->targetBlend.srcColor = QRhiGraphicsPipeline::One;
176 ps->targetBlend.dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha;
177 ps->targetBlend.srcAlpha = QRhiGraphicsPipeline::One;
178 ps->targetBlend.dstAlpha = QRhiGraphicsPipeline::OneMinusSrcAlpha;
179 } else { // set to default, since we may not have had a renderable previously
180 ps->targetBlend.srcColor = QRhiGraphicsPipeline::SrcAlpha;
181 ps->targetBlend.dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha;
182 ps->targetBlend.srcAlpha = QRhiGraphicsPipeline::One;
183 ps->targetBlend.dstAlpha = QRhiGraphicsPipeline::OneMinusSrcAlpha;
184 }
185
186 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(q: rhiCtx);
187 QRhiGraphicsPipeline *pipeline = rhiCtxD->pipeline(ps: *ps, rpDesc, srb);
188 // Make sure that we were able to create the pipeline before trying to use it
189 // When GraphicsPipeline creation fails it should return nullptr and print a warning
190 if (!pipeline)
191 return;
192
193 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
194 cb->setGraphicsPipeline(pipeline);
195 cb->setShaderResources(srb);
196 cb->setViewport(ps->viewport);
197
198 QRhiCommandBuffer::VertexInput vb(m_vbuf->buffer(), 0);
199 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderCall);
200 cb->setVertexInput(startBinding: 0, bindingCount: 1, bindings: &vb, indexBuf: m_ibuf->buffer(), indexOffset: m_ibuf->indexFormat());
201 cb->drawIndexed(indexCount: 36);
202 QSSGRHICTX_STAT(rhiCtx, drawIndexed(36, 1));
203 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderCall, 36, QByteArrayLiteral("render_cube"));
204}
205
206void QSSGRhiCubeRenderer::ensureBuffers(QSSGRhiContext *rhiCtx, QRhiResourceUpdateBatch *rub)
207{
208 if (!m_vbuf) {
209 constexpr int vertexCount = 8;
210 m_vbuf = std::make_shared<QSSGRhiBuffer>(args&: *rhiCtx,
211 args: QRhiBuffer::Immutable,
212 args: QRhiBuffer::VertexBuffer,
213 args: quint32(3 * sizeof(float)),
214 args: 3 * vertexCount * sizeof(float));
215 m_vbuf->buffer()->setName(QByteArrayLiteral("cube vertex buffer"));
216
217 float buf[3 * vertexCount];
218 float *p = buf;
219 for (int i = 0; i < vertexCount; ++i) {
220 *p++ = g_fullScreenRectFaces[4 + i].x();
221 *p++ = g_fullScreenRectFaces[4 + i].y();
222 *p++ = g_fullScreenRectFaces[4 + i].z();
223 }
224 rub->uploadStaticBuffer(buf: m_vbuf->buffer(), data: buf);
225 }
226 if (!m_ibuf) {
227 m_ibuf = std::make_shared<QSSGRhiBuffer>(args&: *rhiCtx,
228 args: QRhiBuffer::Immutable,
229 args: QRhiBuffer::IndexBuffer,
230 args: 0,
231 args: sizeof(g_rectIndex),
232 args: QRhiCommandBuffer::IndexUInt16);
233 m_ibuf->buffer()->setName(QByteArrayLiteral("cube index buffer"));
234 rub->uploadStaticBuffer(buf: m_ibuf->buffer(), data: g_rectIndex);
235 }
236}
237
238QT_END_NAMESPACE
239

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtquick3d/src/runtimerender/qssgrhiquadrenderer.cpp