QtBase  v6.3.1
msaatexture.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2018 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the examples of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** BSD License Usage
18 ** Alternatively, you may use this file under the terms of the BSD license
19 ** as follows:
20 **
21 ** "Redistribution and use in source and binary forms, with or without
22 ** modification, are permitted provided that the following conditions are
23 ** met:
24 ** * Redistributions of source code must retain the above copyright
25 ** notice, this list of conditions and the following disclaimer.
26 ** * Redistributions in binary form must reproduce the above copyright
27 ** notice, this list of conditions and the following disclaimer in
28 ** the documentation and/or other materials provided with the
29 ** distribution.
30 ** * Neither the name of The Qt Company Ltd nor the names of its
31 ** contributors may be used to endorse or promote products derived
32 ** from this software without specific prior written permission.
33 **
34 **
35 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 **
47 ** $QT_END_LICENSE$
48 **
49 ****************************************************************************/
50 
51 #include "../shared/examplefw.h"
52 
53 // Renders into a non-multisample and a multisample (4x) texture, and then uses
54 // those textures to draw two quads. Note that this uses an MSAA sampler in the
55 // shader, not resolves. Not supported on the GL(ES) backend atm.
56 
57 static float vertexData[] =
58 { // Y up, CCW
59  -0.5f, 0.5f, 0.0f, 0.0f,
60  -0.5f, -0.5f, 0.0f, 1.0f,
61  0.5f, -0.5f, 1.0f, 1.0f,
62  0.5f, 0.5f, 1.0f, 0.0f
63 };
64 
65 static quint16 indexData[] =
66 {
67  0, 1, 2, 0, 2, 3
68 };
69 
70 static float triangleData[] =
71 { // Y up, CCW
72  0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
73  -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
74  0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
75 };
76 
77 const int UBUFSZ = 68;
78 
79 struct {
81  QRhiBuffer *vbuf = nullptr;
82  QRhiBuffer *ibuf = nullptr;
83  QRhiBuffer *ubuf = nullptr;
84  QRhiTexture *tex = nullptr;
85  QRhiTexture *msaaTex = nullptr;
86  QRhiSampler *sampler = nullptr;
92  int rightOfs;
95  float triRot = 0;
96 
100  QRhiBuffer *triUbuf = nullptr;
105 } d;
106 
107 //#define NO_MSAA
108 
109 void Window::customInit()
110 {
112  qFatal("Multisample textures not supported by this backend");
113 
114  d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData) + sizeof(triangleData));
115  d.releasePool << d.vbuf;
116  d.vbuf->create();
117 
118  d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indexData));
119  d.releasePool << d.ibuf;
120  d.ibuf->create();
121 
122  d.rightOfs = m_r->ubufAligned(UBUFSZ);
124  d.releasePool << d.ubuf;
125  d.ubuf->create();
126 
128  d.releasePool << d.tex;
129  d.tex->create();
130 #ifndef NO_MSAA
132 #else
134 #endif
135  d.releasePool << d.msaaTex;
136  d.msaaTex->create();
137 
138  d.initialUpdates = m_r->nextResourceUpdateBatch();
139  d.initialUpdates->uploadStaticBuffer(d.vbuf, 0, sizeof(vertexData), vertexData);
140  d.initialUpdates->uploadStaticBuffer(d.vbuf, sizeof(vertexData), sizeof(triangleData), triangleData);
141  d.initialUpdates->uploadStaticBuffer(d.ibuf, indexData);
142 
145  d.releasePool << d.sampler;
146  d.sampler->create();
147 
148  d.srbLeft = m_r->newShaderResourceBindings();
149  d.releasePool << d.srbLeft;
150  d.srbLeft->setBindings({
153  });
154  d.srbLeft->create();
155 
156  d.srbRight = m_r->newShaderResourceBindings();
157  d.releasePool << d.srbRight;
158  d.srbRight->setBindings({
161  });
162  d.srbRight->create();
163 
164  d.psLeft = m_r->newGraphicsPipeline();
165  d.releasePool << d.psLeft;
166  d.psLeft->setShaderStages({
167  { QRhiShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
168  { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
169  });
170  QRhiVertexInputLayout inputLayout;
171  inputLayout.setBindings({ { 4 * sizeof(float) } });
172  inputLayout.setAttributes({
174  { 0, 1, QRhiVertexInputAttribute::Float2, quint32(2 * sizeof(float)) }
175  });
176  d.psLeft->setVertexInputLayout(inputLayout);
177  d.psLeft->setShaderResourceBindings(d.srbLeft);
178  d.psLeft->setRenderPassDescriptor(m_rp);
179  d.psLeft->create();
180 
181  d.psRight = m_r->newGraphicsPipeline();
182  d.releasePool << d.psRight;
183  d.psRight->setShaderStages({
184  { QRhiShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
185 #ifndef NO_MSAA
186  { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture_ms4.frag.qsb")) }
187 #else
188  { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
189 #endif
190  });
191  d.psRight->setVertexInputLayout(d.psLeft->vertexInputLayout());
192  d.psRight->setShaderResourceBindings(d.srbRight);
193  d.psRight->setRenderPassDescriptor(m_rp);
194  d.psRight->create();
195 
196  // set up the offscreen triangle that goes into tex and msaaTex
198  d.releasePool << d.triUbuf;
199  d.triUbuf->create();
200  d.triSrb = m_r->newShaderResourceBindings();
201  d.releasePool << d.triSrb;
202  d.triSrb->setBindings({
204  });
205  d.triSrb->create();
206  d.rt = m_r->newTextureRenderTarget({ d.tex });
207  d.releasePool << d.rt;
208  d.rtRp = d.rt->newCompatibleRenderPassDescriptor();
209  d.releasePool << d.rtRp;
210  d.rt->setRenderPassDescriptor(d.rtRp);
211  d.rt->create();
212  d.msaaRt = m_r->newTextureRenderTarget({ d.msaaTex });
213  d.releasePool << d.msaaRt;
214  d.msaaRtRp = d.msaaRt->newCompatibleRenderPassDescriptor();
215  d.releasePool << d.msaaRtRp;
216  d.msaaRt->setRenderPassDescriptor(d.msaaRtRp);
217  d.msaaRt->create();
218  d.triPs = m_r->newGraphicsPipeline();
219  d.releasePool << d.triPs;
220  d.triPs->setSampleCount(1);
221  d.triPs->setShaderStages({
222  { QRhiShaderStage::Vertex, getShader(QLatin1String(":/color.vert.qsb")) },
223  { QRhiShaderStage::Fragment, getShader(QLatin1String(":/color.frag.qsb")) }
224  });
225  inputLayout.setBindings({
226  { 5 * sizeof(float) }
227  });
228  inputLayout.setAttributes({
230  { 0, 1, QRhiVertexInputAttribute::Float3, quint32(2 * sizeof(float)) }
231  });
232  d.triPs->setVertexInputLayout(inputLayout);
233  d.triPs->setShaderResourceBindings(d.triSrb);
234  d.triPs->setRenderPassDescriptor(d.rtRp);
235  d.triPs->create();
236  d.msaaTriPs = m_r->newGraphicsPipeline();
237  d.releasePool << d.msaaTriPs;
238 #ifndef NO_MSAA
239  d.msaaTriPs->setSampleCount(4);
240 #else
241  d.msaaTriPs->setSampleCount(1);
242 #endif
243  d.msaaTriPs->setShaderStages(d.triPs->cbeginShaderStages(), d.triPs->cendShaderStages());
244  d.msaaTriPs->setVertexInputLayout(d.triPs->vertexInputLayout());
245  d.msaaTriPs->setShaderResourceBindings(d.triSrb);
246  d.msaaTriPs->setRenderPassDescriptor(d.msaaRtRp);
247  d.msaaTriPs->create();
248 }
249 
251 {
252  qDeleteAll(d.releasePool);
253  d.releasePool.clear();
254 }
255 
257 {
258  QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
260  if (d.initialUpdates) {
261  u->merge(d.initialUpdates);
262  d.initialUpdates->release();
263  d.initialUpdates = nullptr;
264 
265  // onscreen ubuf
266  qint32 flip = m_r->isYUpInFramebuffer() ? 1 : 0;
267  u->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
268  u->updateDynamicBuffer(d.ubuf, d.rightOfs + 64, 4, &flip);
269 
270  // offscreen ubuf
271  d.triBaseMvp = m_r->clipSpaceCorrMatrix();
272  d.triBaseMvp.perspective(45.0f, d.msaaTex->pixelSize().width() / float(d.msaaTex->pixelSize().height()), 0.01f, 1000.0f);
273  d.triBaseMvp.translate(0, 0, -2);
274  float opacity = 1.0f;
275  u->updateDynamicBuffer(d.triUbuf, 64, 4, &opacity);
276  }
277 
278  if (d.winProj != m_proj) {
279  // onscreen buf, window size dependent
280  d.winProj = m_proj;
281  QMatrix4x4 mvp = m_proj;
282  mvp.scale(2);
283  mvp.translate(-0.8f, 0, 0);
284  u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
285  mvp.translate(1.6f, 0, 0);
286  u->updateDynamicBuffer(d.ubuf, d.rightOfs, 64, mvp.constData());
287  }
288 
289  // offscreen buf, apply the rotation on every frame
290  QMatrix4x4 triMvp = d.triBaseMvp;
291  triMvp.rotate(d.triRot, 0, 1, 0);
292  d.triRot += 1;
293  u->updateDynamicBuffer(d.triUbuf, 0, 64, triMvp.constData());
294 
295  cb->resourceUpdate(u); // could have passed u to beginPass but exercise this one too
296 
297  // offscreen
298  cb->beginPass(d.rt, QColor::fromRgbF(0.5f, 0.2f, 0.0f, 1.0f), { 1.0f, 0 });
299  cb->setGraphicsPipeline(d.triPs);
300  cb->setViewport({ 0, 0, float(d.msaaTex->pixelSize().width()), float(d.msaaTex->pixelSize().height()) });
301  cb->setShaderResources();
302  QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, quint32(sizeof(vertexData)));
303  cb->setVertexInput(0, 1, &vbufBinding);
304  cb->draw(3);
305  cb->endPass();
306 
307  // offscreen msaa
308  cb->beginPass(d.msaaRt, QColor::fromRgbF(0.5f, 0.2f, 0.0f, 1.0f), { 1.0f, 0 });
309  cb->setGraphicsPipeline(d.msaaTriPs);
310  cb->setViewport({ 0, 0, float(d.msaaTex->pixelSize().width()), float(d.msaaTex->pixelSize().height()) });
311  cb->setShaderResources();
312  cb->setVertexInput(0, 1, &vbufBinding);
313  cb->draw(3);
314  cb->endPass();
315 
316  // onscreen
317  const QSize outputSizeInPixels = m_sc->currentPixelSize();
318  cb->beginPass(m_sc->currentFrameRenderTarget(), m_clearColor, { 1.0f, 0 });
319  cb->setGraphicsPipeline(d.psLeft); // showing the non-msaa version
320  cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
321  cb->setShaderResources();
322  vbufBinding.second = 0;
323  cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
324  cb->drawIndexed(6);
325  cb->setGraphicsPipeline(d.psRight); // showing the msaa version, resolved in the shader
326  cb->setShaderResources();
327  cb->drawIndexed(6);
328  cb->endPass();
329 }
small capitals from c petite p scientific f u
Definition: afcover.h:88
static QColor fromRgbF(float r, float g, float b, float a=1.0)
Definition: qcolor.cpp:2424
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition: qmatrix4x4.h:61
void rotate(float angle, const QVector3D &vector)
void scale(const QVector3D &vector)
Definition: qmatrix4x4.cpp:803
const float * constData() const
Definition: qmatrix4x4.h:183
void translate(const QVector3D &vector)
Definition: qmatrix4x4.cpp:965
@ Immutable
Definition: qrhi_p.h:717
@ Dynamic
Definition: qrhi_p.h:719
@ IndexBuffer
Definition: qrhi_p.h:724
@ VertexBuffer
Definition: qrhi_p.h:723
@ UniformBuffer
Definition: qrhi_p.h:725
QPair< QRhiBuffer *, quint32 > VertexInput
Definition: qrhi_p.h:1426
int ubufAligned(int v) const
Definition: qrhi.cpp:6207
QMatrix4x4 clipSpaceCorrMatrix() const
Definition: qrhi.cpp:6299
bool isYUpInFramebuffer() const
Definition: qrhi.cpp:6238
bool isFeatureSupported(QRhi::Feature feature) const
Definition: qrhi.cpp:6318
QRhiShaderResourceBindings * newShaderResourceBindings()
Definition: qrhi.cpp:6543
QRhiBuffer * newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
Definition: qrhi.cpp:6562
QRhiSampler * newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode addressU, QRhiSampler::AddressMode addressV, QRhiSampler::AddressMode addressW=QRhiSampler::Repeat)
Definition: qrhi.cpp:6679
QRhiTextureRenderTarget * newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags={})
Definition: qrhi.cpp:6696
QRhiGraphicsPipeline * newGraphicsPipeline()
Definition: qrhi.cpp:6520
QRhiTexture * newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
Definition: qrhi.cpp:6609
@ MultisampleTexture
Definition: qrhi_p.h:1562
QRhiResourceUpdateBatch * nextResourceUpdateBatch()
Definition: qrhi.cpp:5568
@ ClampToEdge
Definition: qrhi_p.h:884
static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
Definition: qrhi.cpp:3374
static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf)
Definition: qrhi.cpp:3268
@ RenderTarget
Definition: qrhi_p.h:766
void setBindings(std::initializer_list< QRhiVertexInputBinding > list)
Definition: qrhi_p.h:257
void setAttributes(std::initializer_list< QRhiVertexInputAttribute > list)
Definition: qrhi_p.h:268
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:55
constexpr int height() const noexcept
Definition: qsize.h:160
constexpr int width() const noexcept
Definition: qsize.h:157
qreal opacity
The opacity of the window in the windowing system.
Definition: qwindow.h:132
std::unique_ptr< QRhiSwapChain > m_sc
Definition: window.h:89
std::unique_ptr< QRhiRenderPassDescriptor > m_rp
Definition: window.h:91
virtual void customRender()
QColor m_clearColor
Definition: examplefw.h:176
QMatrix4x4 m_proj
Definition: window.h:94
virtual void customInit()
QRhi * m_r
Definition: examplefw.h:161
qDeleteAll(list.begin(), list.end())
QShader getShader(const QString &name)
Definition: examplefw.h:86
QRhiShaderResourceBindings * srbLeft
Definition: msaatexture.cpp:87
QRhiBuffer * ibuf
Definition: msaatexture.cpp:82
QRhiRenderPassDescriptor * msaaRtRp
QRhiGraphicsPipeline * psRight
Definition: msaatexture.cpp:90
const int UBUFSZ
Definition: msaatexture.cpp:77
QRhiShaderResourceBindings * triSrb
Definition: msaatexture.cpp:97
struct @916 d
QRhiBuffer * ubuf
Definition: msaatexture.cpp:83
QList< QRhiResource * > releasePool
Definition: msaatexture.cpp:80
QRhiGraphicsPipeline * msaaTriPs
Definition: msaatexture.cpp:98
QRhiShaderResourceBindings * srbRight
Definition: msaatexture.cpp:88
float triRot
Definition: msaatexture.cpp:95
QRhiTextureRenderTarget * rt
QRhiRenderPassDescriptor * rtRp
QRhiTexture * tex
Definition: msaatexture.cpp:84
QRhiGraphicsPipeline * triPs
Definition: msaatexture.cpp:99
QMatrix4x4 triBaseMvp
Definition: msaatexture.cpp:94
int rightOfs
Definition: msaatexture.cpp:92
QRhiBuffer * triUbuf
QRhiBuffer * vbuf
Definition: msaatexture.cpp:81
QRhiTextureRenderTarget * msaaRt
QMatrix4x4 winProj
Definition: msaatexture.cpp:93
QRhiResourceUpdateBatch * initialUpdates
Definition: msaatexture.cpp:91
QRhiTexture * msaaTex
Definition: msaatexture.cpp:85
QRhiGraphicsPipeline * psLeft
Definition: msaatexture.cpp:89
unsigned int quint32
Definition: qglobal.h:288
unsigned short quint16
Definition: qglobal.h:286
int qint32
Definition: qglobal.h:287
#define qFatal
Definition: qlogging.h:181
GLuint sampler
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)