1/****************************************************************************
2**
3** Copyright (C) 2019 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the Qt Gui module
7**
8** $QT_BEGIN_LICENSE:LGPL3$
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 http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "qrhi_p_p.h"
38#include <qmath.h>
39#include <QLoggingCategory>
40
41#include "qrhinull_p_p.h"
42#ifndef QT_NO_OPENGL
43#include "qrhigles2_p_p.h"
44#endif
45#if QT_CONFIG(vulkan)
46#include "qrhivulkan_p_p.h"
47#endif
48#ifdef Q_OS_WIN
49#include "qrhid3d11_p_p.h"
50#endif
51#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
52#include "qrhimetal_p_p.h"
53#endif
54
55QT_BEGIN_NAMESPACE
56
57Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
58
59/*!
60 \class QRhi
61 \internal
62 \inmodule QtGui
63
64 \brief Accelerated 2D/3D graphics API abstraction.
65
66 The Qt Rendering Hardware Interface is an abstraction for hardware accelerated
67 graphics APIs, such as, \l{https://www.khronos.org/opengl/}{OpenGL},
68 \l{https://www.khronos.org/opengles/}{OpenGL ES},
69 \l{https://docs.microsoft.com/en-us/windows/desktop/direct3d}{Direct3D},
70 \l{https://developer.apple.com/metal/}{Metal}, and
71 \l{https://www.khronos.org/vulkan/}{Vulkan}.
72
73 Some of the main design goals are:
74
75 \list
76
77 \li Simple, minimal, understandable, extensible. Follow the proven path of the
78 Qt Quick scenegraph.
79
80 \li Aim to be a product - and in the bigger picture, part of a product (Qt) -
81 that is usable out of the box both by internal (such as, Qt Quick) and,
82 eventually, external users.
83
84 \li Not a complete 1:1 wrapper for any of the underlying APIs. The feature set
85 is tuned towards the needs of Qt's 2D and 3D offering (QPainter, Qt Quick, Qt
86 3D Studio). Iterate and evolve in a sustainable manner.
87
88 \li Intrinsically cross-platform, without reinventing: abstracting
89 cross-platform aspects of certain APIs (such as, OpenGL context creation and
90 windowing system interfaces, Vulkan instance and surface management) is not in
91 scope here. These are delegated to the existing QtGui facilities (QWindow,
92 QOpenGLContext, QVulkanInstance) and its backing QPA architecture.
93
94 \endlist
95
96 Each QRhi instance is backed by a backend for a specific graphics API. The
97 selection of the backend is a run time choice and is up to the application
98 or library that creates the QRhi instance. Some backends are available on
99 multiple platforms (OpenGL, Vulkan, Null), while APIs specific to a given
100 platform are only available when running on the platform in question (Metal
101 on macOS/iOS/tvOS, Direct3D on Windows).
102
103 The available backends currently are:
104
105 \list
106
107 \li OpenGL 2.1 or OpenGL ES 2.0 or newer. Some extensions are utilized when
108 present, for example to enable multisample framebuffers.
109
110 \li Direct3D 11.1
111
112 \li Metal
113
114 \li Vulkan 1.0, optionally with some extensions that are part of Vulkan 1.1
115
116 \li Null - A "dummy" backend that issues no graphics calls at all.
117
118 \endlist
119
120 In order to allow shader code to be written once in Qt applications and
121 libraries, all shaders are expected to be written in a single language
122 which is then compiled into SPIR-V. Versions for various shading language
123 are then generated from that, together with reflection information (inputs,
124 outputs, shader resources). This is then packed into easily and efficiently
125 serializable QShader instances. The compilers and tools to generate such
126 shaders are not part of QRhi, but the core classes for using such shaders,
127 QShader and QShaderDescription, are.
128
129 \section2 Design Fundamentals
130
131 A QRhi cannot be instantiated directly. Instead, use the create()
132 function. Delete the QRhi instance normally to release the graphics device.
133
134 \section3 Resources
135
136 Instances of classes deriving from QRhiResource, such as, QRhiBuffer,
137 QRhiTexture, etc., encapsulate zero, one, or more native graphics
138 resources. Instances of such classes are always created via the \c new
139 functions of the QRhi, such as, newBuffer(), newTexture(),
140 newTextureRenderTarget(), newSwapChain().
141
142 \badcode
143 vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
144 if (!vbuf->build()) { error }
145 ...
146 delete vbuf;
147 \endcode
148
149 \list
150
151 \li The returned value from both create() and functions like newBuffer() is
152 owned by the caller.
153
154 \li Just creating a QRhiResource subclass never allocates or initializes any
155 native resources. That is only done when calling the \c build function of a
156 subclass, for example, QRhiBuffer::build() or QRhiTexture::build().
157
158 \li The exception is
159 QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() and
160 QRhiSwapChain::newCompatibleRenderPassDescriptor(). There is no \c build
161 operation for these and the returned object is immediately active.
162
163 \li The resource objects themselves are treated as immutable: once a
164 resource is built, changing any parameters via the setters, such as,
165 QRhiTexture::setPixelSize(), has no effect, unless the underlying native
166 resource is released and \c build is called again. See more about resource
167 reuse in the sections below.
168
169 \li The underlying native resources are scheduled for releasing by the
170 QRhiResource destructor, or by calling QRhiResource::release(). Backends
171 often queue release requests and defer executing them to an unspecified
172 time, this is hidden from the applications. This way applications do not
173 have to worry about releasing native resources that may still be in use by
174 an in-flight frame.
175
176 \li Note that this does not mean that a QRhiResource can freely be
177 destroyed or release()'d within a frame (that is, in a
178 \l{QRhiCommandBuffer::beginFrame()}{beginFrame()} -
179 \l{QRhiCommandBuffer::endFrame()}{endFrame()} section). As a general rule,
180 all referenced QRhiResource objects must stay unchanged until the frame is
181 submitted by calling \l{QRhiCommandBuffer::endFrame()}{endFrame()}. To ease
182 this, QRhiResource::releaseAndDestroyLater() is provided as a convenience.
183
184 \endlist
185
186 \section3 Command buffers and deferred command execution
187
188 Regardless of the design and capabilities of the underlying graphics API,
189 all QRhi backends implement some level of command buffers. No
190 QRhiCommandBuffer function issues any native bind or draw command (such as,
191 \c glDrawElements) directly. Commands are always recorded in a queue,
192 either native or provided by the QRhi backend. The command buffer is
193 submitted, and so execution starts only upon QRhi::endFrame() or
194 QRhi::finish().
195
196 The deferred nature has consequences for some types of objects. For example,
197 writing to a dynamic buffer multiple times within a frame, in case such
198 buffers are backed by host-visible memory, will result in making the
199 results of all writes are visible to all draw calls in the command buffer
200 of the frame, regardless of when the dynamic buffer update was recorded
201 relative to a draw call.
202
203 Furthermore, instances of QRhiResource subclasses must be treated immutable
204 within a frame in which they are referenced in any way. Create or rebuild
205 all resources upfront, before starting to record commands for the next
206 frame. Reusing a QRhiResource instance within a frame (by rebuilding it and
207 then referencing it again in the same \c{beginFrame - endFrame} section)
208 should be avoided as it may lead to unexpected results, depending on the
209 backend.
210
211 As a general rule, all referenced QRhiResource objects must stay valid and
212 unmodified until the frame is submitted by calling
213 \l{QRhiCommandBuffer::endFrame()}{endFrame()}. On the other hand, calling
214 \l{QRhiResource::release()}{release()} or destroying the QRhiResource are
215 always safe once the frame is submitted, regardless of the status of the
216 underlying native resources (which may still be in use by the GPU - but
217 that is taken care of internally).
218
219 Unlike APIs like OpenGL, upload and copy type of commands cannot be mixed
220 with draw commands. The typical renderer will involve a sequence similar to
221 the following: \c{(re)build resources} - \c{begin frame} - \c{record
222 uploads and copies} - \c{start renderpass} - \c{record draw calls} - \c{end
223 renderpass} - \c{end frame}. Recording copy type of operations happens via
224 QRhiResourceUpdateBatch. Such operations are committed typically on
225 \l{QRhiCommandBuffer::beginPass()}{beginPass()}.
226
227 When working with legacy rendering engines designed for OpenGL, the
228 migration to QRhi often involves redesigning from having a single \c render
229 step (that performs copies and uploads, clears buffers, and issues draw
230 calls, all mixed together) to a clearly separated, two phase \c prepare -
231 \c render setup where the \c render step only starts a renderpass and
232 records draw calls, while all resource creation and queuing of updates,
233 uploads and copies happens beforehand, in the \c prepare step.
234
235 QRhi does not at the moment allow freely creating and submitting command
236 buffers. This may be lifted in the future to some extent, in particular if
237 compute support is introduced, but the model of well defined
238 \c{frame-start} and \c{frame-end} points, combined with a dedicated,
239 "frame" command buffer, where \c{frame-end} implies presenting, is going to
240 remain the primary way of operating since this is what fits Qt's various UI
241 technologies best.
242
243 \section3 Threading
244
245 A QRhi instance and the associated resources can be created and used on any
246 thread but all usage must be limited to that one single thread. When
247 rendering to multiple QWindows in an application, having a dedicated thread
248 and QRhi instance for each window is often advisable, as this can eliminate
249 issues with unexpected throttling caused by presenting to multiple windows.
250 Conceptually that is then the same as how Qt Quick scene graph's threaded
251 render loop operates when working directly with OpenGL: one thread for each
252 window, one QOpenGLContext for each thread. When moving onto QRhi,
253 QOpenGLContext is replaced by QRhi, making the migration straightforward.
254
255 When it comes to externally created native objects, such as OpenGL contexts
256 passed in via QRhiGles2NativeHandles, it is up to the application to ensure
257 they are not misused by other threads.
258
259 Resources are not shareable between QRhi instances. This is an intentional
260 choice since QRhi hides most queue, command buffer, and resource
261 synchronization related tasks, and provides no API for them. Safe and
262 efficient concurrent use of graphics resources from multiple threads is
263 tied to those concepts, however, and is thus a topic that is currently out
264 of scope, but may be introduced in the future.
265
266 \note The Metal backend requires that an autorelease pool is available on
267 the rendering thread, ideally wrapping each iteration of the render loop.
268 This needs no action from the users of QRhi when rendering on the main
269 (gui) thread, but becomes important when a separate, dedicated render
270 thread is used.
271
272 \section3 Resource synchronization
273
274 QRhi does not expose APIs for resource barriers or image layout
275 transitions. Such synchronization is done implicitly by the backends, where
276 applicable (for example, Vulkan), by tracking resource usage as necessary.
277 Buffer and image barriers are inserted before render or compute passes
278 transparently to the application.
279
280 \note Resources within a render or compute pass are expected to be bound to
281 a single usage during that pass. For example, a buffer can be used as
282 vertex, index, uniform, or storage buffer, but not a combination of them
283 within a single pass. However, it is perfectly fine to use a buffer as a
284 storage buffer in a compute pass, and then as a vertex buffer in a render
285 pass, for example, assuming the buffer declared both usages upon creation.
286
287 \note Textures have this rule relaxed in certain cases, because using two
288 subresources (typically two different mip levels) of the same texture for
289 different access (one for load, one for store) is supported even within the
290 same pass.
291
292 \section3 Resource reuse
293
294 From the user's point of view a QRhiResource is reusable immediately after
295 calling QRhiResource::release(). With the exception of swapchains, calling
296 \c build() on an already built object does an implicit \c release(). This
297 provides a handy shortcut to reuse a QRhiResource instance with different
298 parameters, with a new native graphics object underneath.
299
300 The importance of reusing the same object lies in the fact that some
301 objects reference other objects: for example, a QRhiShaderResourceBindings
302 can reference QRhiBuffer, QRhiTexture, and QRhiSampler instances. If in a
303 later frame one of these buffers need to be resized or a sampler parameter
304 needs changing, destroying and creating a whole new QRhiBuffer or
305 QRhiSampler would invalidate all references to the old instance. By just
306 changing the appropriate parameters via QRhiBuffer::setSize() or similar
307 and then calling QRhiBuffer::build(), everything works as expected and
308 there is no need to touch the QRhiShaderResourceBindings at all, even
309 though there is a good chance that under the hood the QRhiBuffer is now
310 backed by a whole new native buffer.
311
312 \badcode
313 ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 256);
314 ubuf->build();
315
316 srb = rhi->newShaderResourceBindings()
317 srb->setBindings({
318 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf)
319 });
320 srb->build();
321
322 ...
323
324 // now in a later frame we need to grow the buffer to a larger size
325 ubuf->setSize(512);
326 ubuf->build(); // same as ubuf->release(); ubuf->build();
327
328 // that's it, srb needs no changes whatsoever
329 \endcode
330
331 \section3 Pooled objects
332
333 In addition to resources, there are pooled objects as well, such as,
334 QRhiResourceUpdateBatch. An instance is retrieved via a \c next function,
335 such as, nextResourceUpdateBatch(). The caller does not own the returned
336 instance in this case. The only valid way of operating here is calling
337 functions on the QRhiResourceUpdateBatch and then passing it to
338 QRhiCommandBuffer::beginPass() or QRhiCommandBuffer::endPass(). These
339 functions take care of returning the batch to the pool. Alternatively, a
340 batch can be "canceled" and returned to the pool without processing by
341 calling QRhiResourceUpdateBatch::release().
342
343 A typical pattern is thus:
344
345 \badcode
346 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
347 ...
348 resUpdates->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
349 if (!image.isNull()) {
350 resUpdates->uploadTexture(texture, image);
351 image = QImage();
352 }
353 ...
354 QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
355 cb->beginPass(swapchain->currentFrameRenderTarget(), clearCol, clearDs, resUpdates);
356 \endcode
357
358 \section3 Swapchain specifics
359
360 QRhiSwapChain features some special semantics due to the peculiar nature of
361 swapchains.
362
363 \list
364
365 \li It has no \c build but rather a QRhiSwapChain::buildOrResize().
366 Repeatedly calling this function is \b not the same as calling
367 QRhiSwapChain::release() followed by QRhiSwapChain::buildOrResize(). This
368 is because swapchains often have ways to handle the case where buffers need
369 to be resized in a manner that is more efficient than a brute force
370 destroying and recreating from scratch.
371
372 \li An active QRhiSwapChain must be released by calling
373 \l{QRhiSwapChain::release()}{release()}, or by destroying the object, before
374 the QWindow's underlying QPlatformWindow, and so the associated native
375 window object, is destroyed. It should not be postponed because releasing
376 the swapchain may become problematic (and with some APIs, like Vulkan, is
377 explicitly disallowed) when the native window is not around anymore, for
378 example because the QPlatformWindow got destroyed upon getting a
379 QWindow::close(). Therefore, releasing the swapchain must happen whenever
380 the targeted QWindow sends the
381 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed event. If the event does
382 not arrive before the destruction of the QWindow - this can happen when
383 using QCoreApplication::quit() -, then check QWindow::handle() after the
384 event loop exits and invoke the swapchain release when non-null (meaning
385 the underlying native window is still around).
386
387 \endlist
388
389 \section3 Ownership
390
391 The general rule is no ownership transfer. Creating a QRhi with an already
392 existing graphics device does not mean the QRhi takes ownership of the
393 device object. Similarly, ownership is not given away when a device or
394 texture object is "exported" via QRhi::nativeHandles() or
395 QRhiTexture::nativeHandles(). Most importantly, passing pointers in structs
396 and via setters does not transfer ownership.
397
398 \section2 Troubleshooting
399
400 Errors are printed to the output via qWarning(). Additional debug messages
401 can be enabled via the following logging categories. Messages from these
402 categories are not printed by default unless explicitly enabled via
403 QRhi::EnableProfiling or the facilities of QLoggingCategory (such as, the
404 \c QT_LOGGING_RULES environment variable).
405
406 \list
407 \li \c{qt.rhi.general}
408 \endlist
409
410 It is strongly advised to inspect the output with the logging categories
411 (\c{qt.rhi.*}) enabled whenever a QRhi-based application is not behaving as
412 expected.
413 */
414
415/*!
416 \enum QRhi::Implementation
417 Describes which graphics API-specific backend gets used by a QRhi instance.
418
419 \value Null
420 \value Vulkan
421 \value OpenGLES2
422 \value D3D11
423 \value Metal
424 */
425
426/*!
427 \enum QRhi::Flag
428 Describes what special features to enable.
429
430 \value EnableProfiling Enables gathering timing (CPU, GPU) and resource
431 (QRhiBuffer, QRhiTexture, etc.) information and additional metadata. See
432 QRhiProfiler. Avoid enabling in production builds as it may involve a
433 performance penalty. Also enables debug messages from the \c{qt.rhi.*}
434 logging categories.
435
436 \value EnableDebugMarkers Enables debug marker groups. Without this frame
437 debugging features like making debug groups and custom resource name
438 visible in external GPU debugging tools will not be available and functions
439 like QRhiCommandBuffer::debugMarkBegin() will become a no-op. Avoid
440 enabling in production builds as it may involve a performance penalty.
441
442 \value PreferSoftwareRenderer Indicates that backends should prefer
443 choosing an adapter or physical device that renders in software on the CPU.
444 For example, with Direct3D there is typically a "Basic Render Driver"
445 adapter available with \c{DXGI_ADAPTER_FLAG_SOFTWARE}. Setting this flag
446 requests the backend to choose that adapter over any other, as long as no
447 specific adapter was forced by other backend-specific means. With Vulkan
448 this maps to preferring physical devices with
449 \c{VK_PHYSICAL_DEVICE_TYPE_CPU}. When not available, or when it is not
450 possible to decide if an adapter/device is software-based, this flag is
451 ignored. It may also be ignored with graphics APIs that have no concept and
452 means of enumerating adapters/devices.
453 */
454
455/*!
456 \enum QRhi::FrameOpResult
457 Describes the result of operations that can have a soft failure.
458
459 \value FrameOpSuccess Success
460
461 \value FrameOpError Unspecified error
462
463 \value FrameOpSwapChainOutOfDate The swapchain is in an inconsistent state
464 internally. This can be recoverable by attempting to repeat the operation
465 (such as, beginFrame()) later.
466
467 \value FrameOpDeviceLost The graphics device was lost. This can be
468 recoverable by attempting to repeat the operation (such as, beginFrame())
469 after releasing and reinitializing all objects backed by native graphics
470 resources. See isDeviceLost().
471 */
472
473/*!
474 \enum QRhi::Feature
475 Flag values to indicate what features are supported by the backend currently in use.
476
477 \value MultisampleTexture Indicates that textures with a sample count larger
478 than 1 are supported.
479
480 \value MultisampleRenderBuffer Indicates that renderbuffers with a sample
481 count larger than 1 are supported.
482
483 \value DebugMarkers Indicates that debug marker groups (and so
484 QRhiCommandBuffer::debugMarkBegin()) are supported.
485
486 \value Timestamps Indicates that command buffer timestamps are supported.
487 Relevant for QRhiProfiler::gpuFrameTimes().
488
489 \value Instancing Indicates that instanced drawing is supported.
490
491 \value CustomInstanceStepRate Indicates that instance step rates other than
492 1 are supported.
493
494 \value PrimitiveRestart Indicates that restarting the assembly of
495 primitives when encountering an index value of 0xFFFF
496 (\l{QRhiCommandBuffer::IndexUInt16}{IndexUInt16}) or 0xFFFFFFFF
497 (\l{QRhiCommandBuffer::IndexUInt32}{IndexUInt32}) is enabled, for certain
498 primitive topologies at least. QRhi will try to enable this with all
499 backends, but in some cases it will not be supported. Dynamically
500 controlling primitive restart is not possible since with some APIs
501 primitive restart with a fixed index is always on. Applications must assume
502 that whenever this feature is reported as supported, the above mentioned
503 index values \c may be treated specially, depending on the topology. The
504 only two topologies where primitive restart is guaranteed to behave
505 identically across backends, as long as this feature is reported as
506 supported, are \l{QRhiGraphicsPipeline::LineStrip}{LineStrip} and
507 \l{QRhiGraphicsPipeline::TriangleStrip}{TriangleStrip}.
508
509 \value NonDynamicUniformBuffers Indicates that creating buffers with the
510 usage \l{QRhiBuffer::UniformBuffer}{UniformBuffer} and the types
511 \l{QRhiBuffer::Immutable}{Immutable} or \l{QRhiBuffer::Static}{Static} is
512 supported. When reported as unsupported, uniform (constant) buffers must be
513 created as \l{QRhiBuffer::Dynamic}{Dynamic}. (which is recommended
514 regardless)
515
516 \value NonFourAlignedEffectiveIndexBufferOffset Indicates that effective
517 index buffer offsets (\c{indexOffset + firstIndex * indexComponentSize})
518 that are not 4 byte aligned are supported. When not supported, attempting
519 to issue a \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} with a
520 non-aligned effective offset may lead to unspecified behavior.
521
522 \value NPOTTextureRepeat Indicates that the
523 \l{QRhiSampler::Repeat}{Repeat} wrap mode and mipmap filtering modes are
524 supported for textures with a non-power-of-two size. In practice this can
525 only be false with OpenGL ES 2.0 implementations without
526 \c{GL_OES_texture_npot}.
527
528 \value RedOrAlpha8IsRed Indicates that the
529 \l{QRhiTexture::RED_OR_ALPHA8}{RED_OR_ALPHA8} format maps to a one
530 component 8-bit \c red format. This is the case for all backends except
531 OpenGL, where \c{GL_ALPHA}, a one component 8-bit \c alpha format, is used
532 instead. This is relevant for shader code that samples from the texture.
533
534 \value ElementIndexUint Indicates that 32-bit unsigned integer elements are
535 supported in the index buffer. In practice this is true everywhere except
536 when running on plain OpenGL ES 2.0 implementations without the necessary
537 extension. When false, only 16-bit unsigned elements are supported in the
538 index buffer.
539
540 \value Compute Indicates that compute shaders, image load/store, and
541 storage buffers are supported.
542
543 \value WideLines Indicates that lines with a width other than 1 are
544 supported. When reported as not supported, the line width set on the
545 graphics pipeline state is ignored. This can always be false with some
546 backends (D3D11, Metal). With Vulkan, the value depends on the
547 implementation.
548
549 \value VertexShaderPointSize Indicates that the size of rasterized points
550 set via \c{gl_PointSize} in the vertex shader is taken into account. When
551 reported as not supported, drawing points with a size other than 1 is not
552 supported. Setting \c{gl_PointSize} in the shader is still valid then, but
553 is ignored. (for example, when generating HLSL, the assignment is silently
554 dropped from the generated code) Note that some APIs (Metal, Vulkan)
555 require the point size to be set in the shader explicitly whenever drawing
556 points, even when the size is 1, as they do not automatically default to 1.
557
558 \value BaseVertex Indicates that \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()}
559 supports the \c vertexOffset argument. When reported as not supported, the
560 vertexOffset value in an indexed draw is ignored.
561
562 \value BaseInstance Indicates that instanced draw commands support the \c
563 firstInstance argument. When reported as not supported, the firstInstance
564 value is ignored and the instance ID starts from 0.
565
566 \value TriangleFanTopology Indicates that QRhiGraphicsPipeline::setTopology()
567 supports QRhiGraphicsPipeline::TriangleFan.
568
569 \value ReadBackNonUniformBuffer Indicates that
570 \l{QRhiResourceUpdateBatch::readBackBuffer()}{reading buffer contents} is
571 supported for QRhiBuffer instances with a usage different than
572 UniformBuffer. While this is supported in the majority of cases, it will be
573 unsupported with OpenGL ES older than 3.0.
574
575 \value ReadBackNonBaseMipLevel Indicates that specifying a mip level other
576 than 0 is supported when reading back texture contents. When not supported,
577 specifying a non-zero level in QRhiReadbackDescription leads to returning
578 an all-zero image. In practice this feature will be unsupported with OpenGL
579 ES 2.0, while it will likely be supported everywhere else.
580
581 \value TexelFetch Indicates that texelFetch() is available in shaders. In
582 practice this will be reported as unsupported with OpenGL ES 2.0 and OpenGL
583 2.x contexts, because GLSL 100 es and versions before 130 do not support
584 this function.
585 */
586
587/*!
588 \enum QRhi::BeginFrameFlag
589 Flag values for QRhi::beginFrame()
590
591 \value ExternalContentsInPass Specifies that one or more render or compute
592 passes in this frame will call QRhiCommandBuffer::beginExternal(). Some
593 backends, Vulkan in particular, will fail if this flag is not set and
594 beginExternal() is still called.
595 */
596
597/*!
598 \enum QRhi::EndFrameFlag
599 Flag values for QRhi::endFrame()
600
601 \value SkipPresent Specifies that no present command is to be queued or no
602 swapBuffers call is to be made. This way no image is presented. Generating
603 multiple frames with all having this flag set is not recommended (except,
604 for example, for benchmarking purposes - but keep in mind that backends may
605 behave differently when it comes to waiting for command completion without
606 presenting so the results are not comparable between them)
607 */
608
609/*!
610 \enum QRhi::ResourceLimit
611 Describes the resource limit to query.
612
613 \value TextureSizeMin Minimum texture width and height. This is typically
614 1. The minimum texture size is handled gracefully, meaning attempting to
615 create a texture with an empty size will instead create a texture with the
616 minimum size.
617
618 \value TextureSizeMax Maximum texture width and height. This depends on the
619 graphics API and sometimes the platform or implementation as well.
620 Typically the value is in the range 4096 - 16384. Attempting to create
621 textures larger than this is expected to fail.
622
623 \value MaxColorAttachments The maximum number of color attachments for a
624 QRhiTextureRenderTarget, in case multiple render targets are supported. When
625 MRT is not supported, the value is 1. Otherwise this is typically 8, but
626 watch out for the fact that OpenGL only mandates 4 as the minimum, and that
627 is what some OpenGL ES implementations provide.
628
629 \value FramesInFlight The number of frames the backend may keep "in
630 flight": with backends like Vulkan or Metal, it is the responsibility of
631 QRhi to block whenever starting a new frame and finding the CPU is already
632 \c{N - 1} frames ahead of the GPU (because the command buffer submitted in
633 frame no. \c{current} - \c{N} has not yet completed). The value N is what
634 is returned from here, and is typically 2. This can be relevant to
635 applications that integrate rendering done directly with the graphics API,
636 as such rendering code may want to perform double (if the value is 2)
637 buffering for resources, such as, buffers, similarly to the QRhi backends
638 themselves. The current frame slot index (a value running 0, 1, .., N-1,
639 then wrapping around) is retrievable from QRhi::currentFrameSlot(). The
640 value is 1 for backends where the graphics API offers no such low level
641 control over the command submission process. Note that pipelining may still
642 happen even when this value is 1 (some backends, such as D3D11, are
643 designed to attempt to enable this, for instance, by using an update
644 strategy for uniform buffers that does not stall the pipeline), but that is
645 then not controlled by QRhi and so not reflected here in the API.
646
647 \value MaxAsyncReadbackFrames The number of \l{QRhi::endFrame()}{submitted}
648 frames (including the one that contains the readback) after which an
649 asynchronous texture or buffer readback is guaranteed to complete upon
650 \l{QRhi::beginFrame()}{starting a new frame}.
651 */
652
653/*!
654 \class QRhiInitParams
655 \internal
656 \inmodule QtGui
657 \brief Base class for backend-specific initialization parameters.
658
659 Contains fields that are relevant to all backends.
660 */
661
662/*!
663 \class QRhiDepthStencilClearValue
664 \internal
665 \inmodule QtGui
666 \brief Specifies clear values for a depth or stencil buffer.
667 */
668
669/*!
670 \fn QRhiDepthStencilClearValue::QRhiDepthStencilClearValue()
671
672 Constructs a depth/stencil clear value with depth clear value 1.0f and
673 stencil clear value 0.
674 */
675
676/*!
677 Constructs a depth/stencil clear value with depth clear value \a d and
678 stencil clear value \a s.
679 */
680QRhiDepthStencilClearValue::QRhiDepthStencilClearValue(float d, quint32 s)
681 : m_d(d),
682 m_s(s)
683{
684}
685
686/*!
687 \return \c true if the values in the two QRhiDepthStencilClearValue objects
688 \a a and \a b are equal.
689
690 \relates QRhiDepthStencilClearValue
691 */
692bool operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) Q_DECL_NOTHROW
693{
694 return a.depthClearValue() == b.depthClearValue()
695 && a.stencilClearValue() == b.stencilClearValue();
696}
697
698/*!
699 \return \c false if the values in the two QRhiDepthStencilClearValue
700 objects \a a and \a b are equal; otherwise returns \c true.
701
702 \relates QRhiDepthStencilClearValue
703*/
704bool operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) Q_DECL_NOTHROW
705{
706 return !(a == b);
707}
708
709/*!
710 \return the hash value for \a v, using \a seed to seed the calculation.
711
712 \relates QRhiDepthStencilClearValue
713 */
714uint qHash(const QRhiDepthStencilClearValue &v, uint seed) Q_DECL_NOTHROW
715{
716 return seed * (uint(qFloor(v: qreal(v.depthClearValue()) * 100)) + v.stencilClearValue());
717}
718
719#ifndef QT_NO_DEBUG_STREAM
720QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
721{
722 QDebugStateSaver saver(dbg);
723 dbg.nospace() << "QRhiDepthStencilClearValue(depth-clear=" << v.depthClearValue()
724 << " stencil-clear=" << v.stencilClearValue()
725 << ')';
726 return dbg;
727}
728#endif
729
730/*!
731 \class QRhiViewport
732 \internal
733 \inmodule QtGui
734 \brief Specifies a viewport rectangle.
735
736 Used with QRhiCommandBuffer::setViewport().
737
738 QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
739 bottom-left. Negative width or height are not allowed.
740
741 Typical usage is like the following:
742
743 \badcode
744 const QSize outputSizeInPixels = swapchain->currentPixelSize();
745 const QRhiViewport viewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height());
746 cb->beginPass(swapchain->currentFrameRenderTarget(), { 0, 0, 0, 1 }, { 1, 0 });
747 cb->setGraphicsPipeline(ps);
748 cb->setViewport(viewport);
749 ...
750 \endcode
751
752 \sa QRhiCommandBuffer::setViewport(), QRhi::clipSpaceCorrMatrix(), QRhiScissor
753 */
754
755/*!
756 \fn QRhiViewport::QRhiViewport()
757
758 Constructs a viewport description with an empty rectangle and a depth range
759 of 0.0f - 1.0f.
760
761 \sa QRhi::clipSpaceCorrMatrix()
762 */
763
764/*!
765 Constructs a viewport description with the rectangle specified by \a x, \a
766 y, \a w, \a h and the depth range \a minDepth and \a maxDepth.
767
768 \note \a x and \a y are assumed to be the bottom-left position. \a w and \a
769 h should not be negative, the viewport will be ignored by
770 QRhiCommandBuffer::setViewport() otherwise.
771
772 \sa QRhi::clipSpaceCorrMatrix()
773 */
774QRhiViewport::QRhiViewport(float x, float y, float w, float h, float minDepth, float maxDepth)
775 : m_rect { ._M_elems: { x, y, w, h } },
776 m_minDepth(minDepth),
777 m_maxDepth(maxDepth)
778{
779}
780
781/*!
782 \return \c true if the values in the two QRhiViewport objects
783 \a a and \a b are equal.
784
785 \relates QRhiViewport
786 */
787bool operator==(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW
788{
789 return a.viewport() == b.viewport()
790 && a.minDepth() == b.minDepth()
791 && a.maxDepth() == b.maxDepth();
792}
793
794/*!
795 \return \c false if the values in the two QRhiViewport
796 objects \a a and \a b are equal; otherwise returns \c true.
797
798 \relates QRhiViewport
799*/
800bool operator!=(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW
801{
802 return !(a == b);
803}
804
805/*!
806 \return the hash value for \a v, using \a seed to seed the calculation.
807
808 \relates QRhiViewport
809 */
810uint qHash(const QRhiViewport &v, uint seed) Q_DECL_NOTHROW
811{
812 const std::array<float, 4> r = v.viewport();
813 return seed + uint(r[0]) + uint(r[1]) + uint(r[2]) + uint(r[3])
814 + uint(qFloor(v: qreal(v.minDepth()) * 100)) + uint(qFloor(v: qreal(v.maxDepth()) * 100));
815}
816
817#ifndef QT_NO_DEBUG_STREAM
818QDebug operator<<(QDebug dbg, const QRhiViewport &v)
819{
820 QDebugStateSaver saver(dbg);
821 const std::array<float, 4> r = v.viewport();
822 dbg.nospace() << "QRhiViewport(bottom-left-x=" << r[0]
823 << " bottom-left-y=" << r[1]
824 << " width=" << r[2]
825 << " height=" << r[3]
826 << " minDepth=" << v.minDepth()
827 << " maxDepth=" << v.maxDepth()
828 << ')';
829 return dbg;
830}
831#endif
832
833/*!
834 \class QRhiScissor
835 \internal
836 \inmodule QtGui
837 \brief Specifies a scissor rectangle.
838
839 Used with QRhiCommandBuffer::setScissor(). Setting a scissor rectangle is
840 only possible with a QRhiGraphicsPipeline that has
841 QRhiGraphicsPipeline::UsesScissor set.
842
843 QRhi assumes OpenGL-style scissor coordinates, meaning x and y are
844 bottom-left. Negative width or height are not allowed. However, apart from
845 that, the flexible OpenGL semantics apply: negative x and y, partially out
846 of bounds rectangles, etc. will be handled gracefully, clamping as
847 appropriate. Therefore, any rendering logic targeting OpenGL can feed
848 scissor rectangles into QRhiScissor as-is, without any adaptation.
849
850 \sa QRhiCommandBuffer::setScissor(), QRhiViewport
851 */
852
853/*!
854 \fn QRhiScissor::QRhiScissor()
855
856 Constructs an empty scissor.
857 */
858
859/*!
860 Constructs a scissor with the rectangle specified by \a x, \a y, \a w, and
861 \a h.
862
863 \note \a x and \a y are assumed to be the bottom-left position. Negative \a w
864 or \a h are not allowed, such scissor rectangles will be ignored by
865 QRhiCommandBuffer. Other than that, the flexible OpenGL semantics apply:
866 negative x and y, partially out of bounds rectangles, etc. will be handled
867 gracefully, clamping as appropriate.
868 */
869QRhiScissor::QRhiScissor(int x, int y, int w, int h)
870 : m_rect { ._M_elems: { x, y, w, h } }
871{
872}
873
874/*!
875 \return \c true if the values in the two QRhiScissor objects
876 \a a and \a b are equal.
877
878 \relates QRhiScissor
879 */
880bool operator==(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW
881{
882 return a.scissor() == b.scissor();
883}
884
885/*!
886 \return \c false if the values in the two QRhiScissor
887 objects \a a and \a b are equal; otherwise returns \c true.
888
889 \relates QRhiScissor
890*/
891bool operator!=(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW
892{
893 return !(a == b);
894}
895
896/*!
897 \return the hash value for \a v, using \a seed to seed the calculation.
898
899 \relates QRhiScissor
900 */
901uint qHash(const QRhiScissor &v, uint seed) Q_DECL_NOTHROW
902{
903 const std::array<int, 4> r = v.scissor();
904 return seed + uint(r[0]) + uint(r[1]) + uint(r[2]) + uint(r[3]);
905}
906
907#ifndef QT_NO_DEBUG_STREAM
908QDebug operator<<(QDebug dbg, const QRhiScissor &s)
909{
910 QDebugStateSaver saver(dbg);
911 const std::array<int, 4> r = s.scissor();
912 dbg.nospace() << "QRhiScissor(bottom-left-x=" << r[0]
913 << " bottom-left-y=" << r[1]
914 << " width=" << r[2]
915 << " height=" << r[3]
916 << ')';
917 return dbg;
918}
919#endif
920
921/*!
922 \class QRhiVertexInputBinding
923 \internal
924 \inmodule QtGui
925 \brief Describes a vertex input binding.
926
927 Specifies the stride (in bytes, must be a multiple of 4), the
928 classification and optionally the instance step rate.
929
930 As an example, assume a vertex shader with the following inputs:
931
932 \badcode
933 layout(location = 0) in vec4 position;
934 layout(location = 1) in vec2 texcoord;
935 \endcode
936
937 Now let's assume also that 3 component vertex positions \c{(x, y, z)} and 2
938 component texture coordinates \c{(u, v)} are provided in a non-interleaved
939 format in a buffer (or separate buffers even). Definining two bindings
940 could then be done like this:
941
942 \badcode
943 QRhiVertexInputLayout inputLayout;
944 inputLayout.setBindings({
945 { 3 * sizeof(float) },
946 { 2 * sizeof(float) }
947 });
948 \endcode
949
950 Only the stride is interesting here since instancing is not used. The
951 binding number is given by the index of the QRhiVertexInputBinding
952 element in the bindings vector of the QRhiVertexInputLayout.
953
954 Once a graphics pipeline with this vertex input layout is bound, the vertex
955 inputs could be set up like the following for drawing a cube with 36
956 vertices, assuming we have a single buffer with first the positions and
957 then the texture coordinates:
958
959 \badcode
960 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
961 { cubeBuf, 0 },
962 { cubeBuf, 36 * 3 * sizeof(float) }
963 };
964 cb->setVertexInput(0, 2, vbufBindings);
965 \endcode
966
967 Note how the index defined by \c {startBinding + i}, where \c i is the
968 index in the second argument of
969 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}, matches the
970 index of the corresponding entry in the \c bindings vector of the
971 QRhiVertexInputLayout.
972
973 \note the stride must always be a multiple of 4.
974
975 \sa QRhiCommandBuffer::setVertexInput()
976 */
977
978/*!
979 \enum QRhiVertexInputBinding::Classification
980 Describes the input data classification.
981
982 \value PerVertex Data is per-vertex
983 \value PerInstance Data is per-instance
984 */
985
986/*!
987 \fn QRhiVertexInputBinding::QRhiVertexInputBinding()
988
989 Constructs a default vertex input binding description.
990 */
991
992/*!
993 Constructs a vertex input binding description with the specified \a stride,
994 classification \a cls, and instance step rate \a stepRate.
995
996 \note \a stepRate other than 1 is only supported when
997 QRhi::CustomInstanceStepRate is reported to be supported.
998 */
999QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cls, int stepRate)
1000 : m_stride(stride),
1001 m_classification(cls),
1002 m_instanceStepRate(stepRate)
1003{
1004}
1005
1006/*!
1007 \return \c true if the values in the two QRhiVertexInputBinding objects
1008 \a a and \a b are equal.
1009
1010 \relates QRhiVertexInputBinding
1011 */
1012bool operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) Q_DECL_NOTHROW
1013{
1014 return a.stride() == b.stride()
1015 && a.classification() == b.classification()
1016 && a.instanceStepRate() == b.instanceStepRate();
1017}
1018
1019/*!
1020 \return \c false if the values in the two QRhiVertexInputBinding
1021 objects \a a and \a b are equal; otherwise returns \c true.
1022
1023 \relates QRhiVertexInputBinding
1024*/
1025bool operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) Q_DECL_NOTHROW
1026{
1027 return !(a == b);
1028}
1029
1030/*!
1031 \return the hash value for \a v, using \a seed to seed the calculation.
1032
1033 \relates QRhiVertexInputBinding
1034 */
1035uint qHash(const QRhiVertexInputBinding &v, uint seed) Q_DECL_NOTHROW
1036{
1037 return seed + v.stride() + v.classification();
1038}
1039
1040#ifndef QT_NO_DEBUG_STREAM
1041QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
1042{
1043 QDebugStateSaver saver(dbg);
1044 dbg.nospace() << "QRhiVertexInputBinding(stride=" << b.stride()
1045 << " cls=" << b.classification()
1046 << " step-rate=" << b.instanceStepRate()
1047 << ')';
1048 return dbg;
1049}
1050#endif
1051
1052/*!
1053 \class QRhiVertexInputAttribute
1054 \internal
1055 \inmodule QtGui
1056 \brief Describes a single vertex input element.
1057
1058 The members specify the binding number, location, format, and offset for a
1059 single vertex input element.
1060
1061 \note For HLSL it is assumed that the vertex shader uses
1062 \c{TEXCOORD<location>} as the semantic for each input. Hence no separate
1063 semantic name and index.
1064
1065 As an example, assume a vertex shader with the following inputs:
1066
1067 \badcode
1068 layout(location = 0) in vec4 position;
1069 layout(location = 1) in vec2 texcoord;
1070 \endcode
1071
1072 Now let's assume that we have 3 component vertex positions \c{(x, y, z)}
1073 and 2 component texture coordinates \c{(u, v)} are provided in a
1074 non-interleaved format in a buffer (or separate buffers even). Once two
1075 bindings are defined, the attributes could be specified as:
1076
1077 \badcode
1078 QRhiVertexInputLayout inputLayout;
1079 inputLayout.setBindings({
1080 { 3 * sizeof(float) },
1081 { 2 * sizeof(float) }
1082 });
1083 inputLayout.setAttributes({
1084 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1085 { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
1086 });
1087 \endcode
1088
1089 Once a graphics pipeline with this vertex input layout is bound, the vertex
1090 inputs could be set up like the following for drawing a cube with 36
1091 vertices, assuming we have a single buffer with first the positions and
1092 then the texture coordinates:
1093
1094 \badcode
1095 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1096 { cubeBuf, 0 },
1097 { cubeBuf, 36 * 3 * sizeof(float) }
1098 };
1099 cb->setVertexInput(0, 2, vbufBindings);
1100 \endcode
1101
1102 When working with interleaved data, there will typically be just one
1103 binding, with multiple attributes referring to that same buffer binding
1104 point:
1105
1106 \badcode
1107 QRhiVertexInputLayout inputLayout;
1108 inputLayout.setBindings({
1109 { 5 * sizeof(float) }
1110 });
1111 inputLayout.setAttributes({
1112 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1113 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
1114 });
1115 \endcode
1116
1117 and then:
1118
1119 \badcode
1120 const QRhiCommandBuffer::VertexInput vbufBinding(interleavedCubeBuf, 0);
1121 cb->setVertexInput(0, 1, &vbufBinding);
1122 \endcode
1123
1124 \sa QRhiCommandBuffer::setVertexInput()
1125 */
1126
1127/*!
1128 \enum QRhiVertexInputAttribute::Format
1129 Specifies the type of the element data.
1130
1131 \value Float4 Four component float vector
1132 \value Float3 Three component float vector
1133 \value Float2 Two component float vector
1134 \value Float Float
1135 \value UNormByte4 Four component normalized unsigned byte vector
1136 \value UNormByte2 Two component normalized unsigned byte vector
1137 \value UNormByte Normalized unsigned byte
1138 */
1139
1140/*!
1141 \fn QRhiVertexInputAttribute::QRhiVertexInputAttribute()
1142
1143 Constructs a default vertex input attribute description.
1144 */
1145
1146/*!
1147 Constructs a vertex input attribute description with the specified \a
1148 binding number, \a location, \a format, and \a offset.
1149 */
1150QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset)
1151 : m_binding(binding),
1152 m_location(location),
1153 m_format(format),
1154 m_offset(offset)
1155{
1156}
1157
1158/*!
1159 \return \c true if the values in the two QRhiVertexInputAttribute objects
1160 \a a and \a b are equal.
1161
1162 \relates QRhiVertexInputAttribute
1163 */
1164bool operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) Q_DECL_NOTHROW
1165{
1166 return a.binding() == b.binding()
1167 && a.location() == b.location()
1168 && a.format() == b.format()
1169 && a.offset() == b.offset();
1170}
1171
1172/*!
1173 \return \c false if the values in the two QRhiVertexInputAttribute
1174 objects \a a and \a b are equal; otherwise returns \c true.
1175
1176 \relates QRhiVertexInputAttribute
1177*/
1178bool operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) Q_DECL_NOTHROW
1179{
1180 return !(a == b);
1181}
1182
1183/*!
1184 \return the hash value for \a v, using \a seed to seed the calculation.
1185
1186 \relates QRhiVertexInputAttribute
1187 */
1188uint qHash(const QRhiVertexInputAttribute &v, uint seed) Q_DECL_NOTHROW
1189{
1190 return seed + uint(v.binding()) + uint(v.location()) + uint(v.format()) + v.offset();
1191}
1192
1193#ifndef QT_NO_DEBUG_STREAM
1194QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a)
1195{
1196 QDebugStateSaver saver(dbg);
1197 dbg.nospace() << "QRhiVertexInputAttribute(binding=" << a.binding()
1198 << " location=" << a.location()
1199 << " format=" << a.format()
1200 << " offset=" << a.offset()
1201 << ')';
1202 return dbg;
1203}
1204#endif
1205
1206/*!
1207 \class QRhiVertexInputLayout
1208 \internal
1209 \inmodule QtGui
1210 \brief Describes the layout of vertex inputs consumed by a vertex shader.
1211
1212 The vertex input layout is defined by the collections of
1213 QRhiVertexInputBinding and QRhiVertexInputAttribute.
1214 */
1215
1216/*!
1217 \fn QRhiVertexInputLayout::QRhiVertexInputLayout()
1218
1219 Constructs an empty vertex input layout description.
1220 */
1221
1222/*!
1223 \return \c true if the values in the two QRhiVertexInputLayout objects
1224 \a a and \a b are equal.
1225
1226 \relates QRhiVertexInputLayout
1227 */
1228bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW
1229{
1230 return a.m_bindings == b.m_bindings && a.m_attributes == b.m_attributes;
1231}
1232
1233/*!
1234 \return \c false if the values in the two QRhiVertexInputLayout
1235 objects \a a and \a b are equal; otherwise returns \c true.
1236
1237 \relates QRhiVertexInputLayout
1238*/
1239bool operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW
1240{
1241 return !(a == b);
1242}
1243
1244/*!
1245 \return the hash value for \a v, using \a seed to seed the calculation.
1246
1247 \relates QRhiVertexInputLayout
1248 */
1249uint qHash(const QRhiVertexInputLayout &v, uint seed) Q_DECL_NOTHROW
1250{
1251 return qHash(key: v.m_bindings, seed) + qHash(key: v.m_attributes, seed);
1252}
1253
1254#ifndef QT_NO_DEBUG_STREAM
1255template<typename T, int N>
1256QDebug operator<<(QDebug dbg, const QVarLengthArray<T, N> &vla)
1257{
1258 return QtPrivate::printSequentialContainer(dbg, "VLA", vla);
1259}
1260
1261QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
1262{
1263 QDebugStateSaver saver(dbg);
1264 dbg.nospace() << "QRhiVertexInputLayout(bindings=" << v.m_bindings
1265 << " attributes=" << v.m_attributes
1266 << ')';
1267 return dbg;
1268}
1269#endif
1270
1271/*!
1272 \class QRhiShaderStage
1273 \internal
1274 \inmodule QtGui
1275 \brief Specifies the type and the shader code for a shader stage in the pipeline.
1276 */
1277
1278/*!
1279 \enum QRhiShaderStage::Type
1280 Specifies the type of the shader stage.
1281
1282 \value Vertex Vertex stage
1283 \value Fragment Fragment (pixel) stage
1284 \value Compute Compute stage (this may not always be supported at run time)
1285 */
1286
1287/*!
1288 \fn QRhiShaderStage::QRhiShaderStage()
1289
1290 Constructs a shader stage description for the vertex stage with an empty
1291 QShader.
1292 */
1293
1294/*!
1295 Constructs a shader stage description with the \a type of the stage and the
1296 \a shader.
1297
1298 The shader variant \a v defaults to QShader::StandardShader. A
1299 QShader contains multiple source and binary versions of a shader.
1300 In addition, it can also contain variants of the shader with slightly
1301 modified code. \a v can then be used to select the desired variant.
1302 */
1303QRhiShaderStage::QRhiShaderStage(Type type, const QShader &shader, QShader::Variant v)
1304 : m_type(type),
1305 m_shader(shader),
1306 m_shaderVariant(v)
1307{
1308}
1309
1310/*!
1311 \return \c true if the values in the two QRhiShaderStage objects
1312 \a a and \a b are equal.
1313
1314 \relates QRhiShaderStage
1315 */
1316bool operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) Q_DECL_NOTHROW
1317{
1318 return a.type() == b.type()
1319 && a.shader() == b.shader()
1320 && a.shaderVariant() == b.shaderVariant();
1321}
1322
1323/*!
1324 \return \c false if the values in the two QRhiShaderStage
1325 objects \a a and \a b are equal; otherwise returns \c true.
1326
1327 \relates QRhiShaderStage
1328*/
1329bool operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) Q_DECL_NOTHROW
1330{
1331 return !(a == b);
1332}
1333
1334/*!
1335 \return the hash value for \a v, using \a seed to seed the calculation.
1336
1337 \relates QRhiShaderStage
1338 */
1339uint qHash(const QRhiShaderStage &v, uint seed) Q_DECL_NOTHROW
1340{
1341 return v.type() + qHash(s: v.shader(), seed) + v.shaderVariant();
1342}
1343
1344#ifndef QT_NO_DEBUG_STREAM
1345QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
1346{
1347 QDebugStateSaver saver(dbg);
1348 dbg.nospace() << "QRhiShaderStage(type=" << s.type()
1349 << " shader=" << s.shader()
1350 << " variant=" << s.shaderVariant()
1351 << ')';
1352 return dbg;
1353}
1354#endif
1355
1356/*!
1357 \class QRhiColorAttachment
1358 \internal
1359 \inmodule QtGui
1360 \brief Describes the a single color attachment of a render target.
1361
1362 A color attachment is either a QRhiTexture or a QRhiRenderBuffer. The
1363 former, when texture() is set, is used in most cases.
1364
1365 \note texture() and renderBuffer() cannot be both set (be non-null at the
1366 same time).
1367
1368 Setting renderBuffer instead is recommended only when multisampling is
1369 needed. Relying on QRhi::MultisampleRenderBuffer is a better choice than
1370 QRhi::MultisampleTexture in practice since the former is available in more
1371 run time configurations (e.g. when running on OpenGL ES 3.0 which has no
1372 support for multisample textures, but does support multisample
1373 renderbuffers).
1374
1375 When targeting a non-multisample texture, the layer() and level()
1376 indicate the targeted layer (face index \c{0-5} for cubemaps) and mip
1377 level.
1378
1379 When texture() or renderBuffer() is multisample, resolveTexture() can be
1380 set optionally. When set, samples are resolved automatically into that
1381 (non-multisample) texture at the end of the render pass. When rendering
1382 into a multisample renderbuffers, this is the only way to get resolved,
1383 non-multisample content out of them. Multisample textures allow sampling in
1384 shaders so for them this is just one option.
1385
1386 \note when resolving is enabled, the multisample data may not be written
1387 out at all. This means that the multisample texture() must not be used
1388 afterwards with shaders for sampling when resolveTexture() is set.
1389 */
1390
1391/*!
1392 \fn QRhiColorAttachment::QRhiColorAttachment()
1393
1394 Constructs an empty color attachment description.
1395 */
1396
1397/*!
1398 Constructs a color attachment description that specifies \a texture as the
1399 associated color buffer.
1400 */
1401QRhiColorAttachment::QRhiColorAttachment(QRhiTexture *texture)
1402 : m_texture(texture)
1403{
1404}
1405
1406/*!
1407 Constructs a color attachment description that specifies \a renderBuffer as
1408 the associated color buffer.
1409 */
1410QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
1411 : m_renderBuffer(renderBuffer)
1412{
1413}
1414
1415/*!
1416 \class QRhiTextureRenderTargetDescription
1417 \internal
1418 \inmodule QtGui
1419 \brief Describes the color and depth or depth/stencil attachments of a render target.
1420
1421 A texture render target has zero or more textures as color attachments,
1422 zero or one renderbuffer as combined depth/stencil buffer or zero or one
1423 texture as depth buffer.
1424
1425 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
1426 non-null at the same time).
1427 */
1428
1429/*!
1430 \fn QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription()
1431
1432 Constructs an empty texture render target description.
1433 */
1434
1435/*!
1436 Constructs a texture render target description with one attachment
1437 described by \a colorAttachment.
1438 */
1439QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment)
1440{
1441 m_colorAttachments.append(t: colorAttachment);
1442}
1443
1444/*!
1445 Constructs a texture render target description with two attachments, a
1446 color attachment described by \a colorAttachment, and a depth/stencil
1447 attachment with \a depthStencilBuffer.
1448 */
1449QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
1450 QRhiRenderBuffer *depthStencilBuffer)
1451 : m_depthStencilBuffer(depthStencilBuffer)
1452{
1453 m_colorAttachments.append(t: colorAttachment);
1454}
1455
1456/*!
1457 Constructs a texture render target description with two attachments, a
1458 color attachment described by \a colorAttachment, and a depth attachment
1459 with \a depthTexture.
1460
1461 \note \a depthTexture must have a suitable format, such as QRhiTexture::D16
1462 or QRhiTexture::D32F.
1463 */
1464QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
1465 QRhiTexture *depthTexture)
1466 : m_depthTexture(depthTexture)
1467{
1468 m_colorAttachments.append(t: colorAttachment);
1469}
1470
1471/*!
1472 \class QRhiTextureSubresourceUploadDescription
1473 \internal
1474 \inmodule QtGui
1475 \brief Describes the source for one mip level in a layer in a texture upload operation.
1476
1477 The source content is specified either as a QImage or as a raw blob. The
1478 former is only allowed for uncompressed textures with a format that can be
1479 mapped to QImage, while the latter is supported for all formats, including
1480 floating point and compressed.
1481
1482 \note image() and data() cannot be both set at the same time.
1483
1484 destinationTopLeft() specifies the top-left corner of the target
1485 rectangle. Defaults to (0, 0).
1486
1487 An empty sourceSize() (the default) indicates that size is assumed to be
1488 the size of the subresource. With QImage-based uploads this implies that
1489 the size of the source image() must match the subresource. When providing
1490 raw data instead, sufficient number of bytes must be provided in data().
1491
1492 \note With compressed textures the first upload must always match the
1493 subresource size due to graphics API limitations with some backends.
1494
1495 sourceTopLeft() is supported only for QImage-based uploads, and specifies
1496 the top-left corner of the source rectangle.
1497
1498 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
1499 internally, depending on the format and the backend.
1500
1501 When providing raw data, the stride (row pitch, row length in bytes) of the
1502 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
1503 the number of bytes used for one pixel, and there must be no additional
1504 padding between rows. There is no row start alignment requirement.
1505
1506 \note The format of the source data must be compatible with the texture
1507 format. With many graphics APIs the data is copied as-is into a staging
1508 buffer, there is no intermediate format conversion provided by QRhi. This
1509 applies to floating point formats as well, with, for example, RGBA16F
1510 requiring half floats in the source data.
1511 */
1512
1513/*!
1514 \fn QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription()
1515
1516 Constructs an empty subresource description.
1517
1518 \note an empty QRhiTextureSubresourceUploadDescription is not useful on its
1519 own and should not be submitted to a QRhiTextureUploadEntry. At minimum
1520 image or data must be set first.
1521 */
1522
1523/*!
1524 Constructs a mip level description with a \a image.
1525
1526 The \l{QImage::size()}{size} of \a image must match the size of the mip
1527 level. For level 0 that is the \l{QRhiTexture::pixelSize()}{texture size}.
1528
1529 The bit depth of \a image must be compatible with the
1530 \l{QRhiTexture::Format}{texture format}.
1531
1532 To describe a partial upload, call setSourceSize(), setSourceTopLeft(), or
1533 setDestinationTopLeft() afterwards.
1534 */
1535QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QImage &image)
1536 : m_image(image)
1537{
1538}
1539
1540/*!
1541 Constructs a mip level description with the image data is specified by \a
1542 data and \a size. This is suitable for floating point and compressed
1543 formats as well.
1544
1545 \a data can safely be destroyed or changed once this function returns.
1546 */
1547QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const void *data, int size)
1548 : m_data(reinterpret_cast<const char *>(data), size)
1549{
1550}
1551
1552/*!
1553 \class QRhiTextureUploadEntry
1554 \internal
1555 \inmodule QtGui
1556 \brief Describes one layer (face for cubemaps) in a texture upload operation.
1557 */
1558
1559/*!
1560 \fn QRhiTextureUploadEntry::QRhiTextureUploadEntry()
1561
1562 Constructs an empty QRhiTextureUploadEntry targeting layer 0 and level 0.
1563
1564 \note an empty QRhiTextureUploadEntry should not be submitted without
1565 setting a QRhiTextureSubresourceUploadDescription via setDescription()
1566 first.
1567 */
1568
1569/*!
1570 Constructs a QRhiTextureUploadEntry targeting the given \a layer and mip
1571 \a level, with the subresource contents described by \a desc.
1572 */
1573QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
1574 const QRhiTextureSubresourceUploadDescription &desc)
1575 : m_layer(layer),
1576 m_level(level),
1577 m_desc(desc)
1578{
1579}
1580
1581/*!
1582 \class QRhiTextureUploadDescription
1583 \internal
1584 \inmodule QtGui
1585 \brief Describes a texture upload operation.
1586
1587 Used with QRhiResourceUpdateBatch::uploadTexture(). That function has two
1588 variants: one taking a QImage and one taking a
1589 QRhiTextureUploadDescription. The former is a convenience version,
1590 internally creating a QRhiTextureUploadDescription with a single image
1591 targeting level 0 for layer 0. However, when cubemaps, pre-generated mip
1592 images, or compressed textures are involved, applications will have to work
1593 directly with this class instead.
1594
1595 QRhiTextureUploadDescription also enables specifying batched uploads, which
1596 are useful for example when generating an atlas or glyph cache texture:
1597 multiple, partial uploads for the same subresource (meaning the same layer
1598 and level) are supported, and can be, depending on the backend and the
1599 underlying graphics API, more efficient when batched into the same
1600 QRhiTextureUploadDescription as opposed to issuing individual
1601 \l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} commands for
1602 each of them.
1603
1604 \note Cubemaps have one layer for each of the six faces in the order +X,
1605 -X, +Y, -Y, +Z, -Z.
1606
1607 For example, specifying the faces of a cubemap could look like the following:
1608
1609 \badcode
1610 QImage faces[6];
1611 ...
1612 QVector<QRhiTextureUploadEntry> entries;
1613 for (int i = 0; i < 6; ++i)
1614 entries.append(QRhiTextureUploadEntry(i, 0, faces[i]));
1615 QRhiTextureUploadDescription desc(entries);
1616 resourceUpdates->uploadTexture(texture, desc);
1617 \endcode
1618
1619 Another example that specifies mip images for a compressed texture:
1620
1621 \badcode
1622 QRhiTextureUploadDescription desc;
1623 const int mipCount = rhi->mipLevelsForSize(compressedTexture->pixelSize());
1624 for (int level = 0; level < mipCount; ++level) {
1625 const QByteArray compressedDataForLevel = ..
1626 desc.append(QRhiTextureUploadEntry(0, level, compressedDataForLevel));
1627 }
1628 resourceUpdates->uploadTexture(compressedTexture, desc);
1629 \endcode
1630
1631 With partial uploads targeting the same subresource, it is recommended to
1632 batch them into a single upload request, whenever possible:
1633
1634 \badcode
1635 QRhiTextureSubresourceUploadDescription subresDesc(image);
1636 subresDesc.setSourceSize(QSize(10, 10));
1637 subResDesc.setDestinationTopLeft(QPoint(50, 40));
1638 QRhiTextureUploadEntry entry(0, 0, subresDesc); // layer 0, level 0
1639
1640 QRhiTextureSubresourceUploadDescription subresDesc2(image);
1641 subresDesc2.setSourceSize(QSize(30, 40));
1642 subResDesc2.setDestinationTopLeft(QPoint(100, 200));
1643 QRhiTextureUploadEntry entry2(0, 0, subresDesc2); // layer 0, level 0, i.e. same subresource
1644
1645 QRhiTextureUploadDescription desc({ entry, entry2});
1646 resourceUpdates->uploadTexture(texture, desc);
1647 \endcode
1648 */
1649
1650/*!
1651 \fn QRhiTextureUploadDescription::QRhiTextureUploadDescription()
1652
1653 Constructs an empty texture upload description.
1654 */
1655
1656/*!
1657 Constructs a texture upload description with a single subresource upload
1658 described by \a entry.
1659 */
1660QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry)
1661{
1662 m_entries.append(t: entry);
1663}
1664
1665/*!
1666 Constructs a texture upload description with the specified \a list of entries.
1667
1668 \note \a list can also contain multiple QRhiTextureUploadEntry elements
1669 with the same layer and level. This makes sense when those uploads are
1670 partial, meaning their subresource description has a source size or image
1671 smaller than the subresource dimensions, and can be more efficient than
1672 issuing separate uploadTexture()'s.
1673 */
1674QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list)
1675 : m_entries(list)
1676{
1677}
1678
1679/*!
1680 \class QRhiTextureCopyDescription
1681 \internal
1682 \inmodule QtGui
1683 \brief Describes a texture-to-texture copy operation.
1684
1685 An empty pixelSize() indicates that the entire subresource is to be copied.
1686 A default constructed copy description therefore leads to copying the
1687 entire subresource at level 0 of layer 0.
1688
1689 \note The source texture must be created with
1690 QRhiTexture::UsedAsTransferSource.
1691
1692 \note The source and destination rectangles defined by pixelSize(),
1693 sourceTopLeft(), and destinationTopLeft() must fit the source and
1694 destination textures, respectively. The behavior is undefined otherwise.
1695 */
1696
1697/*!
1698 \fn QRhiTextureCopyDescription::QRhiTextureCopyDescription()
1699
1700 Constructs an empty texture copy description.
1701 */
1702
1703/*!
1704 \class QRhiReadbackDescription
1705 \internal
1706 \inmodule QtGui
1707 \brief Describes a readback (reading back texture contents from possibly GPU-only memory) operation.
1708
1709 The source of the readback operation is either a QRhiTexture or the
1710 current backbuffer of the currently targeted QRhiSwapChain. When
1711 texture() is not set, the swapchain is used. Otherwise the specified
1712 QRhiTexture is treated as the source.
1713
1714 \note Textures used in readbacks must be created with
1715 QRhiTexture::UsedAsTransferSource.
1716
1717 \note Swapchains used in readbacks must be created with
1718 QRhiSwapChain::UsedAsTransferSource.
1719
1720 layer() and level() are only applicable when the source is a QRhiTexture.
1721
1722 \note Multisample textures cannot be read back. Readbacks are supported for
1723 multisample swapchain buffers however.
1724 */
1725
1726/*!
1727 \fn QRhiReadbackDescription::QRhiReadbackDescription()
1728
1729 Constructs an empty texture readback description.
1730
1731 \note The source texture is set to null by default, which is still a valid
1732 readback: it specifies that the backbuffer of the current swapchain is to
1733 be read back. (current meaning the frame's target swapchain at the time of
1734 committing the QRhiResourceUpdateBatch with the
1735 \l{QRhiResourceUpdateBatch::readBackTexture()}{texture readback} on it)
1736 */
1737
1738/*!
1739 Constructs an texture readback description that specifies that level 0 of
1740 layer 0 of \a texture is to be read back.
1741
1742 \note \a texture can also be null in which case this constructor is
1743 identical to the argumentless variant.
1744 */
1745QRhiReadbackDescription::QRhiReadbackDescription(QRhiTexture *texture)
1746 : m_texture(texture)
1747{
1748}
1749
1750/*!
1751 \class QRhiReadbackResult
1752 \internal
1753 \inmodule QtGui
1754 \brief Describes the results of a potentially asynchronous readback operation.
1755
1756 When \l completed is set, the function is invoked when the \l data is
1757 available. \l format and \l pixelSize are set upon completion together with
1758 \l data.
1759 */
1760
1761/*!
1762 \class QRhiNativeHandles
1763 \internal
1764 \inmodule QtGui
1765 \brief Base class for classes exposing backend-specific collections of native resource objects.
1766 */
1767
1768/*!
1769 \class QRhiResource
1770 \internal
1771 \inmodule QtGui
1772 \brief Base class for classes encapsulating native resource objects.
1773 */
1774
1775/*!
1776 \fn QRhiResource::Type QRhiResource::resourceType() const
1777
1778 \return the type of the resource.
1779 */
1780
1781/*!
1782 \internal
1783 */
1784QRhiResource::QRhiResource(QRhiImplementation *rhi)
1785 : m_rhi(rhi)
1786{
1787 m_id = QRhiGlobalObjectIdGenerator::newId();
1788}
1789
1790/*!
1791 Destructor.
1792
1793 Releases (or requests deferred releasing of) the underlying native graphics
1794 resources, if there are any.
1795
1796 \note Resources referenced by commands for the current frame should not be
1797 released until the frame is submitted by QRhi::endFrame().
1798
1799 \sa release()
1800 */
1801QRhiResource::~QRhiResource()
1802{
1803 // release() cannot be called here, it being virtual; it is up to the
1804 // subclasses to do that.
1805}
1806
1807/*!
1808 \fn void QRhiResource::release()
1809
1810 Releases (or requests deferred releasing of) the underlying native graphics
1811 resources. Safe to call multiple times, subsequent invocations will be a
1812 no-op then.
1813
1814 Once release() is called, the QRhiResource instance can be reused, by
1815 calling \c build() again. That will then result in creating new native
1816 graphics resources underneath.
1817
1818 \note Resources referenced by commands for the current frame should not be
1819 released until the frame is submitted by QRhi::endFrame().
1820
1821 The QRhiResource destructor also performs the same task, so calling this
1822 function is not necessary before destroying a QRhiResource.
1823
1824 \sa releaseAndDestroyLater()
1825 */
1826
1827/*!
1828 When called without a frame being recorded, this function is equivalent to
1829 deleting the object. Between a QRhi::beginFrame() and QRhi::endFrame()
1830 however the behavior is different: the QRhiResource will not be destroyed
1831 until the frame is submitted via QRhi::endFrame(), thus satisfying the QRhi
1832 requirement of not altering QRhiResource objects that are referenced by the
1833 frame being recorded.
1834
1835 \sa release()
1836 */
1837void QRhiResource::releaseAndDestroyLater()
1838{
1839 m_rhi->addReleaseAndDestroyLater(res: this);
1840}
1841
1842/*!
1843 \return the currently set object name. By default the name is empty.
1844 */
1845QByteArray QRhiResource::name() const
1846{
1847 return m_objectName;
1848}
1849
1850/*!
1851 Sets a \a name for the object.
1852
1853 This has two uses: to get descriptive names for the native graphics
1854 resources visible in graphics debugging tools, such as
1855 \l{https://renderdoc.org/}{RenderDoc} and
1856 \l{https://developer.apple.com/xcode/}{XCode}, and in the output stream of
1857 QRhiProfiler.
1858
1859 When it comes to naming native objects by relaying the name via the
1860 appropriate graphics API, note that the name is ignored when
1861 QRhi::DebugMarkers are not supported, and may, depending on the backend,
1862 also be ignored when QRhi::EnableDebugMarkers is not set.
1863
1864 \note The name may be ignored for objects other than buffers,
1865 renderbuffers, and textures, depending on the backend.
1866
1867 \note The name may be modified. For slotted resources, such as a QRhiBuffer
1868 backed by multiple native buffers, QRhi will append a suffix to make the
1869 underlying native buffers easily distinguishable from each other.
1870 */
1871void QRhiResource::setName(const QByteArray &name)
1872{
1873 m_objectName = name;
1874 m_objectName.replace(before: ',', after: '_'); // cannot contain comma for QRhiProfiler
1875}
1876
1877/*!
1878 \return the global, unique identifier of this QRhiResource.
1879
1880 User code rarely needs to deal with the value directly. It is used
1881 internally for tracking and bookkeeping purposes.
1882 */
1883quint64 QRhiResource::globalResourceId() const
1884{
1885 return m_id;
1886}
1887
1888/*!
1889 \class QRhiBuffer
1890 \internal
1891 \inmodule QtGui
1892 \brief Vertex, index, or uniform (constant) buffer resource.
1893 */
1894
1895/*!
1896 \enum QRhiBuffer::Type
1897 Specifies storage type of buffer resource.
1898
1899 \value Immutable Indicates that the data is not expected to change ever
1900 after the initial upload. Under the hood such buffer resources are
1901 typically placed in device local (GPU) memory (on systems where
1902 applicable). Uploading new data is possible, but may be expensive. The
1903 upload typically happens by copying to a separate, host visible staging
1904 buffer from which a GPU buffer-to-buffer copy is issued into the actual
1905 GPU-only buffer.
1906
1907 \value Static Indicates that the data is expected to change only
1908 infrequently. Typically placed in device local (GPU) memory, where
1909 applicable. On backends where host visible staging buffers are used for
1910 uploading, the staging buffers are kept around for this type, unlike with
1911 Immutable, so subsequent uploads do not suffer in performance. Frequent
1912 updates, especially updates in consecutive frames, should be avoided.
1913
1914 \value Dynamic Indicates that the data is expected to change frequently.
1915 Not recommended for large buffers. Typically backed by host visible memory
1916 in 2 copies in order to allow for changing without stalling the graphics
1917 pipeline. The double buffering is managed transparently to the applications
1918 and is not exposed in the API here in any form. This is the recommended,
1919 and, with some backends, the only possible, type for buffers with
1920 UniformBuffer usage.
1921 */
1922
1923/*!
1924 \enum QRhiBuffer::UsageFlag
1925 Flag values to specify how the buffer is going to be used.
1926
1927 \value VertexBuffer Vertex buffer. This allows the QRhiBuffer to be used in
1928 \l{setVertexInput()}{QRhiCommandBuffer::setVertexInput()}.
1929
1930 \value IndexBuffer Index buffer. This allows the QRhiBuffer to be used in
1931 \l{setVertexInput()}{QRhiCommandBuffer::setVertexInput()}.
1932
1933 \value UniformBuffer Uniform buffer (also called constant buffer). This
1934 allows the QRhiBuffer to be used in combination with
1935 \l{UniformBuffer}{QRhiShaderResourceBinding::UniformBuffer}. When
1936 \l{QRhi::NonDynamicUniformBuffers}{NonDynamicUniformBuffers} is reported as
1937 not supported, this usage can only be combined with the type Dynamic.
1938
1939 \value StorageBuffer Storage buffer. This allows the QRhiBuffer to be used
1940 in combination with \l{BufferLoad}{QRhiShaderResourceBinding::BufferLoad},
1941 \l{BufferStore}{QRhiShaderResourceBinding::BufferStore}, or
1942 \l{BufferLoadStore}{QRhiShaderResourceBinding::BufferLoadStore}. This usage
1943 can only be combined with the types Immutable or Static, and is only
1944 available when the \l{QRhi::Compute}{Compute feature} is reported as
1945 supported.
1946 */
1947
1948/*!
1949 \fn void QRhiBuffer::setSize(int sz)
1950
1951 Sets the size of the buffer in bytes. The size is normally specified in
1952 QRhi::newBuffer() so this function is only used when the size has to be
1953 changed. As with other setters, the size only takes effect when calling
1954 build(), and for already built buffers this involves releasing the previous
1955 native resource and creating new ones under the hood.
1956
1957 Backends may choose to allocate buffers bigger than \a sz in order to
1958 fulfill alignment requirements. This is hidden from the applications and
1959 size() will always report the size requested in \a sz.
1960 */
1961
1962/*!
1963 \class QRhiBuffer::NativeBuffer
1964 \brief Contains information about the underlying native resources of a buffer.
1965 */
1966
1967/*!
1968 \variable QRhiBuffer::NativeBuffer::objects
1969 \brief an array with pointers to the native object handles.
1970
1971 With OpenGL, the native handle is a GLuint value, so the elements in the \c
1972 objects array are pointers to a GLuint. With Vulkan, the native handle is a
1973 VkBuffer, so the elements of the array are pointers to a VkBuffer. With
1974 Direct3D 11 and Metal the elements are pointers to a ID3D11Buffer or
1975 MTLBuffer pointer, respectively.
1976
1977 \note Pay attention to the fact that the elements are always pointers to
1978 the native buffer handle type, even if the native type itself is a pointer.
1979 */
1980
1981/*!
1982 \variable QRhiBuffer::NativeBuffer::slotCount
1983 \brief Specifies the number of valid elements in the objects array.
1984
1985 The value can be 0, 1, 2, or 3 in practice. 0 indicates that the QRhiBuffer
1986 is not backed by any native buffer objects. This can happen with
1987 QRhiBuffers with the usage UniformBuffer when the underlying API does not
1988 support (or the backend chooses not to use) native uniform buffers. 1 is
1989 commonly used for Immutable and Static types (but some backends may
1990 differ). 2 or 3 is typical when the type is Dynamic (but some backends may
1991 differ).
1992
1993 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
1994 */
1995
1996/*!
1997 \internal
1998 */
1999QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, int size_)
2000 : QRhiResource(rhi),
2001 m_type(type_), m_usage(usage_), m_size(size_)
2002{
2003}
2004
2005/*!
2006 \return the resource type.
2007 */
2008QRhiResource::Type QRhiBuffer::resourceType() const
2009{
2010 return Buffer;
2011}
2012
2013/*!
2014 \fn bool QRhiBuffer::build()
2015
2016 Creates the corresponding native graphics resources. If there are already
2017 resources present due to an earlier build() with no corresponding
2018 release(), then release() is called implicitly first.
2019
2020 \return \c true when successful, \c false when a graphics operation failed.
2021 Regardless of the return value, calling release() is always safe.
2022 */
2023
2024/*!
2025 \return the underlying native resources for this buffer. The returned value
2026 will be empty if exposing the underlying native resources is not supported by
2027 the backend.
2028
2029 A QRhiBuffer may be backed by multiple native buffer objects, depending on
2030 the type() and the QRhi backend in use. When this is the case, all of them
2031 are returned in the objects array in the returned struct, with slotCount
2032 specifying the number of native buffer objects. While
2033 \l{QRhi::beginFrame()}{recording a frame}, QRhi::currentFrameSlot() can be
2034 used to determine which of the native buffers QRhi is using for operations
2035 that read or write from this QRhiBuffer within the frame being recorded.
2036
2037 In some cases a QRhiBuffer will not be backed by a native buffer object at
2038 all. In this case slotCount will be set to 0 and no valid native objects
2039 are returned. This is not an error, and is perfectly valid when a given
2040 backend does not use native buffers for QRhiBuffers with certain types or
2041 usages.
2042
2043 \note Be aware that QRhi backends may employ various buffer update
2044 strategies. Unlike textures, where uploading image data always means
2045 recording a buffer-to-image (or similar) copy command on the command
2046 buffer, buffers, in particular Dynamic and UniformBuffer ones, can operate
2047 in many different ways. For example, a QRhiBuffer with usage type
2048 UniformBuffer may not even be backed by a native buffer object at all if
2049 uniform buffers are not used or supported by a given backend and graphics
2050 API. There are also differences to how data is written to the buffer and
2051 the type of backing memory used. For buffers backed by host visible memory,
2052 calling this function guarantees that pending host writes are executed for
2053 all the returned native buffers.
2054
2055 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
2056 */
2057QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
2058{
2059 return {};
2060}
2061
2062/*!
2063 \class QRhiRenderBuffer
2064 \internal
2065 \inmodule QtGui
2066 \brief Renderbuffer resource.
2067
2068 Renderbuffers cannot be sampled or read but have some benefits over
2069 textures in some cases:
2070
2071 A DepthStencil renderbuffer may be lazily allocated and be backed by
2072 transient memory with some APIs. On some platforms this may mean the
2073 depth/stencil buffer uses no physical backing at all.
2074
2075 Color renderbuffers are useful since QRhi::MultisampleRenderBuffer may be
2076 supported even when QRhi::MultisampleTexture is not.
2077
2078 How the renderbuffer is implemented by a backend is not exposed to the
2079 applications. In some cases it may be backed by ordinary textures, while in
2080 others there may be a different kind of native resource used.
2081
2082 Renderbuffers that are used as (and are only used as) depth-stencil buffers
2083 in combination with a QRhiSwapChain's color buffers should have the
2084 UsedWithSwapChainOnly flag set. This serves a double purpose: such buffers,
2085 depending on the backend and the underlying APIs, be more efficient, and
2086 QRhi provides automatic sizing behavior to match the color buffers, which
2087 means calling setPixelSize() and build() are not necessary for such
2088 renderbuffers.
2089 */
2090
2091/*!
2092 \enum QRhiRenderBuffer::Type
2093 Specifies the type of the renderbuffer
2094
2095 \value DepthStencil Combined depth/stencil
2096 \value Color Color
2097 */
2098
2099/*!
2100 \enum QRhiRenderBuffer::Flag
2101 Flag values for flags() and setFlags()
2102
2103 \value UsedWithSwapChainOnly For DepthStencil renderbuffers this indicates
2104 that the renderbuffer is only used in combination with a QRhiSwapChain, and
2105 never in any other way. This provides automatic sizing and resource
2106 rebuilding, so calling setPixelSize() or build() is not needed whenever
2107 this flag is set. This flag value may also trigger backend-specific
2108 behavior, for example with OpenGL, where a separate windowing system
2109 interface API is in use (EGL, GLX, etc.), the flag is especially important
2110 as it avoids creating any actual renderbuffer resource as there is already
2111 a windowing system provided depth/stencil buffer as requested by
2112 QSurfaceFormat.
2113 */
2114
2115/*!
2116 \internal
2117 */
2118QRhiRenderBuffer::QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
2119 int sampleCount_, Flags flags_)
2120 : QRhiResource(rhi),
2121 m_type(type_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_)
2122{
2123}
2124
2125/*!
2126 \return the resource type.
2127 */
2128QRhiResource::Type QRhiRenderBuffer::resourceType() const
2129{
2130 return RenderBuffer;
2131}
2132
2133/*!
2134 \fn bool QRhiRenderBuffer::build()
2135
2136 Creates the corresponding native graphics resources. If there are already
2137 resources present due to an earlier build() with no corresponding
2138 release(), then release() is called implicitly first.
2139
2140 \return \c true when successful, \c false when a graphics operation failed.
2141 Regardless of the return value, calling release() is always safe.
2142 */
2143
2144/*!
2145 \fn QRhiTexture::Format QRhiRenderBuffer::backingFormat() const
2146
2147 \internal
2148 */
2149
2150/*!
2151 \class QRhiTexture
2152 \internal
2153 \inmodule QtGui
2154 \brief Texture resource.
2155 */
2156
2157/*!
2158 \enum QRhiTexture::Flag
2159
2160 Flag values to specify how the texture is going to be used. Not honoring
2161 the flags set before build() and attempting to use the texture in ways that
2162 was not declared upfront can lead to unspecified behavior or decreased
2163 performance depending on the backend and the underlying graphics API.
2164
2165 \value RenderTarget The texture going to be used in combination with
2166 QRhiTextureRenderTarget.
2167
2168 \value CubeMap The texture is a cubemap. Such textures have 6 layers, one
2169 for each face in the order of +X, -X, +Y, -Y, +Z, -Z. Cubemap textures
2170 cannot be multisample.
2171
2172 \value MipMapped The texture has mipmaps. The appropriate mip count is
2173 calculated automatically and can also be retrieved via
2174 QRhi::mipLevelsForSize(). The images for the mip levels have to be
2175 provided in the texture uploaded or generated via
2176 QRhiResourceUpdateBatch::generateMips(). Multisample textures cannot have
2177 mipmaps.
2178
2179 \value sRGB Use an sRGB format.
2180
2181 \value UsedAsTransferSource The texture is used as the source of a texture
2182 copy or readback, meaning the texture is given as the source in
2183 QRhiResourceUpdateBatch::copyTexture() or
2184 QRhiResourceUpdateBatch::readBackTexture().
2185
2186 \value UsedWithGenerateMips The texture is going to be used with
2187 QRhiResourceUpdateBatch::generateMips().
2188
2189 \value UsedWithLoadStore The texture is going to be used with image
2190 load/store operations, for example, in a compute shader.
2191 */
2192
2193/*!
2194 \enum QRhiTexture::Format
2195
2196 Specifies the texture format. See also QRhi::isTextureFormatSupported() and
2197 note that flags() can modify the format when QRhiTexture::sRGB is set.
2198
2199 \value UnknownFormat Not a valid format. This cannot be passed to setFormat().
2200
2201 \value RGBA8 Four component, unsigned normalized 8 bit per component. Always supported.
2202
2203 \value BGRA8 Four component, unsigned normalized 8 bit per component.
2204
2205 \value R8 One component, unsigned normalized 8 bit.
2206
2207 \value R16 One component, unsigned normalized 16 bit.
2208
2209 \value RED_OR_ALPHA8 Either same as R8, or is a similar format with the component swizzled to alpha,
2210 depending on \l{QRhi::RedOrAlpha8IsRed}{RedOrAlpha8IsRed}.
2211
2212 \value RGBA16F Four components, 16-bit float per component.
2213
2214 \value RGBA32F Four components, 32-bit float per component.
2215
2216 \value D16 16-bit depth (normalized unsigned integer)
2217
2218 \value D32F 32-bit depth (32-bit float)
2219
2220 \value BC1
2221 \value BC2
2222 \value BC3
2223 \value BC4
2224 \value BC5
2225 \value BC6H
2226 \value BC7
2227
2228 \value ETC2_RGB8
2229 \value ETC2_RGB8A1
2230 \value ETC2_RGBA8
2231
2232 \value ASTC_4x4
2233 \value ASTC_5x4
2234 \value ASTC_5x5
2235 \value ASTC_6x5
2236 \value ASTC_6x6
2237 \value ASTC_8x5
2238 \value ASTC_8x6
2239 \value ASTC_8x8
2240 \value ASTC_10x5
2241 \value ASTC_10x6
2242 \value ASTC_10x8
2243 \value ASTC_10x10
2244 \value ASTC_12x10
2245 \value ASTC_12x12
2246 */
2247
2248/*!
2249 \class QRhiTexture::NativeTexture
2250 \brief Contains information about the underlying native resources of a texture.
2251 */
2252
2253/*!
2254 \variable QRhiTexture::NativeTexture::object
2255 \brief a pointer to the native object handle.
2256
2257 With OpenGL, the native handle is a GLuint value, so \c object is then a
2258 pointer to a GLuint. With Vulkan, the native handle is a VkImage, so \c
2259 object is a pointer to a VkImage. With Direct3D 11 and Metal \c
2260 object is a pointer to a ID3D11Texture2D or MTLTexture pointer, respectively.
2261
2262 \note Pay attention to the fact that \a object is always a pointer
2263 to the native texture handle type, even if the native type itself is a
2264 pointer.
2265 */
2266
2267/*!
2268 \variable QRhiTexture::NativeTexture::layout
2269 \brief Specifies the current image layout for APIs like Vulkan.
2270
2271 For Vulkan, \c layout contains a \c VkImageLayout value.
2272 */
2273
2274/*!
2275 \internal
2276 */
2277QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_,
2278 int sampleCount_, Flags flags_)
2279 : QRhiResource(rhi),
2280 m_format(format_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_)
2281{
2282}
2283
2284/*!
2285 \return the resource type.
2286 */
2287QRhiResource::Type QRhiTexture::resourceType() const
2288{
2289 return Texture;
2290}
2291
2292/*!
2293 \fn bool QRhiTexture::build()
2294
2295 Creates the corresponding native graphics resources. If there are already
2296 resources present due to an earlier build() with no corresponding
2297 release(), then release() is called implicitly first.
2298
2299 \return \c true when successful, \c false when a graphics operation failed.
2300 Regardless of the return value, calling release() is always safe.
2301 */
2302
2303/*!
2304 \return the underlying native resources for this texture. The returned value
2305 will be empty if exposing the underlying native resources is not supported by
2306 the backend.
2307
2308 \sa buildFrom()
2309 */
2310QRhiTexture::NativeTexture QRhiTexture::nativeTexture()
2311{
2312 return {};
2313}
2314
2315/*!
2316 Similar to build() except that no new native textures are created. Instead,
2317 the native texture resources specified by \a src is used.
2318
2319 This allows importing an existing native texture object (which must belong
2320 to the same device or sharing context, depending on the graphics API) from
2321 an external graphics engine.
2322
2323 \note format(), pixelSize(), sampleCount(), and flags() must still be set
2324 correctly. Passing incorrect sizes and other values to QRhi::newTexture()
2325 and then following it with a buildFrom() expecting that the native texture
2326 object alone is sufficient to deduce such values is \b wrong and will lead
2327 to problems.
2328
2329 \note QRhiTexture does not take ownership of the texture object. release()
2330 does not free the object or any associated memory.
2331
2332 The opposite of this operation, exposing a QRhiTexture-created native
2333 texture object to a foreign engine, is possible via nativeTexture().
2334
2335*/
2336bool QRhiTexture::buildFrom(QRhiTexture::NativeTexture src)
2337{
2338 Q_UNUSED(src);
2339 return false;
2340}
2341
2342/*!
2343 With some graphics APIs, such as Vulkan, integrating custom rendering code
2344 that uses the graphics API directly needs special care when it comes to
2345 image layouts. This function allows communicating the expected layout the
2346 image backing the QRhiTexture is in after the native rendering commands.
2347
2348 For example, consider rendering into a QRhiTexture's VkImage directly with
2349 Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and
2350 QRhiCommandBuffer::endExternal(), followed by using the image for texture
2351 sampling in a QRhi-based render pass. To avoid potentially incorrect image
2352 layout transitions, this function can be used to indicate what the image
2353 layout will be once the commands recorded in said code block complete.
2354
2355 Calling this function makes sense only after
2356 QRhiCommandBuffer::endExternal() and before a subsequent
2357 QRhiCommandBuffer::beginPass().
2358
2359 This function has no effect with QRhi backends where the underlying
2360 graphics API does not expose a concept of image layouts.
2361 */
2362void QRhiTexture::setNativeLayout(int layout)
2363{
2364 Q_UNUSED(layout);
2365}
2366
2367/*!
2368 \class QRhiSampler
2369 \internal
2370 \inmodule QtGui
2371 \brief Sampler resource.
2372 */
2373
2374/*!
2375 \enum QRhiSampler::Filter
2376 Specifies the minification, magnification, or mipmap filtering
2377
2378 \value None Applicable only for mipmapMode(), indicates no mipmaps to be used
2379 \value Nearest
2380 \value Linear
2381 */
2382
2383/*!
2384 \enum QRhiSampler::AddressMode
2385 Specifies the addressing mode
2386
2387 \value Repeat
2388 \value ClampToEdge
2389 \value Mirror
2390 */
2391
2392/*!
2393 \enum QRhiSampler::CompareOp
2394 Specifies the texture comparison function.
2395
2396 \value Never (default)
2397 \value Less
2398 \value Equal
2399 \value LessOrEqual
2400 \value Greater
2401 \value NotEqual
2402 \value GreaterOrEqual
2403 \value Always
2404 */
2405
2406/*!
2407 \internal
2408 */
2409QRhiSampler::QRhiSampler(QRhiImplementation *rhi,
2410 Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
2411 AddressMode u_, AddressMode v_, AddressMode w_)
2412 : QRhiResource(rhi),
2413 m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_),
2414 m_addressU(u_), m_addressV(v_), m_addressW(w_),
2415 m_compareOp(QRhiSampler::Never)
2416{
2417}
2418
2419/*!
2420 \return the resource type.
2421 */
2422QRhiResource::Type QRhiSampler::resourceType() const
2423{
2424 return Sampler;
2425}
2426
2427/*!
2428 \class QRhiRenderPassDescriptor
2429 \internal
2430 \inmodule QtGui
2431 \brief Render pass resource.
2432
2433 A render pass, if such a concept exists in the underlying graphics API, is
2434 a collection of attachments (color, depth, stencil) and describes how those
2435 attachments are used.
2436 */
2437
2438/*!
2439 \internal
2440 */
2441QRhiRenderPassDescriptor::QRhiRenderPassDescriptor(QRhiImplementation *rhi)
2442 : QRhiResource(rhi)
2443{
2444}
2445
2446/*!
2447 \return the resource type.
2448 */
2449QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
2450{
2451 return RenderPassDescriptor;
2452}
2453
2454/*!
2455 \fn bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const;
2456
2457 \return true if the \a other QRhiRenderPassDescriptor is compatible with
2458 this one, meaning \c this and \a other can be used interchangebly in
2459 QRhiGraphicsPipeline::setRenderPassDescriptor().
2460
2461 The concept of the compatibility of renderpass descriptors is similar to
2462 the \l{QRhiShaderResourceBindings::isLayoutCompatible}{layout
2463 compatibility} of QRhiShaderResourceBindings instances. They allow better
2464 reuse of QRhiGraphicsPipeline instances: for example, a
2465 QRhiGraphicsPipeline instance cache is expected to use these functions to
2466 look for a matching pipeline, instead of just comparing pointers, thus
2467 allowing a different QRhiRenderPassDescriptor and
2468 QRhiShaderResourceBindings to be used in combination with the pipeline, as
2469 long as they are compatible.
2470 */
2471
2472/*!
2473 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
2474 QRhiVulkanRenderPassNativeHandles. The returned value is \nullptr when exposing
2475 the underlying native resources is not supported by the backend.
2476
2477 \sa QRhiVulkanRenderPassNativeHandles
2478 */
2479const QRhiNativeHandles *QRhiRenderPassDescriptor::nativeHandles()
2480{
2481 return nullptr;
2482}
2483
2484/*!
2485 \class QRhiRenderTarget
2486 \internal
2487 \inmodule QtGui
2488 \brief Represents an onscreen (swapchain) or offscreen (texture) render target.
2489 */
2490
2491/*!
2492 \internal
2493 */
2494QRhiRenderTarget::QRhiRenderTarget(QRhiImplementation *rhi)
2495 : QRhiResource(rhi)
2496{
2497}
2498
2499/*!
2500 \return the resource type.
2501 */
2502QRhiResource::Type QRhiRenderTarget::resourceType() const
2503{
2504 return RenderTarget;
2505}
2506
2507/*!
2508 \fn QSize QRhiRenderTarget::pixelSize() const
2509
2510 \return the size in pixels.
2511 */
2512
2513/*!
2514 \fn float QRhiRenderTarget::devicePixelRatio() const
2515
2516 \return the device pixel ratio. For QRhiTextureRenderTarget this is always
2517 1. For targets retrieved from a QRhiSwapChain the value reflects the
2518 \l{QWindow::devicePixelRatio()}{device pixel ratio} of the targeted
2519 QWindow.
2520 */
2521
2522/*!
2523 \class QRhiTextureRenderTarget
2524 \internal
2525 \inmodule QtGui
2526 \brief Texture render target resource.
2527
2528 A texture render target allows rendering into one or more textures,
2529 optionally with a depth texture or depth/stencil renderbuffer.
2530
2531 \note Textures used in combination with QRhiTextureRenderTarget must be
2532 created with the QRhiTexture::RenderTarget flag.
2533
2534 The simplest example of creating a render target with a texture as its
2535 single color attachment:
2536
2537 \badcode
2538 texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
2539 texture->build();
2540 rt = rhi->newTextureRenderTarget({ texture });
2541 rp = rt->newCompatibleRenderPassDescriptor();
2542 rt->setRenderPassDescriptor(rt);
2543 rt->build();
2544 // rt can now be used with beginPass()
2545 \endcode
2546 */
2547
2548/*!
2549 \enum QRhiTextureRenderTarget::Flag
2550
2551 Flag values describing the load/store behavior for the render target. The
2552 load/store behavior may be baked into native resources under the hood,
2553 depending on the backend, and therefore it needs to be known upfront and
2554 cannot be changed without rebuilding (and so releasing and creating new
2555 native resources).
2556
2557 \value PreserveColorContents Indicates that the contents of the color
2558 attachments is to be loaded when starting a render pass, instead of
2559 clearing. This is potentially more expensive, especially on mobile (tiled)
2560 GPUs, but allows preserving the existing contents between passes.
2561
2562 \value PreserveDepthStencilContents Indicates that the contents of the
2563 depth texture is to be loaded when starting a render pass, instead
2564 clearing. Only applicable when a texture is used as the depth buffer
2565 (QRhiTextureRenderTargetDescription::depthTexture() is set) because
2566 depth/stencil renderbuffers may not have any physical backing and data may
2567 not be written out in the first place.
2568 */
2569
2570/*!
2571 \internal
2572 */
2573QRhiTextureRenderTarget::QRhiTextureRenderTarget(QRhiImplementation *rhi,
2574 const QRhiTextureRenderTargetDescription &desc_,
2575 Flags flags_)
2576 : QRhiRenderTarget(rhi),
2577 m_desc(desc_),
2578 m_flags(flags_)
2579{
2580}
2581
2582/*!
2583 \return the resource type.
2584 */
2585QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
2586{
2587 return TextureRenderTarget;
2588}
2589
2590/*!
2591 \fn QRhiRenderPassDescriptor *QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()
2592
2593 \return a new QRhiRenderPassDescriptor that is compatible with this render
2594 target.
2595
2596 The returned value is used in two ways: it can be passed to
2597 setRenderPassDescriptor() and
2598 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
2599 describes the attachments (color, depth/stencil) and the load/store
2600 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
2601 be used in combination with a render target that has the same
2602 QRhiRenderPassDescriptor set.
2603
2604 Two QRhiTextureRenderTarget instances can share the same render pass
2605 descriptor as long as they have the same number and type of attachments.
2606 The associated QRhiTexture or QRhiRenderBuffer instances are not part of
2607 the render pass descriptor so those can differ in the two
2608 QRhiTextureRenderTarget intances.
2609
2610 \note resources, such as QRhiTexture instances, referenced in description()
2611 must already be built
2612
2613 \sa build()
2614 */
2615
2616/*!
2617 \fn bool QRhiTextureRenderTarget::build()
2618
2619 Creates the corresponding native graphics resources. If there are already
2620 resources present due to an earlier build() with no corresponding
2621 release(), then release() is called implicitly first.
2622
2623 \note renderPassDescriptor() must be set before calling build(). To obtain
2624 a QRhiRenderPassDescriptor compatible with the render target, call
2625 newCompatibleRenderPassDescriptor() before build() but after setting all
2626 other parameters, such as description() and flags(). To save resources,
2627 reuse the same QRhiRenderPassDescriptor with multiple
2628 QRhiTextureRenderTarget instances, whenever possible. Sharing the same
2629 render pass descriptor is only possible when the render targets have the
2630 same number and type of attachments (the actual textures can differ) and
2631 the same flags.
2632
2633 \note resources, such as QRhiTexture instances, referenced in description()
2634 must already be built
2635
2636 \return \c true when successful, \c false when a graphics operation failed.
2637 Regardless of the return value, calling release() is always safe.
2638 */
2639
2640/*!
2641 \class QRhiShaderResourceBindings
2642 \internal
2643 \inmodule QtGui
2644 \brief Encapsulates resources for making buffer, texture, sampler resources visible to shaders.
2645
2646 A QRhiShaderResourceBindings is a collection of QRhiShaderResourceBinding
2647 objects, each of which describe a single binding.
2648
2649 Take a fragment shader with the following interface:
2650
2651 \badcode
2652 layout(std140, binding = 0) uniform buf {
2653 mat4 mvp;
2654 int flip;
2655 } ubuf;
2656
2657 layout(binding = 1) uniform sampler2D tex;
2658 \endcode
2659
2660 To make resources visible to the shader, the following
2661 QRhiShaderResourceBindings could be created and then passed to
2662 QRhiGraphicsPipeline::setShaderResourceBindings():
2663
2664 \badcode
2665 srb = rhi->newShaderResourceBindings();
2666 srb->setBindings({
2667 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf),
2668 QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler)
2669 });
2670 srb->build();
2671 ...
2672 ps = rhi->newGraphicsPipeline();
2673 ...
2674 ps->setShaderResourceBindings(srb);
2675 ps->build();
2676 ...
2677 cb->setGraphicsPipeline(ps);
2678 cb->setShaderResources(); // binds srb
2679 \endcode
2680
2681 This assumes that \c ubuf is a QRhiBuffer, \c texture is a QRhiTexture,
2682 while \a sampler is a QRhiSampler. The example also assumes that the
2683 uniform block is present in the vertex shader as well so the same buffer is
2684 made visible to the vertex stage too.
2685
2686 \section3 Advanced usage
2687
2688 Building on the above example, let's assume that a pass now needs to use
2689 the exact same pipeline and shaders with a different texture. Creating a
2690 whole separate QRhiGraphicsPipeline just for this would be an overkill.
2691 This is why QRhiCommandBuffer::setShaderResources() allows specifying a \a
2692 srb argument. As long as the layouts (so the number of bindings and the
2693 binding points) match between two QRhiShaderResourceBindings, they can both
2694 be used with the same pipeline, assuming the pipeline was built with one of
2695 them in the first place.
2696
2697 \badcode
2698 srb2 = rhi->newShaderResourceBindings();
2699 ...
2700 cb->setGraphicsPipeline(ps);
2701 cb->setShaderResources(srb2); // binds srb2
2702 \endcode
2703 */
2704
2705/*!
2706 \internal
2707 */
2708QRhiShaderResourceBindings::QRhiShaderResourceBindings(QRhiImplementation *rhi)
2709 : QRhiResource(rhi)
2710{
2711}
2712
2713/*!
2714 \return the resource type.
2715 */
2716QRhiResource::Type QRhiShaderResourceBindings::resourceType() const
2717{
2718 return ShaderResourceBindings;
2719}
2720
2721/*!
2722 \return \c true if the layout is compatible with \a other. The layout does
2723 not include the actual resource (such as, buffer or texture) and related
2724 parameters (such as, offset or size). It does include the binding point,
2725 pipeline stage, and resource type, however. The number and order of the
2726 bindings must also match in order to be compatible.
2727
2728 When there is a QRhiGraphicsPipeline created with this
2729 QRhiShaderResourceBindings, and the function returns \c true, \a other can
2730 then safely be passed to QRhiCommandBuffer::setShaderResources(), and so
2731 be used with the pipeline in place of this QRhiShaderResourceBindings.
2732
2733 This function can be called before build() as well. The bindings must
2734 already be set via setBindings() however.
2735 */
2736bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBindings *other) const
2737{
2738 const int count = m_bindings.count();
2739 if (count != other->m_bindings.count())
2740 return false;
2741
2742 for (int i = 0; i < count; ++i) {
2743 if (!m_bindings[i].isLayoutCompatible(other: other->m_bindings.at(idx: i)))
2744 return false;
2745 }
2746
2747 return true;
2748}
2749
2750/*!
2751 \class QRhiShaderResourceBinding
2752 \internal
2753 \inmodule QtGui
2754 \brief Describes the shader resource for a single binding point.
2755
2756 A QRhiShaderResourceBinding cannot be constructed directly. Instead, use
2757 the static functions uniformBuffer(), sampledTexture() to get an instance.
2758 */
2759
2760/*!
2761 \enum QRhiShaderResourceBinding::Type
2762 Specifies type of the shader resource bound to a binding point
2763
2764 \value UniformBuffer Uniform buffer
2765
2766 \value SampledTexture Combined image sampler
2767
2768 \value ImageLoad Image load (with GLSL this maps to doing imageLoad() on a
2769 single level - and either one or all layers - of a texture exposed to the
2770 shader as an image object)
2771
2772 \value ImageStore Image store (with GLSL this maps to doing imageStore() or
2773 imageAtomic*() on a single level - and either one or all layers - of a
2774 texture exposed to the shader as an image object)
2775
2776 \value ImageLoadStore Image load and store
2777
2778 \value BufferLoad Storage buffer store (with GLSL this maps to reading from
2779 a shader storage buffer)
2780
2781 \value BufferStore Storage buffer store (with GLSL this maps to writing to
2782 a shader storage buffer)
2783
2784 \value BufferLoadStore Storage buffer load and store
2785 */
2786
2787/*!
2788 \enum QRhiShaderResourceBinding::StageFlag
2789 Flag values to indicate which stages the shader resource is visible in
2790
2791 \value VertexStage Vertex stage
2792 \value FragmentStage Fragment (pixel) stage
2793 \value ComputeStage Compute stage
2794 */
2795
2796/*!
2797 \internal
2798 */
2799QRhiShaderResourceBinding::QRhiShaderResourceBinding()
2800{
2801 // Zero out everything, including possible padding, because will use
2802 // qHashBits on it.
2803 memset(s: &d.u, c: 0, n: sizeof(d.u));
2804}
2805
2806/*!
2807 \return \c true if the layout is compatible with \a other. The layout does not
2808 include the actual resource (such as, buffer or texture) and related
2809 parameters (such as, offset or size).
2810
2811 For example, \c a and \c b below are not equal, but are compatible layout-wise:
2812
2813 \badcode
2814 auto a = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buffer);
2815 auto b = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, someOtherBuffer, 256);
2816 \endcode
2817 */
2818bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBinding &other) const
2819{
2820 return d.binding == other.d.binding && d.stage == other.d.stage && d.type == other.d.type;
2821}
2822
2823/*!
2824 \return a shader resource binding for the given binding number, pipeline
2825 stages, and buffer specified by \a binding, \a stage, and \a buf.
2826
2827 \note \a buf must have been created with QRhiBuffer::UniformBuffer.
2828 */
2829QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
2830 int binding, StageFlags stage, QRhiBuffer *buf)
2831{
2832 QRhiShaderResourceBinding b;
2833 b.d.binding = binding;
2834 b.d.stage = stage;
2835 b.d.type = UniformBuffer;
2836 b.d.u.ubuf.buf = buf;
2837 b.d.u.ubuf.offset = 0;
2838 b.d.u.ubuf.maybeSize = 0; // entire buffer
2839 b.d.u.ubuf.hasDynamicOffset = false;
2840 return b;
2841}
2842
2843/*!
2844 \return a shader resource binding for the given binding number, pipeline
2845 stages, and buffer specified by \a binding, \a stage, and \a buf. This
2846 overload binds a region only, as specified by \a offset and \a size.
2847
2848 \note It is up to the user to ensure the offset is aligned to
2849 QRhi::ubufAlignment().
2850
2851 \note \a size must be greater than 0.
2852
2853 \note \a buf must have been created with QRhiBuffer::UniformBuffer.
2854 */
2855QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
2856 int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
2857{
2858 Q_ASSERT(size > 0);
2859 QRhiShaderResourceBinding b = uniformBuffer(binding, stage, buf);
2860 b.d.u.ubuf.offset = offset;
2861 b.d.u.ubuf.maybeSize = size;
2862 return b;
2863}
2864
2865/*!
2866 \return a shader resource binding for the given binding number, pipeline
2867 stages, and buffer specified by \a binding, \a stage, and \a buf. The
2868 uniform buffer is assumed to have dynamic offset. The dynamic offset can be
2869 specified in QRhiCommandBuffer::setShaderResources(), thus allowing using
2870 varying offset values without creating new bindings for the buffer. The
2871 size of the bound region is specified by \a size. Like with non-dynamic
2872 offsets, \c{offset + size} cannot exceed the size of \a buf.
2873
2874 \note \a buf must have been created with QRhiBuffer::UniformBuffer.
2875 */
2876QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(
2877 int binding, StageFlags stage, QRhiBuffer *buf, int size)
2878{
2879 QRhiShaderResourceBinding b = uniformBuffer(binding, stage, buf, offset: 0, size);
2880 b.d.u.ubuf.hasDynamicOffset = true;
2881 return b;
2882}
2883
2884/*!
2885 \return a shader resource binding for the given binding number, pipeline
2886 stages, texture, and sampler specified by \a binding, \a stage, \a tex,
2887 \a sampler.
2888
2889 \note This function is equivalent to calling sampledTextures() with a
2890 \c count of 1.
2891
2892 \sa sampledTextures()
2893 */
2894QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
2895 int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
2896{
2897 const TextureAndSampler texSampler = { .tex: tex, .sampler: sampler };
2898 return sampledTextures(binding, stage, count: 1, texSamplers: &texSampler);
2899}
2900
2901/*!
2902 \return a shader resource binding for the given binding number, pipeline
2903 stages, and the array of texture-sampler pairs specified by \a binding, \a
2904 stage, \a count, and \a texSamplers.
2905
2906 \note \a count must be at least 1, and not larger than 16.
2907
2908 \note When \a count is 1, this function is equivalent to sampledTexture().
2909
2910 This function is relevant when arrays of combined image samplers are
2911 involved. For example, in GLSL \c{layout(binding = 5) uniform sampler2D
2912 shadowMaps[8];} declares an array of combined image samplers. The
2913 application is then expected provide a QRhiShaderResourceBinding for
2914 binding point 5, set up by calling this function with \a count set to 8 and
2915 a valid texture and sampler for each element of the array.
2916
2917 \warning All elements of the array must be specified. With the above
2918 example, the only valid, portable approach is calling this function with a
2919 \a count of 8. Additionally, all QRhiTexture and QRhiSampler instances must
2920 be valid, meaning nullptr is not an accepted value. This is due to some of
2921 the underlying APIs, such as, Vulkan, that require a valid image and
2922 sampler object for each element in descriptor arrays. Applications are
2923 advised to provide "dummy" samplers and textures if some array elements are
2924 not relevant (due to not being accessed in the shader).
2925
2926 \sa sampledTexture()
2927 */
2928QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTextures(
2929 int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers)
2930{
2931 Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
2932 QRhiShaderResourceBinding b;
2933 b.d.binding = binding;
2934 b.d.stage = stage;
2935 b.d.type = SampledTexture;
2936 b.d.u.stex.count = count;
2937 for (int i = 0; i < count; ++i)
2938 b.d.u.stex.texSamplers[i] = texSamplers[i];
2939 return b;
2940}
2941
2942/*!
2943 \return a shader resource binding for a read-only storage image with the
2944 given \a binding number and pipeline \a stage. The image load operations
2945 will have access to all layers of the specified \a level. (so if the texture
2946 is a cubemap, the shader must use imageCube instead of image2D)
2947
2948 \note \a tex must have been created with QRhiTexture::UsedWithLoadStore.
2949 */
2950QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoad(
2951 int binding, StageFlags stage, QRhiTexture *tex, int level)
2952{
2953 QRhiShaderResourceBinding b;
2954 b.d.binding = binding;
2955 b.d.stage = stage;
2956 b.d.type = ImageLoad;
2957 b.d.u.simage.tex = tex;
2958 b.d.u.simage.level = level;
2959 return b;
2960}
2961
2962/*!
2963 \return a shader resource binding for a write-only storage image with the
2964 given \a binding number and pipeline \a stage. The image store operations
2965 will have access to all layers of the specified \a level. (so if the texture
2966 is a cubemap, the shader must use imageCube instead of image2D)
2967
2968 \note \a tex must have been created with QRhiTexture::UsedWithLoadStore.
2969 */
2970QRhiShaderResourceBinding QRhiShaderResourceBinding::imageStore(
2971 int binding, StageFlags stage, QRhiTexture *tex, int level)
2972{
2973 QRhiShaderResourceBinding b = imageLoad(binding, stage, tex, level);
2974 b.d.type = ImageStore;
2975 return b;
2976}
2977
2978/*!
2979 \return a shader resource binding for a read/write storage image with the
2980 given \a binding number and pipeline \a stage. The image load/store operations
2981 will have access to all layers of the specified \a level. (so if the texture
2982 is a cubemap, the shader must use imageCube instead of image2D)
2983
2984 \note \a tex must have been created with QRhiTexture::UsedWithLoadStore.
2985 */
2986QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoadStore(
2987 int binding, StageFlags stage, QRhiTexture *tex, int level)
2988{
2989 QRhiShaderResourceBinding b = imageLoad(binding, stage, tex, level);
2990 b.d.type = ImageLoadStore;
2991 return b;
2992}
2993
2994/*!
2995 \return a shader resource binding for a read-only storage buffer with the
2996 given \a binding number and pipeline \a stage.
2997
2998 \note \a buf must have been created with QRhiBuffer::StorageBuffer.
2999 */
3000QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
3001 int binding, StageFlags stage, QRhiBuffer *buf)
3002{
3003 QRhiShaderResourceBinding b;
3004 b.d.binding = binding;
3005 b.d.stage = stage;
3006 b.d.type = BufferLoad;
3007 b.d.u.sbuf.buf = buf;
3008 b.d.u.sbuf.offset = 0;
3009 b.d.u.sbuf.maybeSize = 0; // entire buffer
3010 return b;
3011}
3012
3013/*!
3014 \return a shader resource binding for a read-only storage buffer with the
3015 given \a binding number and pipeline \a stage. This overload binds a region
3016 only, as specified by \a offset and \a size.
3017
3018 \note \a buf must have been created with QRhiBuffer::StorageBuffer.
3019 */
3020QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
3021 int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
3022{
3023 Q_ASSERT(size > 0);
3024 QRhiShaderResourceBinding b = bufferLoad(binding, stage, buf);
3025 b.d.u.sbuf.offset = offset;
3026 b.d.u.sbuf.maybeSize = size;
3027 return b;
3028}
3029
3030/*!
3031 \return a shader resource binding for a write-only storage buffer with the
3032 given \a binding number and pipeline \a stage.
3033
3034 \note \a buf must have been created with QRhiBuffer::StorageBuffer.
3035 */
3036QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
3037 int binding, StageFlags stage, QRhiBuffer *buf)
3038{
3039 QRhiShaderResourceBinding b = bufferLoad(binding, stage, buf);
3040 b.d.type = BufferStore;
3041 return b;
3042}
3043
3044/*!
3045 \return a shader resource binding for a write-only storage buffer with the
3046 given \a binding number and pipeline \a stage. This overload binds a region
3047 only, as specified by \a offset and \a size.
3048
3049 \note \a buf must have been created with QRhiBuffer::StorageBuffer.
3050 */
3051QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
3052 int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
3053{
3054 Q_ASSERT(size > 0);
3055 QRhiShaderResourceBinding b = bufferStore(binding, stage, buf);
3056 b.d.u.sbuf.offset = offset;
3057 b.d.u.sbuf.maybeSize = size;
3058 return b;
3059}
3060
3061/*!
3062 \return a shader resource binding for a read-write storage buffer with the
3063 given \a binding number and pipeline \a stage.
3064
3065 \note \a buf must have been created with QRhiBuffer::StorageBuffer.
3066 */
3067QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
3068 int binding, StageFlags stage, QRhiBuffer *buf)
3069{
3070 QRhiShaderResourceBinding b = bufferLoad(binding, stage, buf);
3071 b.d.type = BufferLoadStore;
3072 return b;
3073}
3074
3075/*!
3076 \return a shader resource binding for a read-write storage buffer with the
3077 given \a binding number and pipeline \a stage. This overload binds a region
3078 only, as specified by \a offset and \a size.
3079
3080 \note \a buf must have been created with QRhiBuffer::StorageBuffer.
3081 */
3082QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
3083 int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
3084{
3085 Q_ASSERT(size > 0);
3086 QRhiShaderResourceBinding b = bufferLoadStore(binding, stage, buf);
3087 b.d.u.sbuf.offset = offset;
3088 b.d.u.sbuf.maybeSize = size;
3089 return b;
3090}
3091
3092/*!
3093 \return \c true if the contents of the two QRhiShaderResourceBinding
3094 objects \a a and \a b are equal. This includes the resources (buffer,
3095 texture) and related parameters (offset, size) as well. To only compare
3096 layouts (binding point, pipeline stage, resource type), use
3097 \l{QRhiShaderResourceBinding::isLayoutCompatible()}{isLayoutCompatible()}
3098 instead.
3099
3100 \relates QRhiShaderResourceBinding
3101 */
3102bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) Q_DECL_NOTHROW
3103{
3104 const QRhiShaderResourceBinding::Data *da = a.data();
3105 const QRhiShaderResourceBinding::Data *db = b.data();
3106
3107 if (da == db)
3108 return true;
3109
3110
3111 if (da->binding != db->binding
3112 || da->stage != db->stage
3113 || da->type != db->type)
3114 {
3115 return false;
3116 }
3117
3118 switch (da->type) {
3119 case QRhiShaderResourceBinding::UniformBuffer:
3120 if (da->u.ubuf.buf != db->u.ubuf.buf
3121 || da->u.ubuf.offset != db->u.ubuf.offset
3122 || da->u.ubuf.maybeSize != db->u.ubuf.maybeSize)
3123 {
3124 return false;
3125 }
3126 break;
3127 case QRhiShaderResourceBinding::SampledTexture:
3128 if (da->u.stex.count != db->u.stex.count)
3129 return false;
3130 for (int i = 0; i < da->u.stex.count; ++i) {
3131 if (da->u.stex.texSamplers[i].tex != db->u.stex.texSamplers[i].tex
3132 || da->u.stex.texSamplers[i].sampler != db->u.stex.texSamplers[i].sampler)
3133 {
3134 return false;
3135 }
3136 }
3137 break;
3138 case QRhiShaderResourceBinding::ImageLoad:
3139 Q_FALLTHROUGH();
3140 case QRhiShaderResourceBinding::ImageStore:
3141 Q_FALLTHROUGH();
3142 case QRhiShaderResourceBinding::ImageLoadStore:
3143 if (da->u.simage.tex != db->u.simage.tex
3144 || da->u.simage.level != db->u.simage.level)
3145 {
3146 return false;
3147 }
3148 break;
3149 case QRhiShaderResourceBinding::BufferLoad:
3150 Q_FALLTHROUGH();
3151 case QRhiShaderResourceBinding::BufferStore:
3152 Q_FALLTHROUGH();
3153 case QRhiShaderResourceBinding::BufferLoadStore:
3154 if (da->u.sbuf.buf != db->u.sbuf.buf
3155 || da->u.sbuf.offset != db->u.sbuf.offset
3156 || da->u.sbuf.maybeSize != db->u.sbuf.maybeSize)
3157 {
3158 return false;
3159 }
3160 break;
3161 default:
3162 Q_UNREACHABLE();
3163 return false;
3164 }
3165
3166 return true;
3167}
3168
3169/*!
3170 \return \c false if all the bindings in the two QRhiShaderResourceBinding
3171 objects \a a and \a b are equal; otherwise returns \c true.
3172
3173 \relates QRhiShaderResourceBinding
3174 */
3175bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) Q_DECL_NOTHROW
3176{
3177 return !(a == b);
3178}
3179
3180/*!
3181 \return the hash value for \a b, using \a seed to seed the calculation.
3182
3183 \relates QRhiShaderResourceBinding
3184 */
3185uint qHash(const QRhiShaderResourceBinding &b, uint seed) Q_DECL_NOTHROW
3186{
3187 const QRhiShaderResourceBinding::Data *d = b.data();
3188 return seed + uint(d->binding) + 10 * uint(d->stage) + 100 * uint(d->type)
3189 + qHashBits(p: &d->u, size: sizeof(d->u), seed);
3190}
3191
3192#ifndef QT_NO_DEBUG_STREAM
3193QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
3194{
3195 QDebugStateSaver saver(dbg);
3196 const QRhiShaderResourceBinding::Data *d = b.data();
3197 dbg.nospace() << "QRhiShaderResourceBinding("
3198 << "binding=" << d->binding
3199 << " stage=" << d->stage
3200 << " type=" << d->type;
3201 switch (d->type) {
3202 case QRhiShaderResourceBinding::UniformBuffer:
3203 dbg.nospace() << " UniformBuffer("
3204 << "buffer=" << d->u.ubuf.buf
3205 << " offset=" << d->u.ubuf.offset
3206 << " maybeSize=" << d->u.ubuf.maybeSize
3207 << ')';
3208 break;
3209 case QRhiShaderResourceBinding::SampledTexture:
3210 dbg.nospace() << " SampledTextures("
3211 << "count=" << d->u.stex.count;
3212 for (int i = 0; i < d->u.stex.count; ++i) {
3213 dbg.nospace() << " texture=" << d->u.stex.texSamplers[i].tex
3214 << " sampler=" << d->u.stex.texSamplers[i].sampler;
3215 }
3216 dbg.nospace() << ')';
3217 break;
3218 case QRhiShaderResourceBinding::ImageLoad:
3219 dbg.nospace() << " ImageLoad("
3220 << "texture=" << d->u.simage.tex
3221 << " level=" << d->u.simage.level
3222 << ')';
3223 break;
3224 case QRhiShaderResourceBinding::ImageStore:
3225 dbg.nospace() << " ImageStore("
3226 << "texture=" << d->u.simage.tex
3227 << " level=" << d->u.simage.level
3228 << ')';
3229 break;
3230 case QRhiShaderResourceBinding::ImageLoadStore:
3231 dbg.nospace() << " ImageLoadStore("
3232 << "texture=" << d->u.simage.tex
3233 << " level=" << d->u.simage.level
3234 << ')';
3235 break;
3236 case QRhiShaderResourceBinding::BufferLoad:
3237 dbg.nospace() << " BufferLoad("
3238 << "buffer=" << d->u.sbuf.buf
3239 << " offset=" << d->u.sbuf.offset
3240 << " maybeSize=" << d->u.sbuf.maybeSize
3241 << ')';
3242 break;
3243 case QRhiShaderResourceBinding::BufferStore:
3244 dbg.nospace() << " BufferStore("
3245 << "buffer=" << d->u.sbuf.buf
3246 << " offset=" << d->u.sbuf.offset
3247 << " maybeSize=" << d->u.sbuf.maybeSize
3248 << ')';
3249 break;
3250 case QRhiShaderResourceBinding::BufferLoadStore:
3251 dbg.nospace() << " BufferLoadStore("
3252 << "buffer=" << d->u.sbuf.buf
3253 << " offset=" << d->u.sbuf.offset
3254 << " maybeSize=" << d->u.sbuf.maybeSize
3255 << ')';
3256 break;
3257 default:
3258 Q_UNREACHABLE();
3259 break;
3260 }
3261 dbg.nospace() << ')';
3262 return dbg;
3263}
3264#endif
3265
3266#ifndef QT_NO_DEBUG_STREAM
3267QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
3268{
3269 QDebugStateSaver saver(dbg);
3270 dbg.nospace() << "QRhiShaderResourceBindings("
3271 << srb.m_bindings
3272 << ')';
3273 return dbg;
3274}
3275#endif
3276
3277/*!
3278 \class QRhiGraphicsPipeline
3279 \internal
3280 \inmodule QtGui
3281 \brief Graphics pipeline state resource.
3282
3283 \note Setting the shader stages is mandatory. There must be at least one
3284 stage, and there must be a vertex stage.
3285
3286 \note Setting the shader resource bindings is mandatory. The referenced
3287 QRhiShaderResourceBindings must already be built by the time build() is
3288 called. Associating with a QRhiShaderResourceBindings that has no bindings
3289 is also valid, as long as no shader in any stage expects any resources.
3290
3291 \note Setting the render pass descriptor is mandatory. To obtain a
3292 QRhiRenderPassDescriptor that can be passed to setRenderPassDescriptor(),
3293 use either QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() or
3294 QRhiSwapChain::newCompatibleRenderPassDescriptor().
3295
3296 \note Setting the vertex input layout is mandatory.
3297
3298 \note sampleCount() defaults to 1 and must match the sample count of the
3299 render target's color and depth stencil attachments.
3300
3301 \note The depth test, depth write, and stencil test are disabled by
3302 default.
3303
3304 \note stencilReadMask() and stencilWriteMask() apply to both faces. They
3305 both default to 0xFF.
3306 */
3307
3308/*!
3309 \fn void QRhiGraphicsPipeline::setTargetBlends(const QVector<TargetBlend> &blends)
3310
3311 Sets the blend specification for color attachments. Each element in \a
3312 blends corresponds to a color attachment of the render target.
3313
3314 By default no blends are set, which is a shortcut to disabling blending and
3315 enabling color write for all four channels.
3316 */
3317
3318/*!
3319 \enum QRhiGraphicsPipeline::Flag
3320
3321 Flag values for describing the dynamic state of the pipeline. The viewport is always dynamic.
3322
3323 \value UsesBlendConstants Indicates that a blend color constant will be set
3324 via QRhiCommandBuffer::setBlendConstants()
3325
3326 \value UsesStencilRef Indicates that a stencil reference value will be set
3327 via QRhiCommandBuffer::setStencilRef()
3328
3329 \value UsesScissor Indicates that a scissor rectangle will be set via
3330 QRhiCommandBuffer::setScissor()
3331 */
3332
3333/*!
3334 \enum QRhiGraphicsPipeline::Topology
3335 Specifies the primitive topology
3336
3337 \value Triangles (default)
3338 \value TriangleStrip
3339 \value TriangleFan (only available if QRhi::TriangleFanTopology is supported)
3340 \value Lines
3341 \value LineStrip
3342 \value Points
3343 */
3344
3345/*!
3346 \enum QRhiGraphicsPipeline::CullMode
3347 Specifies the culling mode
3348
3349 \value None No culling (default)
3350 \value Front Cull front faces
3351 \value Back Cull back faces
3352 */
3353
3354/*!
3355 \enum QRhiGraphicsPipeline::FrontFace
3356 Specifies the front face winding order
3357
3358 \value CCW Counter clockwise (default)
3359 \value CW Clockwise
3360 */
3361
3362/*!
3363 \enum QRhiGraphicsPipeline::ColorMaskComponent
3364 Flag values for specifying the color write mask
3365
3366 \value R
3367 \value G
3368 \value B
3369 \value A
3370 */
3371
3372/*!
3373 \enum QRhiGraphicsPipeline::BlendFactor
3374 Specifies the blend factor
3375
3376 \value Zero
3377 \value One
3378 \value SrcColor
3379 \value OneMinusSrcColor
3380 \value DstColor
3381 \value OneMinusDstColor
3382 \value SrcAlpha
3383 \value OneMinusSrcAlpha
3384 \value DstAlpha
3385 \value OneMinusDstAlpha
3386 \value ConstantColor
3387 \value OneMinusConstantColor
3388 \value ConstantAlpha
3389 \value OneMinusConstantAlpha
3390 \value SrcAlphaSaturate
3391 \value Src1Color
3392 \value OneMinusSrc1Color
3393 \value Src1Alpha
3394 \value OneMinusSrc1Alpha
3395 */
3396
3397/*!
3398 \enum QRhiGraphicsPipeline::BlendOp
3399 Specifies the blend operation
3400
3401 \value Add
3402 \value Subtract
3403 \value ReverseSubtract
3404 \value Min
3405 \value Max
3406 */
3407
3408/*!
3409 \enum QRhiGraphicsPipeline::CompareOp
3410 Specifies the depth or stencil comparison function
3411
3412 \value Never
3413 \value Less (default for depth)
3414 \value Equal
3415 \value LessOrEqual
3416 \value Greater
3417 \value NotEqual
3418 \value GreaterOrEqual
3419 \value Always (default for stencil)
3420 */
3421
3422/*!
3423 \enum QRhiGraphicsPipeline::StencilOp
3424 Specifies the stencil operation
3425
3426 \value StencilZero
3427 \value Keep (default)
3428 \value Replace
3429 \value IncrementAndClamp
3430 \value DecrementAndClamp
3431 \value Invert
3432 \value IncrementAndWrap
3433 \value DecrementAndWrap
3434 */
3435
3436/*!
3437 \class QRhiGraphicsPipeline::TargetBlend
3438 \internal
3439 \inmodule QtGui
3440 \brief Describes the blend state for one color attachment.
3441
3442 Defaults to color write enabled, blending disabled. The blend values are
3443 set up for pre-multiplied alpha (One, OneMinusSrcAlpha, One,
3444 OneMinusSrcAlpha) by default.
3445 */
3446
3447/*!
3448 \class QRhiGraphicsPipeline::StencilOpState
3449 \internal
3450 \inmodule QtGui
3451 \brief Describes the stencil operation state.
3452 */
3453
3454/*!
3455 \internal
3456 */
3457QRhiGraphicsPipeline::QRhiGraphicsPipeline(QRhiImplementation *rhi)
3458 : QRhiResource(rhi)
3459{
3460}
3461
3462/*!
3463 \return the resource type.
3464 */
3465QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
3466{
3467 return GraphicsPipeline;
3468}
3469
3470/*!
3471 \fn bool QRhiGraphicsPipeline::build()
3472
3473 Creates the corresponding native graphics resources. If there are already
3474 resources present due to an earlier build() with no corresponding
3475 release(), then release() is called implicitly first.
3476
3477 \return \c true when successful, \c false when a graphics operation failed.
3478 Regardless of the return value, calling release() is always safe.
3479 */
3480
3481/*!
3482 \fn void QRhiGraphicsPipeline::setDepthTest(bool enable)
3483
3484 Enables or disables depth testing. Both depth test and the writing out of
3485 depth data are disabled by default.
3486
3487 \sa setDepthWrite()
3488 */
3489
3490/*!
3491 \fn void QRhiGraphicsPipeline::setDepthWrite(bool enable)
3492
3493 Controls the writing out of depth data into the depth buffer. By default
3494 this is disabled. Depth write is typically enabled together with the depth
3495 test.
3496
3497 \note Enabling depth write without having depth testing enabled may not
3498 lead to the desired result, and should be avoided.
3499
3500 \sa setDepthTest()
3501 */
3502
3503/*!
3504 \class QRhiSwapChain
3505 \internal
3506 \inmodule QtGui
3507 \brief Swapchain resource.
3508
3509 A swapchain enables presenting rendering results to a surface. A swapchain
3510 is typically backed by a set of color buffers. Of these, one is displayed
3511 at a time.
3512
3513 Below is a typical pattern for creating and managing a swapchain and some
3514 associated resources in order to render onto a QWindow:
3515
3516 \badcode
3517 void init()
3518 {
3519 sc = rhi->newSwapChain();
3520 ds = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
3521 QSize(), // no need to set the size here due to UsedWithSwapChainOnly
3522 1,
3523 QRhiRenderBuffer::UsedWithSwapChainOnly);
3524 sc->setWindow(window);
3525 sc->setDepthStencil(ds);
3526 rp = sc->newCompatibleRenderPassDescriptor();
3527 sc->setRenderPassDescriptor(rp);
3528 resizeSwapChain();
3529 }
3530
3531 void resizeSwapChain()
3532 {
3533 hasSwapChain = sc->buildOrResize();
3534 }
3535
3536 void render()
3537 {
3538 if (!hasSwapChain || notExposed)
3539 return;
3540
3541 if (sc->currentPixelSize() != sc->surfacePixelSize() || newlyExposed) {
3542 resizeSwapChain();
3543 if (!hasSwapChain)
3544 return;
3545 newlyExposed = false;
3546 }
3547
3548 rhi->beginFrame(sc);
3549 // ...
3550 rhi->endFrame(sc);
3551 }
3552 \endcode
3553
3554 Avoid relying on QWindow resize events to resize swapchains, especially
3555 considering that surface sizes may not always fully match the QWindow
3556 reported dimensions. The safe, cross-platform approach is to do the check
3557 via surfacePixelSize() whenever starting a new frame.
3558
3559 Releasing the swapchain must happen while the QWindow and the underlying
3560 native window is fully up and running. Building on the previous example:
3561
3562 \badcode
3563 void releaseSwapChain()
3564 {
3565 if (hasSwapChain) {
3566 sc->release();
3567 hasSwapChain = false;
3568 }
3569 }
3570
3571 // assuming Window is our QWindow subclass
3572 bool Window::event(QEvent *e)
3573 {
3574 switch (e->type()) {
3575 case QEvent::UpdateRequest: // for QWindow::requestUpdate()
3576 render();
3577 break;
3578 case QEvent::PlatformSurface:
3579 if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
3580 releaseSwapChain();
3581 break;
3582 default:
3583 break;
3584 }
3585 return QWindow::event(e);
3586 }
3587 \endcode
3588
3589 Initializing the swapchain and starting to render the first frame cannot
3590 start at any time. The safe, cross-platform approach is to rely on expose
3591 events. QExposeEvent is a loosely specified event that is sent whenever a
3592 window gets mapped, obscured, and resized, depending on the platform.
3593
3594 \badcode
3595 void Window::exposeEvent(QExposeEvent *)
3596 {
3597 // initialize and start rendering when the window becomes usable for graphics purposes
3598 if (isExposed() && !running) {
3599 running = true;
3600 init();
3601 }
3602
3603 // stop pushing frames when not exposed or size becomes 0
3604 if ((!isExposed() || (hasSwapChain && sc->surfacePixelSize().isEmpty())) && running)
3605 notExposed = true;
3606
3607 // continue when exposed again and the surface has a valid size
3608 if (isExposed() && running && notExposed && !sc->surfacePixelSize().isEmpty()) {
3609 notExposed = false;
3610 newlyExposed = true;
3611 }
3612
3613 if (isExposed() && !sc->surfacePixelSize().isEmpty())
3614 render();
3615 }
3616 \endcode
3617
3618 Once the rendering has started, a simple way to request a new frame is
3619 QWindow::requestUpdate(). While on some platforms this is merely a small
3620 timer, on others it has a specific implementation: for instance on macOS or
3621 iOS it may be backed by
3622 \l{https://developer.apple.com/documentation/corevideo/cvdisplaylink?language=objc}{CVDisplayLink}.
3623 The example above is already prepared for update requests by handling
3624 QEvent::UpdateRequest.
3625
3626 While acting as a QRhiRenderTarget, QRhiSwapChain also manages a
3627 QRhiCommandBuffer. Calling QRhi::endFrame() submits the recorded commands
3628 and also enqueues a \c present request. The default behavior is to do this
3629 with a swap interval of 1, meaning synchronizing to the display's vertical
3630 refresh is enabled. Thus the rendering thread calling beginFrame() and
3631 endFrame() will get throttled to vsync. On some backends this can be
3632 disabled by passing QRhiSwapChain:NoVSync in flags().
3633
3634 Multisampling (MSAA) is handled transparently to the applications when
3635 requested via setSampleCount(). Where applicable, QRhiSwapChain will take
3636 care of creating additional color buffers and issuing a multisample resolve
3637 command at the end of a frame. For OpenGL, it is necessary to request the
3638 appropriate sample count also via QSurfaceFormat, by calling
3639 QSurfaceFormat::setDefaultFormat() before initializing the QRhi.
3640 */
3641
3642/*!
3643 \enum QRhiSwapChain::Flag
3644 Flag values to describe swapchain properties
3645
3646 \value SurfaceHasPreMulAlpha Indicates that the target surface has
3647 transparency with premultiplied alpha. For example, this is what Qt Quick
3648 uses when the alpha channel is enabled on the target QWindow, because the
3649 scenegraph rendrerer always outputs fragments with alpha multiplied into
3650 the red, green, and blue values. To ensure identical behavior across
3651 platforms, always set QSurfaceFormat::alphaBufferSize() to a non-zero value
3652 on the target QWindow whenever this flag is set on the swapchain.
3653
3654 \value SurfaceHasNonPreMulAlpha Indicates the target surface has
3655 transparency with non-premultiplied alpha. Be aware that this may not be
3656 supported on some systems, if the system compositor always expects content
3657 with premultiplied alpha. In that case the behavior with this flag set is
3658 expected to be equivalent to SurfaceHasPreMulAlpha.
3659
3660 \value sRGB Requests to pick an sRGB format for the swapchain and/or its
3661 render target views, where applicable. Note that this implies that sRGB
3662 framebuffer update and blending will get enabled for all content targeting
3663 this swapchain, and opting out is not possible. For OpenGL, set
3664 \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the QSurfaceFormat of
3665 the QWindow in addition.
3666
3667 \value UsedAsTransferSource Indicates the swapchain will be used as the
3668 source of a readback in QRhiResourceUpdateBatch::readBackTexture().
3669
3670 \value NoVSync Requests disabling waiting for vertical sync, also avoiding
3671 throttling the rendering thread. The behavior is backend specific and
3672 applicable only where it is possible to control this. Some may ignore the
3673 request altogether. For OpenGL, try instead setting the swap interval to 0
3674 on the QWindow via QSurfaceFormat::setSwapInterval().
3675
3676 \value MinimalBufferCount Requests creating the swapchain with the minimum
3677 number of buffers, which is in practice 2, unless the graphics
3678 implementation has a higher minimum number than that. Only applicable with
3679 backends where such control is available via the graphics API, for example,
3680 Vulkan. By default it is up to the backend to decide what number of buffers
3681 it requests (in practice this is almost always either 2 or 3), and it is
3682 not the applications' concern. However, on Vulkan for instance the backend
3683 will likely prefer the higher number (3), for example to avoid odd
3684 performance issues with some Vulkan implementations on mobile devices. It
3685 could be that on some platforms it can prove to be beneficial to force the
3686 lower buffer count (2), so this flag allows forcing that. Note that all
3687 this has no effect on the number of frames kept in flight, so the CPU
3688 (QRhi) will still prepare frames at most \c{N - 1} frames ahead of the GPU,
3689 even when the swapchain image buffer count larger than \c N. (\c{N} =
3690 QRhi::FramesInFlight and typically 2).
3691 */
3692
3693/*!
3694 \internal
3695 */
3696QRhiSwapChain::QRhiSwapChain(QRhiImplementation *rhi)
3697 : QRhiResource(rhi)
3698{
3699}
3700
3701/*!
3702 \return the resource type.
3703 */
3704QRhiResource::Type QRhiSwapChain::resourceType() const
3705{
3706 return SwapChain;
3707}
3708
3709/*!
3710 \fn QSize QRhiSwapChain::currentPixelSize() const
3711
3712 \return the size with which the swapchain was last successfully built. Use
3713 this to decide if buildOrResize() needs to be called again: if
3714 \c{currentPixelSize() != surfacePixelSize()} then the swapchain needs to be
3715 resized.
3716
3717 \note Typical rendering logic will call this function to get the output
3718 size when starting to prepare a new frame, and base dependent calculations
3719 (such as, the viewport) on the size returned from this function.
3720
3721 While in many cases the value is the same as \c{QWindow::size() *
3722 QWindow::devicePixelRatio()}, relying on the QWindow-reported size is not
3723 guaranteed to be correct on all platforms and graphics API implementations.
3724 Using this function is therefore strongly recommended whenever there is a
3725 need to identify the dimensions, in pixels, of the output layer or surface.
3726
3727 This also has the added benefit of avoiding potential data races when QRhi
3728 is used on a dedicated rendering thread, because the need to call QWindow
3729 functions, that may then access data updated on the main thread, is
3730 avoided.
3731
3732 \sa surfacePixelSize()
3733 */
3734
3735/*!
3736 \fn QSize QRhiSwapChain::surfacePixelSize()
3737
3738 \return The size of the window's associated surface or layer.
3739
3740 \warning Do not assume this is the same as \c{QWindow::size() *
3741 QWindow::devicePixelRatio()}. With some graphics APIs and windowing system
3742 interfaces (for example, Vulkan) there is a theoretical possibility for a
3743 surface to assume a size different from the associated window. To support
3744 these cases, rendering logic must always base size-derived calculations
3745 (such as, viewports) on the size reported from QRhiSwapChain, and never on
3746 the size queried from QWindow.
3747
3748 \note Can also be called before buildOrResize(), if at least window() is
3749 already set) This in combination with currentPixelSize() allows to detect
3750 when a swapchain needs to be resized. However, watch out for the fact that
3751 the size of the underlying native object (surface, layer, or similar) is
3752 "live", so whenever this function is called, it returns the latest value
3753 reported by the underlying implementation, without any atomicity guarantee.
3754 Therefore, using this function to determine pixel sizes for graphics
3755 resources that are used in a frame is strongly discouraged. Rely on
3756 currentPixelSize() instead which returns a size that is atomic and will not
3757 change between buildOrResize() invocations.
3758
3759 \note For depth-stencil buffers used in combination with the swapchain's
3760 color buffers, it is strongly recommended to rely on the automatic sizing
3761 and rebuilding behavior provided by the
3762 QRhiRenderBuffer:UsedWithSwapChainOnly flag. Avoid querying the surface
3763 size via this function just to get a size that can be passed to
3764 QRhiRenderBuffer::setPixelSize() as that would suffer from the lack of
3765 atomicity as described above.
3766
3767 \sa currentPixelSize()
3768 */
3769
3770/*!
3771 \fn QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer()
3772
3773 \return a command buffer on which rendering commands can be recorded. Only
3774 valid within a QRhi::beginFrame() - QRhi::endFrame() block where
3775 beginFrame() was called with this swapchain.
3776
3777 \note the value must not be cached and reused between frames
3778*/
3779
3780/*!
3781 \fn QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget()
3782
3783 \return a render target that can used with beginPass() in order to render
3784 the swapchain's current backbuffer. Only valid within a
3785 QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called
3786 with this swapchain.
3787
3788 \note the value must not be cached and reused between frames
3789 */
3790
3791/*!
3792 \fn bool QRhiSwapChain::buildOrResize()
3793
3794 Creates the swapchain if not already done and resizes the swapchain buffers
3795 to match the current size of the targeted surface. Call this whenever the
3796 size of the target surface is different than before.
3797
3798 \note call release() only when the swapchain needs to be released
3799 completely, typically upon
3800 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed. To perform resizing, just
3801 call buildOrResize().
3802
3803 \return \c true when successful, \c false when a graphics operation failed.
3804 Regardless of the return value, calling release() is always safe.
3805 */
3806
3807/*!
3808 \class QRhiComputePipeline
3809 \internal
3810 \inmodule QtGui
3811 \brief Compute pipeline state resource.
3812
3813 \note Setting the shader resource bindings is mandatory. The referenced
3814 QRhiShaderResourceBindings must already be built by the time build() is
3815 called.
3816
3817 \note Setting the shader is mandatory.
3818 */
3819
3820/*!
3821 \return the resource type.
3822 */
3823QRhiResource::Type QRhiComputePipeline::resourceType() const
3824{
3825 return ComputePipeline;
3826}
3827
3828/*!
3829 \internal
3830 */
3831QRhiComputePipeline::QRhiComputePipeline(QRhiImplementation *rhi)
3832 : QRhiResource(rhi)
3833{
3834}
3835
3836/*!
3837 \class QRhiCommandBuffer
3838 \internal
3839 \inmodule QtGui
3840 \brief Command buffer resource.
3841
3842 Not creatable by applications at the moment. The only ways to obtain a
3843 valid QRhiCommandBuffer are to get it from the targeted swapchain via
3844 QRhiSwapChain::currentFrameCommandBuffer(), or, in case of rendering
3845 completely offscreen, initializing one via QRhi::beginOffscreenFrame().
3846 */
3847
3848/*!
3849 \enum QRhiCommandBuffer::IndexFormat
3850 Specifies the index data type
3851
3852 \value IndexUInt16 Unsigned 16-bit (quint16)
3853 \value IndexUInt32 Unsigned 32-bit (quint32)
3854 */
3855
3856/*!
3857 \typedef QRhiCommandBuffer::DynamicOffset
3858
3859 Synonym for QPair<int, quint32>. The first entry is the binding, the second
3860 is the offset in the buffer.
3861*/
3862
3863/*!
3864 \typedef QRhiCommandBuffer::VertexInput
3865
3866 Synonym for QPair<QRhiBuffer *, quint32>. The second entry is an offset in
3867 the buffer specified by the first.
3868*/
3869
3870/*!
3871 \internal
3872 */
3873QRhiCommandBuffer::QRhiCommandBuffer(QRhiImplementation *rhi)
3874 : QRhiResource(rhi)
3875{
3876}
3877
3878/*!
3879 \return the resource type.
3880 */
3881QRhiResource::Type QRhiCommandBuffer::resourceType() const
3882{
3883 return CommandBuffer;
3884}
3885
3886#ifndef QT_NO_DEBUG
3887static const char *resourceTypeStr(QRhiResource *res)
3888{
3889 switch (res->resourceType()) {
3890 case QRhiResource::Buffer:
3891 return "Buffer";
3892 case QRhiResource::Texture:
3893 return "Texture";
3894 case QRhiResource::Sampler:
3895 return "Sampler";
3896 case QRhiResource::RenderBuffer:
3897 return "RenderBuffer";
3898 case QRhiResource::RenderPassDescriptor:
3899 return "RenderPassDescriptor";
3900 case QRhiResource::RenderTarget:
3901 return "RenderTarget";
3902 case QRhiResource::TextureRenderTarget:
3903 return "TextureRenderTarget";
3904 case QRhiResource::ShaderResourceBindings:
3905 return "ShaderResourceBindings";
3906 case QRhiResource::GraphicsPipeline:
3907 return "GraphicsPipeline";
3908 case QRhiResource::SwapChain:
3909 return "SwapChain";
3910 case QRhiResource::ComputePipeline:
3911 return "ComputePipeline";
3912 case QRhiResource::CommandBuffer:
3913 return "CommandBuffer";
3914 default:
3915 Q_UNREACHABLE();
3916 break;
3917 }
3918 return "";
3919}
3920#endif
3921
3922QRhiImplementation::~QRhiImplementation()
3923{
3924 qDeleteAll(c: resUpdPool);
3925
3926 // Be nice and show something about leaked stuff. Though we may not get
3927 // this far with some backends where the allocator or the api may check
3928 // and freak out for unfreed graphics objects in the derived dtor already.
3929#ifndef QT_NO_DEBUG
3930 if (!resources.isEmpty()) {
3931 qWarning(msg: "QRhi %p going down with %d unreleased resources that own native graphics objects. This is not nice.",
3932 q, resources.count());
3933 for (QRhiResource *res : qAsConst(t&: resources)) {
3934 qWarning(msg: " %s resource %p (%s)", resourceTypeStr(res), res, res->m_objectName.constData());
3935 res->m_rhi = nullptr;
3936 }
3937 }
3938#endif
3939}
3940
3941bool QRhiImplementation::isCompressedFormat(QRhiTexture::Format format) const
3942{
3943 return (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
3944 || (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
3945 || (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12);
3946}
3947
3948void QRhiImplementation::compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
3949 quint32 *bpl, quint32 *byteSize,
3950 QSize *blockDim) const
3951{
3952 int xdim = 4;
3953 int ydim = 4;
3954 quint32 blockSize = 0;
3955
3956 switch (format) {
3957 case QRhiTexture::BC1:
3958 blockSize = 8;
3959 break;
3960 case QRhiTexture::BC2:
3961 blockSize = 16;
3962 break;
3963 case QRhiTexture::BC3:
3964 blockSize = 16;
3965 break;
3966 case QRhiTexture::BC4:
3967 blockSize = 8;
3968 break;
3969 case QRhiTexture::BC5:
3970 blockSize = 16;
3971 break;
3972 case QRhiTexture::BC6H:
3973 blockSize = 16;
3974 break;
3975 case QRhiTexture::BC7:
3976 blockSize = 16;
3977 break;
3978
3979 case QRhiTexture::ETC2_RGB8:
3980 blockSize = 8;
3981 break;
3982 case QRhiTexture::ETC2_RGB8A1:
3983 blockSize = 8;
3984 break;
3985 case QRhiTexture::ETC2_RGBA8:
3986 blockSize = 16;
3987 break;
3988
3989 case QRhiTexture::ASTC_4x4:
3990 blockSize = 16;
3991 break;
3992 case QRhiTexture::ASTC_5x4:
3993 blockSize = 16;
3994 xdim = 5;
3995 break;
3996 case QRhiTexture::ASTC_5x5:
3997 blockSize = 16;
3998 xdim = ydim = 5;
3999 break;
4000 case QRhiTexture::ASTC_6x5:
4001 blockSize = 16;
4002 xdim = 6;
4003 ydim = 5;
4004 break;
4005 case QRhiTexture::ASTC_6x6:
4006 blockSize = 16;
4007 xdim = ydim = 6;
4008 break;
4009 case QRhiTexture::ASTC_8x5:
4010 blockSize = 16;
4011 xdim = 8;
4012 ydim = 5;
4013 break;
4014 case QRhiTexture::ASTC_8x6:
4015 blockSize = 16;
4016 xdim = 8;
4017 ydim = 6;
4018 break;
4019 case QRhiTexture::ASTC_8x8:
4020 blockSize = 16;
4021 xdim = ydim = 8;
4022 break;
4023 case QRhiTexture::ASTC_10x5:
4024 blockSize = 16;
4025 xdim = 10;
4026 ydim = 5;
4027 break;
4028 case QRhiTexture::ASTC_10x6:
4029 blockSize = 16;
4030 xdim = 10;
4031 ydim = 6;
4032 break;
4033 case QRhiTexture::ASTC_10x8:
4034 blockSize = 16;
4035 xdim = 10;
4036 ydim = 8;
4037 break;
4038 case QRhiTexture::ASTC_10x10:
4039 blockSize = 16;
4040 xdim = ydim = 10;
4041 break;
4042 case QRhiTexture::ASTC_12x10:
4043 blockSize = 16;
4044 xdim = 12;
4045 ydim = 10;
4046 break;
4047 case QRhiTexture::ASTC_12x12:
4048 blockSize = 16;
4049 xdim = ydim = 12;
4050 break;
4051
4052 default:
4053 Q_UNREACHABLE();
4054 break;
4055 }
4056
4057 const quint32 wblocks = uint((size.width() + xdim - 1) / xdim);
4058 const quint32 hblocks = uint((size.height() + ydim - 1) / ydim);
4059
4060 if (bpl)
4061 *bpl = wblocks * blockSize;
4062 if (byteSize)
4063 *byteSize = wblocks * hblocks * blockSize;
4064 if (blockDim)
4065 *blockDim = QSize(xdim, ydim);
4066}
4067
4068void QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSize &size,
4069 quint32 *bpl, quint32 *byteSize) const
4070{
4071 if (isCompressedFormat(format)) {
4072 compressedFormatInfo(format, size, bpl, byteSize, blockDim: nullptr);
4073 return;
4074 }
4075
4076 quint32 bpc = 0;
4077 switch (format) {
4078 case QRhiTexture::RGBA8:
4079 bpc = 4;
4080 break;
4081 case QRhiTexture::BGRA8:
4082 bpc = 4;
4083 break;
4084 case QRhiTexture::R8:
4085 bpc = 1;
4086 break;
4087 case QRhiTexture::R16:
4088 bpc = 2;
4089 break;
4090 case QRhiTexture::RED_OR_ALPHA8:
4091 bpc = 1;
4092 break;
4093
4094 case QRhiTexture::RGBA16F:
4095 bpc = 8;
4096 break;
4097 case QRhiTexture::RGBA32F:
4098 bpc = 16;
4099 break;
4100 case QRhiTexture::R16F:
4101 bpc = 2;
4102 break;
4103 case QRhiTexture::R32F:
4104 bpc = 4;
4105 break;
4106
4107 case QRhiTexture::D16:
4108 bpc = 2;
4109 break;
4110 case QRhiTexture::D32F:
4111 bpc = 4;
4112 break;
4113
4114 default:
4115 Q_UNREACHABLE();
4116 break;
4117 }
4118
4119 if (bpl)
4120 *bpl = uint(size.width()) * bpc;
4121 if (byteSize)
4122 *byteSize = uint(size.width() * size.height()) * bpc;
4123}
4124
4125// Approximate because it excludes subresource alignment or multisampling.
4126quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format, const QSize &baseSize,
4127 int mipCount, int layerCount)
4128{
4129 quint32 approxSize = 0;
4130 for (int level = 0; level < mipCount; ++level) {
4131 quint32 byteSize = 0;
4132 const QSize size(qFloor(v: qreal(qMax(a: 1, b: baseSize.width() >> level))),
4133 qFloor(v: qreal(qMax(a: 1, b: baseSize.height() >> level))));
4134 textureFormatInfo(format, size, bpl: nullptr, byteSize: &byteSize);
4135 approxSize += byteSize;
4136 }
4137 approxSize *= uint(layerCount);
4138 return approxSize;
4139}
4140
4141bool QRhiImplementation::sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps)
4142{
4143 if (ps->cbeginShaderStages() == ps->cendShaderStages()) {
4144 qWarning(msg: "Cannot build a graphics pipeline without any stages");
4145 return false;
4146 }
4147
4148 bool hasVertexStage = false;
4149 for (auto it = ps->cbeginShaderStages(), itEnd = ps->cendShaderStages(); it != itEnd; ++it) {
4150 if (!it->shader().isValid()) {
4151 qWarning(msg: "Empty shader passed to graphics pipeline");
4152 return false;
4153 }
4154 if (it->type() == QRhiShaderStage::Vertex) {
4155 hasVertexStage = true;
4156 const QRhiVertexInputLayout inputLayout = ps->vertexInputLayout();
4157 if (inputLayout.cbeginAttributes() == inputLayout.cendAttributes()) {
4158 qWarning(msg: "Vertex stage present without any vertex inputs");
4159 return false;
4160 }
4161 }
4162 }
4163 if (!hasVertexStage) {
4164 qWarning(msg: "Cannot build a graphics pipeline without a vertex stage");
4165 return false;
4166 }
4167
4168 if (!ps->renderPassDescriptor()) {
4169 qWarning(msg: "Cannot build a graphics pipeline without a QRhiRenderPassDescriptor");
4170 return false;
4171 }
4172
4173 if (!ps->shaderResourceBindings()) {
4174 qWarning(msg: "Cannot build a graphics pipeline without QRhiShaderResourceBindings");
4175 return false;
4176 }
4177
4178 return true;
4179}
4180
4181/*!
4182 \internal
4183 */
4184QRhi::QRhi()
4185{
4186}
4187
4188/*!
4189 Destructor. Destroys the backend and releases resources.
4190 */
4191QRhi::~QRhi()
4192{
4193 if (!d)
4194 return;
4195
4196 qDeleteAll(c: d->pendingReleaseAndDestroyResources);
4197 d->pendingReleaseAndDestroyResources.clear();
4198
4199 runCleanup();
4200
4201 d->destroy();
4202 delete d;
4203}
4204
4205/*!
4206 \return a new QRhi instance with a backend for the graphics API specified by \a impl.
4207
4208 \a params must point to an instance of one of the backend-specific
4209 subclasses of QRhiInitParams, such as, QRhiVulkanInitParams,
4210 QRhiMetalInitParams, QRhiD3D11InitParams, QRhiGles2InitParams. See these
4211 classes for examples on creating a QRhi.
4212
4213 \a flags is optional. It is used to enable profile and debug related
4214 features that are potentially expensive and should only be used during
4215 development.
4216 */
4217QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice)
4218{
4219 QScopedPointer<QRhi> r(new QRhi);
4220
4221 switch (impl) {
4222 case Null:
4223 r->d = new QRhiNull(static_cast<QRhiNullInitParams *>(params));
4224 break;
4225 case Vulkan:
4226#if QT_CONFIG(vulkan)
4227 r->d = new QRhiVulkan(static_cast<QRhiVulkanInitParams *>(params),
4228 static_cast<QRhiVulkanNativeHandles *>(importDevice));
4229 break;
4230#else
4231 Q_UNUSED(importDevice);
4232 qWarning("This build of Qt has no Vulkan support");
4233 break;
4234#endif
4235 case OpenGLES2:
4236#ifndef QT_NO_OPENGL
4237 r->d = new QRhiGles2(static_cast<QRhiGles2InitParams *>(params),
4238 static_cast<QRhiGles2NativeHandles *>(importDevice));
4239 break;
4240#else
4241 qWarning("This build of Qt has no OpenGL support");
4242 break;
4243#endif
4244 case D3D11:
4245#ifdef Q_OS_WIN
4246 r->d = new QRhiD3D11(static_cast<QRhiD3D11InitParams *>(params),
4247 static_cast<QRhiD3D11NativeHandles *>(importDevice));
4248 break;
4249#else
4250 qWarning(msg: "This platform has no Direct3D 11 support");
4251 break;
4252#endif
4253 case Metal:
4254#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
4255 r->d = new QRhiMetal(static_cast<QRhiMetalInitParams *>(params),
4256 static_cast<QRhiMetalNativeHandles *>(importDevice));
4257 break;
4258#else
4259 qWarning(msg: "This platform has no Metal support");
4260 break;
4261#endif
4262 default:
4263 break;
4264 }
4265
4266 if (r->d) {
4267 r->d->q = r.data();
4268
4269 if (flags.testFlag(flag: EnableProfiling)) {
4270 QRhiProfilerPrivate *profD = QRhiProfilerPrivate::get(p: &r->d->profiler);
4271 profD->rhiDWhenEnabled = r->d;
4272 const_cast<QLoggingCategory &>(QRHI_LOG_INFO()).setEnabled(type: QtDebugMsg, enable: true);
4273 }
4274
4275 // Play nice with QSG_INFO since that is still the most commonly used
4276 // way to get graphics info printed from Qt Quick apps, and the Quick
4277 // scenegraph is our primary user.
4278 if (qEnvironmentVariableIsSet(varName: "QSG_INFO"))
4279 const_cast<QLoggingCategory &>(QRHI_LOG_INFO()).setEnabled(type: QtDebugMsg, enable: true);
4280
4281 r->d->debugMarkers = flags.testFlag(flag: EnableDebugMarkers);
4282
4283 if (r->d->create(flags)) {
4284 r->d->implType = impl;
4285 r->d->implThread = QThread::currentThread();
4286 return r.take();
4287 }
4288 }
4289
4290 return nullptr;
4291}
4292
4293/*!
4294 \return the backend type for this QRhi.
4295 */
4296QRhi::Implementation QRhi::backend() const
4297{
4298 return d->implType;
4299}
4300
4301/*!
4302 \return the thread on which the QRhi was \l{QRhi::create()}{initialized}.
4303 */
4304QThread *QRhi::thread() const
4305{
4306 return d->implThread;
4307}
4308
4309/*!
4310 Registers a \a callback that is invoked either when the QRhi is destroyed,
4311 or when runCleanup() is called.
4312
4313 The callback will run with the graphics resource still available, so this
4314 provides an opportunity for the application to cleanly release QRhiResource
4315 instances belonging to the QRhi. This is particularly useful for managing
4316 the lifetime of resources stored in \c cache type of objects, where the
4317 cache holds QRhiResources or objects containing QRhiResources.
4318
4319 \sa runCleanup(), ~QRhi()
4320 */
4321void QRhi::addCleanupCallback(const CleanupCallback &callback)
4322{
4323 d->addCleanupCallback(callback);
4324}
4325
4326/*!
4327 Invokes all registered cleanup functions. The list of cleanup callbacks it
4328 then cleared. Normally destroying the QRhi does this automatically, but
4329 sometimes it can be useful to trigger cleanup in order to release all
4330 cached, non-essential resources.
4331
4332 \sa addCleanupCallback()
4333 */
4334void QRhi::runCleanup()
4335{
4336 for (const CleanupCallback &f : qAsConst(t&: d->cleanupCallbacks))
4337 f(this);
4338
4339 d->cleanupCallbacks.clear();
4340}
4341
4342/*!
4343 \class QRhiResourceUpdateBatch
4344 \internal
4345 \inmodule QtGui
4346 \brief Records upload and copy type of operations.
4347
4348 With QRhi it is no longer possible to perform copy type of operations at
4349 arbitrary times. Instead, all such operations are recorded into batches
4350 that are then passed, most commonly, to QRhiCommandBuffer::beginPass().
4351 What then happens under the hood is hidden from the application: the
4352 underlying implementations can defer and implement these operations in
4353 various different ways.
4354
4355 A resource update batch owns no graphics resources and does not perform any
4356 actual operations on its own. It should rather be viewed as a command
4357 buffer for update, upload, and copy type of commands.
4358
4359 To get an available, empty batch from the pool, call
4360 QRhi::nextResourceUpdateBatch().
4361 */
4362
4363/*!
4364 \internal
4365 */
4366QRhiResourceUpdateBatch::QRhiResourceUpdateBatch(QRhiImplementation *rhi)
4367 : d(new QRhiResourceUpdateBatchPrivate)
4368{
4369 d->q = this;
4370 d->rhi = rhi;
4371}
4372
4373QRhiResourceUpdateBatch::~QRhiResourceUpdateBatch()
4374{
4375 delete d;
4376}
4377
4378/*!
4379 \return the batch to the pool. This should only be used when the batch is
4380 not passed to one of QRhiCommandBuffer::beginPass(),
4381 QRhiCommandBuffer::endPass(), or QRhiCommandBuffer::resourceUpdate()
4382 because these implicitly call release().
4383
4384 \note QRhiResourceUpdateBatch instances must never by \c deleted by
4385 applications.
4386 */
4387void QRhiResourceUpdateBatch::release()
4388{
4389 d->free();
4390}
4391
4392/*!
4393 Copies all queued operations from the \a other batch into this one.
4394
4395 \note \a other is not changed in any way, typically it will still need a
4396 release()
4397
4398 This allows for a convenient pattern where resource updates that are
4399 already known during the initialization step are collected into a batch
4400 that is then merged into another when starting to first render pass later
4401 on:
4402
4403 \badcode
4404 void init()
4405 {
4406 ...
4407 initialUpdates = rhi->nextResourceUpdateBatch();
4408 initialUpdates->uploadStaticBuffer(vbuf, vertexData);
4409 initialUpdates->uploadStaticBuffer(ibuf, indexData);
4410 ...
4411 }
4412
4413 void render()
4414 {
4415 ...
4416 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
4417 if (initialUpdates) {
4418 resUpdates->merge(initialUpdates);
4419 initialUpdates->release();
4420 initialUpdates = nullptr;
4421 }
4422 resUpdates->updateDynamicBuffer(...);
4423 ...
4424 cb->beginPass(rt, clearCol, clearDs, resUpdates);
4425 }
4426 \endcode
4427 */
4428void QRhiResourceUpdateBatch::merge(QRhiResourceUpdateBatch *other)
4429{
4430 d->merge(other: other->d);
4431}
4432
4433/*!
4434 Enqueues updating a region of a QRhiBuffer \a buf created with the type
4435 QRhiBuffer::Dynamic.
4436
4437 The region is specified \a offset and \a size. The actual bytes to write
4438 are specified by \a data which must have at least \a size bytes available.
4439 \a data can safely be destroyed or changed once this function returns.
4440
4441 \note If host writes are involved, which is the case with
4442 updateDynamicBuffer() typically as such buffers are backed by host visible
4443 memory with most backends, they may accumulate within a frame. Thus pass 1
4444 reading a region changed by a batch passed to pass 2 may see the changes
4445 specified in pass 2's update batch.
4446
4447 \note QRhi transparently manages double buffering in order to prevent
4448 stalling the graphics pipeline. The fact that a QRhiBuffer may have
4449 multiple native underneath can be safely ignored when using the QRhi and
4450 QRhiResourceUpdateBatch.
4451 */
4452void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, int offset, int size, const void *data)
4453{
4454 if (size > 0)
4455 d->bufferOps.append(t: QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, size, data));
4456}
4457
4458/*!
4459 Enqueues updating a region of a QRhiBuffer \a buf created with the type
4460 QRhiBuffer::Immutable or QRhiBuffer::Static.
4461
4462 The region is specified \a offset and \a size. The actual bytes to write
4463 are specified by \a data which must have at least \a size bytes available.
4464 \a data can safely be destroyed or changed once this function returns.
4465 */
4466void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, int offset, int size, const void *data)
4467{
4468 if (size > 0)
4469 d->bufferOps.append(t: QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, size, data));
4470}
4471
4472/*!
4473 Enqueues updating the entire QRhiBuffer \a buf created with the type
4474 QRhiBuffer::Immutable or QRhiBuffer::Static.
4475 */
4476void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *data)
4477{
4478 if (buf->size() > 0)
4479 d->bufferOps.append(t: QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset: 0, size: 0, data));
4480}
4481
4482/*!
4483 Enqueues reading back a region of the QRhiBuffer \a buf. The size of the
4484 region is specified by \a size in bytes, \a offset is the offset in bytes
4485 to start reading from.
4486
4487 A readback is asynchronous. \a result contains a callback that is invoked
4488 when the operation has completed. The data is provided in
4489 QRhiBufferReadbackResult::data. Upon successful completion that QByteArray
4490 will have a size equal to \a size. On failure the QByteArray will be empty.
4491
4492 \note Reading buffers with a usage different than QRhiBuffer::UniformBuffer
4493 is supported only when the QRhi::ReadBackNonUniformBuffer feature is
4494 reported as supported.
4495
4496 \note The asynchronous readback is guaranteed to have completed when one of
4497 the following conditions is met: \l{QRhi::finish()}{finish()} has been
4498 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
4499 including the frame that issued the readback operation, and the
4500 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
4501 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
4502 QRhi::MaxAsyncReadbackFrames.
4503
4504 \sa readBackTexture(), QRhi::isFeatureSupported(), QRhi::resourceLimit()
4505 */
4506void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, int offset, int size, QRhiBufferReadbackResult *result)
4507{
4508 d->bufferOps.append(t: QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result));
4509}
4510
4511/*!
4512 Enqueues uploading the image data for one or more mip levels in one or more
4513 layers of the texture \a tex.
4514
4515 The details of the copy (source QImage or compressed texture data, regions,
4516 target layers and levels) are described in \a desc.
4517 */
4518void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
4519{
4520 if (desc.cbeginEntries() != desc.cendEntries())
4521 d->textureOps.append(t: QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc));
4522}
4523
4524/*!
4525 Enqueues uploading the image data for mip level 0 of layer 0 of the texture
4526 \a tex.
4527
4528 \a tex must have an uncompressed format. Its format must also be compatible
4529 with the QImage::format() of \a image. The source data is given in \a
4530 image.
4531 */
4532void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &image)
4533{
4534 uploadTexture(tex, desc: QRhiTextureUploadEntry(0, 0, image));
4535}
4536
4537/*!
4538 Enqueues a texture-to-texture copy operation from \a src into \a dst as
4539 described by \a desc.
4540
4541 \note The source texture \a src must be created with
4542 QRhiTexture::UsedAsTransferSource.
4543 */
4544void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
4545{
4546 d->textureOps.append(t: QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc));
4547}
4548
4549/*!
4550 Enqueues a texture-to-host copy operation as described by \a rb.
4551
4552 Normally \a rb will specify a QRhiTexture as the source. However, when the
4553 swapchain in the current frame was created with
4554 QRhiSwapChain::UsedAsTransferSource, it can also be the source of the
4555 readback. For this, leave the texture set to null in \a rb.
4556
4557 Unlike other operations, the results here need to be processed by the
4558 application. Therefore, \a result provides not just the data but also a
4559 callback as operations on the batch are asynchronous by nature:
4560
4561 \badcode
4562 beginFrame(sc);
4563 beginPass
4564 ...
4565 QRhiReadbackResult *rbResult = new QRhiReadbackResult;
4566 rbResult->completed = [rbResult] {
4567 {
4568 const QImage::Format fmt = QImage::Format_RGBA8888_Premultiplied; // fits QRhiTexture::RGBA8
4569 const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
4570 QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
4571 image.save("result.png");
4572 }
4573 delete rbResult;
4574 };
4575 u = nextResourceUpdateBatch();
4576 QRhiReadbackDescription rb; // no texture -> uses the current backbuffer of sc
4577 u->readBackTexture(rb, rbResult);
4578 endPass(u);
4579 endFrame(sc);
4580 \endcode
4581
4582 \note The texture must be created with QRhiTexture::UsedAsTransferSource.
4583
4584 \note Multisample textures cannot be read back.
4585
4586 \note The readback returns raw byte data, in order to allow the applications
4587 to interpret it in any way they see fit. Be aware of the blending settings
4588 of rendering code: if the blending is set up to rely on premultiplied alpha,
4589 the results of the readback must also be interpreted as Premultiplied.
4590
4591 \note When interpreting the resulting raw data, be aware that the readback
4592 happens with a byte ordered format. A \l{QRhiTexture::RGBA8}{RGBA8} texture
4593 maps therefore to byte ordered QImage formats, such as,
4594 QImage::Format_RGBA8888.
4595
4596 \note The asynchronous readback is guaranteed to have completed when one of
4597 the following conditions is met: \l{QRhi::finish()}{finish()} has been
4598 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
4599 including the frame that issued the readback operation, and the
4600 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
4601 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
4602 QRhi::MaxAsyncReadbackFrames.
4603
4604 \sa readBackBuffer(), QRhi::resourceLimit()
4605 */
4606void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
4607{
4608 d->textureOps.append(t: QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result));
4609}
4610
4611/*!
4612 Enqueues a mipmap generation operation for the specified \a layer of texture
4613 \a tex.
4614
4615 \note The texture must be created with QRhiTexture::MipMapped and
4616 QRhiTexture::UsedWithGenerateMips.
4617 */
4618void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex, int layer)
4619{
4620 d->textureOps.append(t: QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex, layer));
4621}
4622
4623/*!
4624 \return an available, empty batch to which copy type of operations can be
4625 recorded.
4626
4627 \note the return value is not owned by the caller and must never be
4628 destroyed. Instead, the batch is returned the pool for reuse by passing
4629 it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or
4630 QRhiCommandBuffer::resourceUpdate(), or by calling
4631 QRhiResourceUpdateBatch::release() on it.
4632
4633 \note Can be called outside beginFrame() - endFrame() as well since a batch
4634 instance just collects data on its own, it does not perform any operations.
4635 */
4636QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
4637{
4638 auto nextFreeBatch = [this]() -> QRhiResourceUpdateBatch * {
4639 for (int i = 0, ie = d->resUpdPoolMap.count(); i != ie; ++i) {
4640 if (!d->resUpdPoolMap.testBit(i)) {
4641 d->resUpdPoolMap.setBit(i);
4642 QRhiResourceUpdateBatch *u = d->resUpdPool[i];
4643 QRhiResourceUpdateBatchPrivate::get(b: u)->poolIndex = i;
4644 return u;
4645 }
4646 }
4647 return nullptr;
4648 };
4649
4650 QRhiResourceUpdateBatch *u = nextFreeBatch();
4651 if (!u) {
4652 const int oldSize = d->resUpdPool.count();
4653 const int newSize = oldSize + 4;
4654 d->resUpdPool.resize(asize: newSize);
4655 d->resUpdPoolMap.resize(size: newSize);
4656 for (int i = oldSize; i < newSize; ++i)
4657 d->resUpdPool[i] = new QRhiResourceUpdateBatch(d);
4658 u = nextFreeBatch();
4659 Q_ASSERT(u);
4660 }
4661
4662 return u;
4663}
4664
4665void QRhiResourceUpdateBatchPrivate::free()
4666{
4667 Q_ASSERT(poolIndex >= 0 && rhi->resUpdPool[poolIndex] == q);
4668
4669 bufferOps.clear();
4670 textureOps.clear();
4671
4672 rhi->resUpdPoolMap.clearBit(i: poolIndex);
4673 poolIndex = -1;
4674}
4675
4676void QRhiResourceUpdateBatchPrivate::merge(QRhiResourceUpdateBatchPrivate *other)
4677{
4678 bufferOps.reserve(asize: bufferOps.size() + other->bufferOps.size());
4679 for (const BufferOp &op : qAsConst(t&: other->bufferOps))
4680 bufferOps.append(t: op);
4681
4682 textureOps.reserve(asize: textureOps.size() + other->textureOps.size());
4683 for (const TextureOp &op : qAsConst(t&: other->textureOps))
4684 textureOps.append(t: op);
4685}
4686
4687/*!
4688 Sometimes committing resource updates is necessary without starting a
4689 render pass. Not often needed, updates should typically be passed to
4690 beginPass (or endPass, in case of readbacks) instead.
4691
4692 \note Cannot be called inside a pass.
4693 */
4694void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
4695{
4696 if (resourceUpdates)
4697 m_rhi->resourceUpdate(cb: this, resourceUpdates);
4698}
4699
4700/*!
4701 Records starting a new render pass targeting the render target \a rt.
4702
4703 \a resourceUpdates, when not null, specifies a resource update batch that
4704 is to be committed and then released.
4705
4706 The color and depth/stencil buffers of the render target are normally
4707 cleared. The clear values are specified in \a colorClearValue and \a
4708 depthStencilClearValue. The exception is when the render target was created
4709 with QRhiTextureRenderTarget::PreserveColorContents and/or
4710 QRhiTextureRenderTarget::PreserveDepthStencilContents. The clear values are
4711 ignored then.
4712
4713 \note Enabling preserved color or depth contents leads to decreased
4714 performance depending on the underlying hardware. Mobile GPUs with tiled
4715 architecture benefit from not having to reload the previous contents into
4716 the tile buffer. Similarly, a QRhiTextureRenderTarget with a QRhiTexture as
4717 the depth buffer is less efficient than a QRhiRenderBuffer since using a
4718 depth texture triggers requiring writing the data out to it, while with
4719 renderbuffers this is not needed (as the API does not allow sampling or
4720 reading from a renderbuffer).
4721
4722 \note Do not assume that any state or resource bindings persist between
4723 passes.
4724
4725 \note The QRhiCommandBuffer's \c set and \c draw functions can only be
4726 called inside a pass. Also, with the exception of setGraphicsPipeline(),
4727 they expect to have a pipeline set already on the command buffer.
4728 Unspecified issues may arise otherwise, depending on the backend.
4729 */
4730void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
4731 const QColor &colorClearValue,
4732 const QRhiDepthStencilClearValue &depthStencilClearValue,
4733 QRhiResourceUpdateBatch *resourceUpdates)
4734{
4735 m_rhi->beginPass(cb: this, rt, colorClearValue, depthStencilClearValue, resourceUpdates);
4736}
4737
4738/*!
4739 Records ending the current render pass.
4740
4741 \a resourceUpdates, when not null, specifies a resource update batch that
4742 is to be committed and then released.
4743 */
4744void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates)
4745{
4746 m_rhi->endPass(cb: this, resourceUpdates);
4747}
4748
4749/*!
4750 Records setting a new graphics pipeline \a ps.
4751
4752 \note This function must be called before recording other \c set or \c draw
4753 commands on the command buffer.
4754
4755 \note QRhi will optimize out unnecessary invocations within a pass, so
4756 therefore overoptimizing to avoid calls to this function is not necessary
4757 on the applications' side.
4758
4759 \note This function can only be called inside a render pass, meaning
4760 between a beginPass() and endPass() call.
4761 */
4762void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)
4763{
4764 m_rhi->setGraphicsPipeline(cb: this, ps);
4765}
4766
4767/*!
4768 Records binding a set of shader resources, such as, uniform buffers or
4769 textures, that are made visible to one or more shader stages.
4770
4771 \a srb can be null in which case the current graphics or compute pipeline's
4772 associated QRhiShaderResourceBindings is used. When \a srb is non-null, it
4773 must be
4774 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible},
4775 meaning the layout (number of bindings, the type and binding number of each
4776 binding) must fully match the QRhiShaderResourceBindings that was
4777 associated with the pipeline at the time of calling the pipeline's build().
4778
4779 There are cases when a seemingly unnecessary setShaderResources() call is
4780 mandatory: when rebuilding a resource referenced from \a srb, for example
4781 changing the size of a QRhiBuffer followed by a QRhiBuffer::build(), this
4782 is the place where associated native objects (such as descriptor sets in
4783 case of Vulkan) are updated to refer to the current native resources that
4784 back the QRhiBuffer, QRhiTexture, QRhiSampler objects referenced from \a
4785 srb. In this case setShaderResources() must be called even if \a srb is
4786 the same as in the last call.
4787
4788 \a dynamicOffsets allows specifying buffer offsets for uniform buffers that
4789 were associated with \a srb via
4790 QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(). This is
4791 different from providing the offset in the \a srb itself: dynamic offsets
4792 do not require building a new QRhiShaderResourceBindings for every
4793 different offset, can avoid writing the underlying descriptors (with
4794 backends where applicable), and so they may be more efficient. Each element
4795 of \a dynamicOffsets is a \c binding - \c offset pair.
4796 \a dynamicOffsetCount specifies the number of elements in \a dynamicOffsets.
4797
4798 \note All offsets in \a dynamicOffsets must be byte aligned to the value
4799 returned from QRhi::ubufAlignment().
4800
4801 \note QRhi will optimize out unnecessary invocations within a pass (taking
4802 the conditions described above into account), so therefore overoptimizing
4803 to avoid calls to this function is not necessary on the applications' side.
4804
4805 \note This function can only be called inside a render or compute pass,
4806 meaning between a beginPass() and endPass(), or beginComputePass() and
4807 endComputePass().
4808 */
4809void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb,
4810 int dynamicOffsetCount,
4811 const DynamicOffset *dynamicOffsets)
4812{
4813 m_rhi->setShaderResources(cb: this, srb, dynamicOffsetCount, dynamicOffsets);
4814}
4815
4816/*!
4817 Records vertex input bindings.
4818
4819 The index buffer used by subsequent drawIndexed() commands is specified by
4820 \a indexBuf, \a indexOffset, and \a indexFormat. \a indexBuf can be set to
4821 null when indexed drawing is not needed.
4822
4823 Vertex buffer bindings are batched. \a startBinding specifies the first
4824 binding number. The recorded command then binds each buffer from \a
4825 bindings to the binding point \c{startBinding + i} where \c i is the index
4826 in \a bindings. Each element in \a bindings specifies a QRhiBuffer and an
4827 offset.
4828
4829 Superfluous vertex input and index changes in the same pass are ignored
4830 automatically with most backends and therefore applications do not need to
4831 overoptimize to avoid calls to this function.
4832
4833 \note This function can only be called inside a render pass, meaning
4834 between a beginPass() and endPass() call.
4835
4836 As a simple example, take a vertex shader with two inputs:
4837
4838 \badcode
4839 layout(location = 0) in vec4 position;
4840 layout(location = 1) in vec3 color;
4841 \endcode
4842
4843 and assume we have the data available in interleaved format, using only 2
4844 floats for position (so 5 floats per vertex: x, y, r, g, b). A QRhiGraphicsPipeline for
4845 this shader can then be created using the input layout:
4846
4847 \badcode
4848 QRhiVertexInputLayout inputLayout;
4849 inputLayout.setBindings({
4850 { 5 * sizeof(float) }
4851 });
4852 inputLayout.setAttributes({
4853 { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
4854 { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
4855 });
4856 \endcode
4857
4858 Here there is one buffer binding (binding number 0), with two inputs
4859 referencing it. When recording the pass, once the pipeline is set, the
4860 vertex bindings can be specified simply like the following (using C++11
4861 initializer syntax), assuming vbuf is the QRhiBuffer with all the
4862 interleaved position+color data:
4863
4864 \badcode
4865 const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
4866 cb->setVertexInput(0, 1, &vbufBinding);
4867 \endcode
4868 */
4869void QRhiCommandBuffer::setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
4870 QRhiBuffer *indexBuf, quint32 indexOffset,
4871 IndexFormat indexFormat)
4872{
4873 m_rhi->setVertexInput(cb: this, startBinding, bindingCount, bindings, indexBuf, indexOffset, indexFormat);
4874}
4875
4876/*!
4877 Records setting the active viewport rectangle specified in \a viewport.
4878
4879 With backends where the underlying graphics API has scissoring always
4880 enabled, this function also sets the scissor to match the viewport whenever
4881 the active QRhiGraphicsPipeline does not have
4882 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set.
4883
4884 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
4885 bottom-left.
4886
4887 \note This function can only be called inside a render pass, meaning
4888 between a beginPass() and endPass() call.
4889 */
4890void QRhiCommandBuffer::setViewport(const QRhiViewport &viewport)
4891{
4892 m_rhi->setViewport(cb: this, viewport);
4893}
4894
4895/*!
4896 Records setting the active scissor rectangle specified in \a scissor.
4897
4898 This can only be called when the bound pipeline has
4899 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set. When the flag is
4900 set on the active pipeline, this function must be called because scissor
4901 testing will get enabled and so a scissor rectangle must be provided.
4902
4903 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
4904 bottom-left.
4905
4906 \note This function can only be called inside a render pass, meaning
4907 between a beginPass() and endPass() call.
4908 */
4909void QRhiCommandBuffer::setScissor(const QRhiScissor &scissor)
4910{
4911 m_rhi->setScissor(cb: this, scissor);
4912}
4913
4914/*!
4915 Records setting the active blend constants to \a c.
4916
4917 This can only be called when the bound pipeline has
4918 QRhiGraphicsPipeline::UsesBlendConstants set.
4919
4920 \note This function can only be called inside a render pass, meaning
4921 between a beginPass() and endPass() call.
4922 */
4923void QRhiCommandBuffer::setBlendConstants(const QColor &c)
4924{
4925 m_rhi->setBlendConstants(cb: this, c);
4926}
4927
4928/*!
4929 Records setting the active stencil reference value to \a refValue.
4930
4931 This can only be called when the bound pipeline has
4932 QRhiGraphicsPipeline::UsesStencilRef set.
4933
4934 \note This function can only be called inside a render pass, meaning between
4935 a beginPass() and endPass() call.
4936 */
4937void QRhiCommandBuffer::setStencilRef(quint32 refValue)
4938{
4939 m_rhi->setStencilRef(cb: this, refValue);
4940}
4941
4942/*!
4943 Records a non-indexed draw.
4944
4945 The number of vertices is specified in \a vertexCount. For instanced
4946 drawing set \a instanceCount to a value other than 1. \a firstVertex is the
4947 index of the first vertex to draw. When drawing multiple instances, the
4948 first instance ID is specified by \a firstInstance.
4949
4950 \note \a firstInstance may not be supported, and is ignored when the
4951 QRhi::BaseInstance feature is reported as not supported. The first ID is
4952 always 0 in that case.
4953
4954 \note This function can only be called inside a render pass, meaning
4955 between a beginPass() and endPass() call.
4956 */
4957void QRhiCommandBuffer::draw(quint32 vertexCount,
4958 quint32 instanceCount,
4959 quint32 firstVertex,
4960 quint32 firstInstance)
4961{
4962 m_rhi->draw(cb: this, vertexCount, instanceCount, firstVertex, firstInstance);
4963}
4964
4965/*!
4966 Records an indexed draw.
4967
4968 The number of vertices is specified in \a indexCount. \a firstIndex is the
4969 base index. The effective offset in the index buffer is given by
4970 \c{indexOffset + firstIndex * n} where \c n is 2 or 4 depending on the
4971 index element type. \c indexOffset is specified in setVertexInput().
4972
4973 \note The effective offset in the index buffer must be 4 byte aligned with
4974 some backends (for example, Metal). With these backends the
4975 \l{QRhi::NonFourAlignedEffectiveIndexBufferOffset}{NonFourAlignedEffectiveIndexBufferOffset}
4976 feature will be reported as not-supported.
4977
4978 For instanced drawing set \a instanceCount to a value other than 1. When
4979 drawing multiple instances, the first instance ID is specified by \a
4980 firstInstance.
4981
4982 \note \a firstInstance may not be supported, and is ignored when the
4983 QRhi::BaseInstance feature is reported as not supported. The first ID is
4984 always 0 in that case.
4985
4986 \a vertexOffset (also called \c{base vertex}) is a signed value that is
4987 added to the element index before indexing into the vertex buffer. Support
4988 for this is not always available, and the value is ignored when the feature
4989 QRhi::BaseVertex is reported as unsupported.
4990
4991 \note This function can only be called inside a render pass, meaning
4992 between a beginPass() and endPass() call.
4993 */
4994void QRhiCommandBuffer::drawIndexed(quint32 indexCount,
4995 quint32 instanceCount,
4996 quint32 firstIndex,
4997 qint32 vertexOffset,
4998 quint32 firstInstance)
4999{
5000 m_rhi->drawIndexed(cb: this, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
5001}
5002
5003/*!
5004 Records a named debug group on the command buffer. This is shown in
5005 graphics debugging tools such as \l{https://renderdoc.org/}{RenderDoc} and
5006 \l{https://developer.apple.com/xcode/}{XCode}. The end of the grouping is
5007 indicated by debugMarkEnd().
5008
5009 \note Ignored when QRhi::DebugMarkers are not supported or
5010 QRhi::EnableDebugMarkers is not set.
5011
5012 \note Can be called anywhere within the frame, both inside and outside of passes.
5013 */
5014void QRhiCommandBuffer::debugMarkBegin(const QByteArray &name)
5015{
5016 m_rhi->debugMarkBegin(cb: this, name);
5017}
5018
5019/*!
5020 Records the end of a debug group.
5021
5022 \note Ignored when QRhi::DebugMarkers are not supported or
5023 QRhi::EnableDebugMarkers is not set.
5024
5025 \note Can be called anywhere within the frame, both inside and outside of passes.
5026 */
5027void QRhiCommandBuffer::debugMarkEnd()
5028{
5029 m_rhi->debugMarkEnd(cb: this);
5030}
5031
5032/*!
5033 Inserts a debug message \a msg into the command stream.
5034
5035 \note Ignored when QRhi::DebugMarkers are not supported or
5036 QRhi::EnableDebugMarkers is not set.
5037
5038 \note With some backends debugMarkMsg() is only supported inside a pass and
5039 is ignored when called outside a pass. With others it is recorded anywhere
5040 within the frame.
5041 */
5042void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)
5043{
5044 m_rhi->debugMarkMsg(cb: this, msg);
5045}
5046
5047/*!
5048 Records starting a new compute pass.
5049
5050 \a resourceUpdates, when not null, specifies a resource update batch that
5051 is to be committed and then released.
5052
5053 \note Do not assume that any state or resource bindings persist between
5054 passes.
5055
5056 \note A compute pass can record setComputePipeline(), setShaderResources(),
5057 and dispatch() calls, not graphics ones. General functionality, such as,
5058 debug markers and beginExternal() is available both in render and compute
5059 passes.
5060
5061 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
5062 is reported as supported.
5063 */
5064void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates)
5065{
5066 m_rhi->beginComputePass(cb: this, resourceUpdates);
5067}
5068
5069/*!
5070 Records ending the current compute pass.
5071
5072 \a resourceUpdates, when not null, specifies a resource update batch that
5073 is to be committed and then released.
5074 */
5075void QRhiCommandBuffer::endComputePass(QRhiResourceUpdateBatch *resourceUpdates)
5076{
5077 m_rhi->endComputePass(cb: this, resourceUpdates);
5078}
5079
5080/*!
5081 Records setting a new compute pipeline \a ps.
5082
5083 \note This function must be called before recording setShaderResources() or
5084 dispatch() commands on the command buffer.
5085
5086 \note QRhi will optimize out unnecessary invocations within a pass, so
5087 therefore overoptimizing to avoid calls to this function is not necessary
5088 on the applications' side.
5089
5090 \note This function can only be called inside a compute pass, meaning
5091 between a beginComputePass() and endComputePass() call.
5092 */
5093void QRhiCommandBuffer::setComputePipeline(QRhiComputePipeline *ps)
5094{
5095 m_rhi->setComputePipeline(cb: this, ps);
5096}
5097
5098/*!
5099 Records dispatching compute work items, with \a x, \a y, and \a z
5100 specifying the number of local workgroups in the corresponding dimension.
5101
5102 \note This function can only be called inside a compute pass, meaning
5103 between a beginComputePass() and endComputePass() call.
5104 */
5105void QRhiCommandBuffer::dispatch(int x, int y, int z)
5106{
5107 m_rhi->dispatch(cb: this, x, y, z);
5108}
5109
5110/*!
5111 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
5112 QRhiVulkanCommandBufferNativeHandles. The returned value is \nullptr when
5113 exposing the underlying native resources is not supported by, or not
5114 applicable to, the backend.
5115
5116 \sa QRhiVulkanCommandBufferNativeHandles,
5117 QRhiMetalCommandBufferNativeHandles, beginExternal(), endExternal()
5118 */
5119const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
5120{
5121 return m_rhi->nativeHandles(cb: this);
5122}
5123
5124/*!
5125 To be called when the application before the application is about to
5126 enqueue commands to the current pass' command buffer by calling graphics
5127 API functions directly.
5128
5129 \note This is only available when the intent was declared up front in
5130 beginFrame(). Therefore this function must only be called when the frame
5131 was started with specifying QRhi::ExternalContentsInPass in the flags
5132 passed to QRhi::beginFrame().
5133
5134 With Vulkan or Metal one can query the native command buffer or encoder
5135 objects via nativeHandles() and enqueue commands to them. With OpenGL or
5136 Direct3D 11 the (device) context can be retrieved from
5137 QRhi::nativeHandles(). However, this must never be done without ensuring
5138 the QRhiCommandBuffer's state stays up-to-date. Hence the requirement for
5139 wrapping any externally added command recording between beginExternal() and
5140 endExternal(). Conceptually this is the same as QPainter's
5141 \l{QPainter::beginNativePainting()}{beginNativePainting()} and
5142 \l{QPainter::endNativePainting()}{endNativePainting()} functions.
5143
5144 For OpenGL in particular, this function has an additional task: it makes
5145 sure the context is made current on the current thread.
5146
5147 \note Once beginExternal() is called, no other render pass specific
5148 functions (\c set* or \c draw*) must be called on the
5149 QRhiCommandBuffer until endExternal().
5150
5151 \warning Some backends may return a native command buffer object from
5152 QRhiCommandBuffer::nativeHandles() that is different from the primary one
5153 when inside a beginExternal() - endExternal() block. Therefore it is
5154 important to (re)query the native command buffer object after calling
5155 beginExternal(). In practical terms this means that with Vulkan for example
5156 the externally recorded Vulkan commands are placed onto a secondary command
5157 buffer (with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT).
5158 nativeHandles() returns this secondary command buffer when called between
5159 begin/endExternal.
5160
5161 \sa endExternal(), nativeHandles()
5162 */
5163void QRhiCommandBuffer::beginExternal()
5164{
5165 m_rhi->beginExternal(cb: this);
5166}
5167
5168/*!
5169 To be called once the externally added commands are recorded to the command
5170 buffer or context.
5171
5172 \note All QRhiCommandBuffer state must be assumed as invalid after calling
5173 this function. Pipelines, vertex and index buffers, and other state must be
5174 set again if more draw calls are recorded after the external commands.
5175
5176 \sa beginExternal(), nativeHandles()
5177 */
5178void QRhiCommandBuffer::endExternal()
5179{
5180 m_rhi->endExternal(cb: this);
5181}
5182
5183/*!
5184 \return the value (typically an offset) \a v aligned to the uniform buffer
5185 alignment given by by ubufAlignment().
5186 */
5187int QRhi::ubufAligned(int v) const
5188{
5189 const int byteAlign = ubufAlignment();
5190 return (v + byteAlign - 1) & ~(byteAlign - 1);
5191}
5192
5193/*!
5194 \return the number of mip levels for a given \a size.
5195 */
5196int QRhi::mipLevelsForSize(const QSize &size) const
5197{
5198 return qFloor(v: std::log2(x: qMax(a: size.width(), b: size.height()))) + 1;
5199}
5200
5201/*!
5202 \return the texture image size for a given \a mipLevel, calculated based on
5203 the level 0 size given in \a baseLevelSize.
5204 */
5205QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize) const
5206{
5207 const int w = qMax(a: 1, b: baseLevelSize.width() >> mipLevel);
5208 const int h = qMax(a: 1, b: baseLevelSize.height() >> mipLevel);
5209 return QSize(w, h);
5210}
5211
5212/*!
5213 \return \c true if the underlying graphics API has the Y axis pointing up
5214 in framebuffers and images.
5215
5216 In practice this is \c true for OpenGL only.
5217 */
5218bool QRhi::isYUpInFramebuffer() const
5219{
5220 return d->isYUpInFramebuffer();
5221}
5222
5223/*!
5224 \return \c true if the underlying graphics API has the Y axis pointing up
5225 in its normalized device coordinate system.
5226
5227 In practice this is \c false for Vulkan only.
5228
5229 \note clipSpaceCorrMatrix() includes the corresponding adjustment (to make
5230 Y point up) in its returned matrix.
5231 */
5232bool QRhi::isYUpInNDC() const
5233{
5234 return d->isYUpInNDC();
5235}
5236
5237/*!
5238 \return \c true if the underlying graphics API uses depth range [0, 1] in
5239 clip space.
5240
5241 In practice this is \c false for OpenGL only, because OpenGL uses a
5242 post-projection depth range of [-1, 1]. (not to be confused with the
5243 NDC-to-window mapping controlled by glDepthRange(), which uses a range of
5244 [0, 1], unless overridden by the QRhiViewport) In some OpenGL versions
5245 glClipControl() could be used to change this, but the OpenGL backend of
5246 QRhi does not use that function as it is not available in OpenGL ES or
5247 OpenGL versions lower than 4.5.
5248
5249 \note clipSpaceCorrMatrix() includes the corresponding adjustment in its
5250 returned matrix. Therefore, many users of QRhi do not need to take any
5251 further measures apart from pre-multiplying their projection matrices with
5252 clipSpaceCorrMatrix(). However, some graphics techniques, such as, some
5253 types of shadow mapping, involve working with and outputting depth values
5254 in the shaders. These will need to query and take the value of this
5255 function into account as appropriate.
5256 */
5257bool QRhi::isClipDepthZeroToOne() const
5258{
5259 return d->isClipDepthZeroToOne();
5260}
5261
5262/*!
5263 \return a matrix that can be used to allow applications keep using
5264 OpenGL-targeted vertex data and perspective projection matrices (such as,
5265 the ones generated by QMatrix4x4::perspective()), regardless of the active
5266 QRhi backend.
5267
5268 In a typical renderer, once \c{this_matrix * mvp} is used instead of just
5269 \c mvp, vertex data with Y up and viewports with depth range 0 - 1 can be
5270 used without considering what backend (and so graphics API) is going to be
5271 used at run time. This way branching based on isYUpInNDC() and
5272 isClipDepthZeroToOne() can be avoided (although such logic may still become
5273 required when implementing certain advanced graphics techniques).
5274
5275 See
5276 \l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this
5277 page} for a discussion of the topic from Vulkan perspective.
5278 */
5279QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
5280{
5281 return d->clipSpaceCorrMatrix();
5282}
5283
5284/*!
5285 \return \c true if the specified texture \a format modified by \a flags is
5286 supported.
5287
5288 The query is supported both for uncompressed and compressed formats.
5289 */
5290bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
5291{
5292 return d->isTextureFormatSupported(format, flags);
5293}
5294
5295/*!
5296 \return \c true if the specified \a feature is supported
5297 */
5298bool QRhi::isFeatureSupported(QRhi::Feature feature) const
5299{
5300 return d->isFeatureSupported(feature);
5301}
5302
5303/*!
5304 \return the value for the specified resource \a limit.
5305
5306 The values are expected to be queried by the backends upon initialization,
5307 meaning calling this function is a light operation.
5308 */
5309int QRhi::resourceLimit(ResourceLimit limit) const
5310{
5311 return d->resourceLimit(limit);
5312}
5313
5314/*!
5315 \return a pointer to the backend-specific collection of native objects
5316 for the device, context, and similar concepts used by the backend.
5317
5318 Cast to QRhiVulkanNativeHandles, QRhiD3D11NativeHandles,
5319 QRhiGles2NativeHandles, QRhiMetalNativeHandles as appropriate.
5320
5321 \note No ownership is transferred, neither for the returned pointer nor for
5322 any native objects.
5323 */
5324const QRhiNativeHandles *QRhi::nativeHandles()
5325{
5326 return d->nativeHandles();
5327}
5328
5329/*!
5330 With OpenGL this makes the OpenGL context current on the current thread.
5331 The function has no effect with other backends.
5332
5333 Calling this function is relevant typically in Qt framework code, when one
5334 has to ensure external OpenGL code provided by the application can still
5335 run like it did before with direct usage of OpenGL, as long as the QRhi is
5336 using the OpenGL backend.
5337
5338 \return false when failed, similarly to QOpenGLContext::makeCurrent(). When
5339 the operation failed, isDeviceLost() can be called to determine if there
5340 was a loss of context situation. Such a check is equivalent to checking via
5341 QOpenGLContext::isValid().
5342
5343 \sa QOpenGLContext::makeCurrent(), QOpenGLContext::isValid()
5344 */
5345bool QRhi::makeThreadLocalNativeContextCurrent()
5346{
5347 return d->makeThreadLocalNativeContextCurrent();
5348}
5349
5350/*!
5351 \return the associated QRhiProfiler instance.
5352
5353 An instance is always available for each QRhi, but it is not very useful
5354 without EnableProfiling because no data is collected without setting the
5355 flag upon creation.
5356 */
5357QRhiProfiler *QRhi::profiler()
5358{
5359 return &d->profiler;
5360}
5361
5362/*!
5363 Attempts to release resources in the backend's caches. This can include both
5364 CPU and GPU resources. Only memory and resources that can be recreated
5365 automatically are in scope. As an example, if the backend's
5366 QRhiGraphicsPipeline implementation maintains a cache of shader compilation
5367 results, calling this function leads to emptying that cache, thus
5368 potentially freeing up memory and graphics resources.
5369
5370 Calling this function makes sense in resource constrained environments,
5371 where at a certain point there is a need to ensure minimal resource usage,
5372 at the expense of performance.
5373 */
5374void QRhi::releaseCachedResources()
5375{
5376 d->releaseCachedResources();
5377}
5378
5379/*!
5380 \return true if the graphics device was lost.
5381
5382 The loss of the device is typically detected in beginFrame(), endFrame() or
5383 QRhiSwapChain::buildOrResize(), depending on the backend and the underlying
5384 native APIs. The most common is endFrame() because that is where presenting
5385 happens. With some backends QRhiSwapChain::buildOrResize() can also fail
5386 due to a device loss. Therefore this function is provided as a generic way
5387 to check if a device loss was detected by a previous operation.
5388
5389 When the device is lost, no further operations should be done via the QRhi.
5390 Rather, all QRhi resources should be released, followed by destroying the
5391 QRhi. A new QRhi can then be attempted to be created. If successful, all
5392 graphics resources must be reinitialized. If not, try again later,
5393 repeatedly.
5394
5395 While simple applications may decide to not care about device loss,
5396 on the commonly used desktop platforms a device loss can happen
5397 due to a variety of reasons, including physically disconnecting the
5398 graphics adapter, disabling the device or driver, uninstalling or upgrading
5399 the graphics driver, or due to errors that lead to a graphics device reset.
5400 Some of these can happen under perfectly normal circumstances as well, for
5401 example the upgrade of the graphics driver to a newer version is a common
5402 task that can happen at any time while a Qt application is running. Users
5403 may very well expect applications to be able to survive this, even when the
5404 application is actively using an API like OpenGL or Direct3D.
5405
5406 Qt's own frameworks built on top of QRhi, such as, Qt Quick, can be
5407 expected to handle and take appropriate measures when a device loss occurs.
5408 If the data for graphics resources, such as textures and buffers, are still
5409 available on the CPU side, such an event may not be noticeable on the
5410 application level at all since graphics resources can seamlessly be
5411 reinitialized then. However, applications and libraries working directly
5412 with QRhi are expected to be prepared to check and handle device loss
5413 situations themselves.
5414
5415 \note With OpenGL, applications may need to opt-in to context reset
5416 notifications by setting QSurfaceFormat::ResetNotification on the
5417 QOpenGLContext. This is typically done by enabling the flag in
5418 QRhiGles2InitParams::format. Keep in mind however that some systems may
5419 generate context resets situations even when this flag is not set.
5420 */
5421bool QRhi::isDeviceLost() const
5422{
5423 return d->isDeviceLost();
5424}
5425
5426/*!
5427 \return a new graphics pipeline resource.
5428
5429 \sa QRhiResource::release()
5430 */
5431QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
5432{
5433 return d->createGraphicsPipeline();
5434}
5435
5436/*!
5437 \return a new compute pipeline resource.
5438
5439 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
5440 is reported as supported.
5441
5442 \sa QRhiResource::release()
5443 */
5444QRhiComputePipeline *QRhi::newComputePipeline()
5445{
5446 return d->createComputePipeline();
5447}
5448
5449/*!
5450 \return a new shader resource binding collection resource.
5451
5452 \sa QRhiResource::release()
5453 */
5454QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
5455{
5456 return d->createShaderResourceBindings();
5457}
5458
5459/*!
5460 \return a new buffer with the specified \a type, \a usage, and \a size.
5461
5462 \note Some \a usage and \a type combinations may not be supported by all
5463 backends. See \l{QRhiBuffer::UsageFlag}{UsageFlags} and
5464 \l{QRhi::NonDynamicUniformBuffers}{the feature flags}.
5465
5466 \note Backends may choose to allocate buffers bigger than \a size. This is
5467 done transparently to applications, so there are no special restrictions on
5468 the value of \a size. QRhiBuffer::size() will always report back the value
5469 that was requested in \a size.
5470
5471 \sa QRhiResource::release()
5472 */
5473QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type,
5474 QRhiBuffer::UsageFlags usage,
5475 int size)
5476{
5477 return d->createBuffer(type, usage, size);
5478}
5479
5480/*!
5481 \return a new renderbuffer with the specified \a type, \a pixelSize, \a
5482 sampleCount, and \a flags.
5483
5484 \sa QRhiResource::release()
5485 */
5486QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type,
5487 const QSize &pixelSize,
5488 int sampleCount,
5489 QRhiRenderBuffer::Flags flags)
5490{
5491 return d->createRenderBuffer(type, pixelSize, sampleCount, flags);
5492}
5493
5494/*!
5495 \return a new texture with the specified \a format, \a pixelSize, \a
5496 sampleCount, and \a flags.
5497
5498 \note \a format specifies the requested internal and external format,
5499 meaning the data to be uploaded to the texture will need to be in a
5500 compatible format, while the native texture may (but is not guaranteed to,
5501 in case of OpenGL at least) use this format internally.
5502
5503 \sa QRhiResource::release()
5504 */
5505QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
5506 const QSize &pixelSize,
5507 int sampleCount,
5508 QRhiTexture::Flags flags)
5509{
5510 return d->createTexture(format, pixelSize, sampleCount, flags);
5511}
5512
5513/*!
5514 \return a new sampler with the specified magnification filter \a magFilter,
5515 minification filter \a minFilter, mipmapping mode \a mipmapMode, and the
5516 addressing (wrap) modes \a addressU, \a addressV, and \a addressW.
5517
5518 \sa QRhiResource::release()
5519 */
5520QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter,
5521 QRhiSampler::Filter minFilter,
5522 QRhiSampler::Filter mipmapMode,
5523 QRhiSampler::AddressMode addressU,
5524 QRhiSampler::AddressMode addressV,
5525 QRhiSampler::AddressMode addressW)
5526{
5527 return d->createSampler(magFilter, minFilter, mipmapMode, u: addressU, v: addressV, w: addressW);
5528}
5529
5530/*!
5531 \return a new texture render target with color and depth/stencil
5532 attachments given in \a desc, and with the specified \a flags.
5533
5534 \sa QRhiResource::release()
5535 */
5536
5537QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
5538 QRhiTextureRenderTarget::Flags flags)
5539{
5540 return d->createTextureRenderTarget(desc, flags);
5541}
5542
5543/*!
5544 \return a new swapchain.
5545
5546 \sa QRhiResource::release(), QRhiSwapChain::buildOrResize()
5547 */
5548QRhiSwapChain *QRhi::newSwapChain()
5549{
5550 return d->createSwapChain();
5551}
5552
5553/*!
5554 Starts a new frame targeting the next available buffer of \a swapChain.
5555
5556 A frame consists of resource updates and one or more render and compute
5557 passes.
5558
5559 \a flags can indicate certain special cases. For example, the fact that
5560 QRhiCommandBuffer::beginExternal() will be called within this new frame
5561 must be declared up front by setting the ExternalContentsInPass flag.
5562
5563 The high level pattern of rendering into a QWindow using a swapchain:
5564
5565 \list
5566
5567 \li Create a swapchain.
5568
5569 \li Call QRhiSwapChain::buildOrResize() whenever the surface size is
5570 different than before.
5571
5572 \li Call QRhiSwapChain::release() on
5573 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed.
5574
5575 \li Then on every frame:
5576 \badcode
5577 beginFrame(sc);
5578 updates = nextResourceUpdateBatch();
5579 updates->...
5580 QRhiCommandBuffer *cb = sc->currentFrameCommandBuffer();
5581 cb->beginPass(sc->currentFrameRenderTarget(), colorClear, dsClear, updates);
5582 ...
5583 cb->endPass();
5584 ... // more passes as necessary
5585 endFrame(sc);
5586 \endcode
5587
5588 \endlist
5589
5590 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
5591 value on failure. Some of these should be treated as soft, "try again
5592 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
5593 the swapchain is to be resized or updated by calling
5594 QRhiSwapChain::buildOrResize(). The application should then attempt to
5595 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
5596 lost but this may also be recoverable by releasing all resources, including
5597 the QRhi itself, and then recreating all resources. See isDeviceLost() for
5598 further discussion.
5599
5600 \sa endFrame(), beginOffscreenFrame(), isDeviceLost()
5601 */
5602QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
5603{
5604 if (d->inFrame)
5605 qWarning(msg: "Attempted to call beginFrame() within a still active frame; ignored");
5606
5607 QRhi::FrameOpResult r = !d->inFrame ? d->beginFrame(swapChain, flags) : FrameOpSuccess;
5608 if (r == FrameOpSuccess)
5609 d->inFrame = true;
5610
5611 return r;
5612}
5613
5614/*!
5615 Ends, commits, and presents a frame that was started in the last
5616 beginFrame() on \a swapChain.
5617
5618 Double (or triple) buffering is managed internally by the QRhiSwapChain and
5619 QRhi.
5620
5621 \a flags can optionally be used to change the behavior in certain ways.
5622 Passing QRhi::SkipPresent skips queuing the Present command or calling
5623 swapBuffers.
5624
5625 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
5626 value on failure. Some of these should be treated as soft, "try again
5627 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
5628 the swapchain is to be resized or updated by calling
5629 QRhiSwapChain::buildOrResize(). The application should then attempt to
5630 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
5631 lost but this may also be recoverable by releasing all resources, including
5632 the QRhi itself, and then recreating all resources. See isDeviceLost() for
5633 further discussion.
5634
5635 \sa beginFrame(), isDeviceLost()
5636 */
5637QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags)
5638{
5639 if (!d->inFrame)
5640 qWarning(msg: "Attempted to call endFrame() without an active frame; ignored");
5641
5642 QRhi::FrameOpResult r = d->inFrame ? d->endFrame(swapChain, flags) : FrameOpSuccess;
5643 d->inFrame = false;
5644 // releaseAndDestroyLater is a high level QRhi concept the backends know
5645 // nothing about - handle it here.
5646 qDeleteAll(c: d->pendingReleaseAndDestroyResources);
5647 d->pendingReleaseAndDestroyResources.clear();
5648
5649 return r;
5650}
5651
5652/*!
5653 \return true when there is an active frame, meaning there was a
5654 beginFrame() (or beginOffscreenFrame()) with no corresponding endFrame()
5655 (or endOffscreenFrame()) yet.
5656
5657 \sa currentFrameSlot(), beginFrame(), endFrame()
5658 */
5659bool QRhi::isRecordingFrame() const
5660{
5661 return d->inFrame;
5662}
5663
5664/*!
5665 \return the current frame slot index while recording a frame. Unspecified
5666 when called outside an active frame (that is, when isRecordingFrame() is \c
5667 false).
5668
5669 With backends like Vulkan or Metal, it is the responsibility of the QRhi
5670 backend to block whenever starting a new frame and finding the CPU is
5671 already \c{FramesInFlight - 1} frames ahead of the GPU (because the command
5672 buffer submitted in frame no. \c{current} - \c{FramesInFlight} has not yet
5673 completed).
5674
5675 Resources that tend to change between frames (such as, the native buffer
5676 object backing a QRhiBuffer with type QRhiBuffer::Dynamic) exist in
5677 multiple versions, so that each frame, that can be submitted while a
5678 previous one is still being processed, works with its own copy, thus
5679 avoiding the need to stall the pipeline when preparing the frame. (The
5680 contents of a resource that may still be in use in the GPU should not be
5681 touched, but simply always waiting for the previous frame to finish would
5682 reduce GPU utilization and ultimately, performance and efficiency.)
5683
5684 Conceptually this is somewhat similar to copy-on-write schemes used by some
5685 C++ containers and other types. It may also be similar to what an OpenGL or
5686 Direct 3D 11 implementation performs internally for certain type of objects.
5687
5688 In practice, such double (or tripple) buffering resources is realized in
5689 the Vulkan, Metal, and similar QRhi backends by having a fixed number of
5690 native resource (such as, VkBuffer) \c slots behind a QRhiResource. That
5691 can then be indexed by a frame slot index running 0, 1, ..,
5692 FramesInFlight-1, and then wrapping around.
5693
5694 All this is managed transparently to the users of QRhi. However,
5695 applications that integrate rendering done directly with the graphics API
5696 may want to perform a similar double or tripple buffering of their own
5697 graphics resources. That is then most easily achieved by knowing the values
5698 of the maximum number of in-flight frames (retrievable via resourceLimit())
5699 and the current frame (slot) index (returned by this function).
5700
5701 \sa isRecordingFrame(), beginFrame(), endFrame()
5702 */
5703int QRhi::currentFrameSlot() const
5704{
5705 return d->currentFrameSlot;
5706}
5707
5708/*!
5709 Starts a new offscreen frame. Provides a command buffer suitable for
5710 recording rendering commands in \a cb. \a flags is used to indicate
5711 certain special cases, just like with beginFrame().
5712
5713 \note The QRhiCommandBuffer stored to *cb is not owned by the caller.
5714
5715 Rendering without a swapchain is possible as well. The typical use case is
5716 to use it in completely offscreen applications, e.g. to generate image
5717 sequences by rendering and reading back without ever showing a window.
5718
5719 Usage in on-screen applications (so beginFrame, endFrame,
5720 beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) is possible too
5721 but it does reduce parallelism so it should be done only infrequently.
5722
5723 Offscreen frames do not let the CPU - potentially - generate another frame
5724 while the GPU is still processing the previous one. This has the side
5725 effect that if readbacks are scheduled, the results are guaranteed to be
5726 available once endOffscreenFrame() returns. That is not the case with
5727 frames targeting a swapchain.
5728
5729 The skeleton of rendering a frame without a swapchain and then reading the
5730 frame contents back could look like the following:
5731
5732 \badcode
5733 QRhiReadbackResult rbResult;
5734 QRhiCommandBuffer *cb;
5735 beginOffscreenFrame(&cb);
5736 beginPass
5737 ...
5738 u = nextResourceUpdateBatch();
5739 u->readBackTexture(rb, &rbResult);
5740 endPass(u);
5741 endOffscreenFrame();
5742 // image data available in rbResult
5743 \endcode
5744
5745 \sa endOffscreenFrame(), beginFrame()
5746 */
5747QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags)
5748{
5749 if (d->inFrame)
5750 qWarning(msg: "Attempted to call beginOffscreenFrame() within a still active frame; ignored");
5751
5752 QRhi::FrameOpResult r = !d->inFrame ? d->beginOffscreenFrame(cb, flags) : FrameOpSuccess;
5753 if (r == FrameOpSuccess)
5754 d->inFrame = true;
5755
5756 return r;
5757}
5758
5759/*!
5760 Ends and waits for the offscreen frame.
5761
5762 \sa beginOffscreenFrame()
5763 */
5764QRhi::FrameOpResult QRhi::endOffscreenFrame(EndFrameFlags flags)
5765{
5766 if (!d->inFrame)
5767 qWarning(msg: "Attempted to call endOffscreenFrame() without an active frame; ignored");
5768
5769 QRhi::FrameOpResult r = d->inFrame ? d->endOffscreenFrame(flags) : FrameOpSuccess;
5770 d->inFrame = false;
5771 qDeleteAll(c: d->pendingReleaseAndDestroyResources);
5772 d->pendingReleaseAndDestroyResources.clear();
5773
5774 return r;
5775}
5776
5777/*!
5778 Waits for any work on the graphics queue (where applicable) to complete,
5779 then executes all deferred operations, like completing readbacks and
5780 resource releases. Can be called inside and outside of a frame, but not
5781 inside a pass. Inside a frame it implies submitting any work on the
5782 command buffer.
5783
5784 \note Avoid this function. One case where it may be needed is when the
5785 results of an enqueued readback in a swapchain-based frame are needed at a
5786 fixed given point and so waiting for the results is desired.
5787 */
5788QRhi::FrameOpResult QRhi::finish()
5789{
5790 return d->finish();
5791}
5792
5793/*!
5794 \return the list of supported sample counts.
5795
5796 A typical example would be (1, 2, 4, 8).
5797
5798 With some backend this list of supported values is fixed in advance, while
5799 with some others the (physical) device properties indicate what is
5800 supported at run time.
5801 */
5802QVector<int> QRhi::supportedSampleCounts() const
5803{
5804 return d->supportedSampleCounts();
5805}
5806
5807/*!
5808 \return the minimum uniform buffer offset alignment in bytes. This is
5809 typically 256.
5810
5811 Attempting to bind a uniform buffer region with an offset not aligned to
5812 this value will lead to failures depending on the backend and the
5813 underlying graphics API.
5814
5815 \sa ubufAligned()
5816 */
5817int QRhi::ubufAlignment() const
5818{
5819 return d->ubufAlignment();
5820}
5821
5822static QBasicAtomicInteger<QRhiGlobalObjectIdGenerator::Type> counter = Q_BASIC_ATOMIC_INITIALIZER(0);
5823
5824QRhiGlobalObjectIdGenerator::Type QRhiGlobalObjectIdGenerator::newId()
5825{
5826 return counter.fetchAndAddRelaxed(valueToAdd: 1) + 1;
5827}
5828
5829bool QRhiPassResourceTracker::isEmpty() const
5830{
5831 return m_buffers.isEmpty() && m_textures.isEmpty();
5832}
5833
5834void QRhiPassResourceTracker::reset()
5835{
5836 m_buffers.clear();
5837 m_textures.clear();
5838}
5839
5840static inline QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a,
5841 QRhiPassResourceTracker::BufferStage b)
5842{
5843 return QRhiPassResourceTracker::BufferStage(qMin(a: int(a), b: int(b)));
5844}
5845
5846void QRhiPassResourceTracker::registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
5847 const UsageState &state)
5848{
5849 auto it = m_buffers.find(akey: buf);
5850 if (it != m_buffers.end()) {
5851 if (it->access != *access) {
5852 const QByteArray name = buf->name();
5853 qWarning(msg: "Buffer %p (%s) used with different accesses within the same pass, this is not allowed.",
5854 buf, name.constData());
5855 return;
5856 }
5857 if (it->stage != *stage) {
5858 it->stage = earlierStage(a: it->stage, b: *stage);
5859 *stage = it->stage;
5860 }
5861 return;
5862 }
5863
5864 Buffer b;
5865 b.slot = slot;
5866 b.access = *access;
5867 b.stage = *stage;
5868 b.stateAtPassBegin = state; // first use -> initial state
5869 m_buffers.insert(akey: buf, avalue: b);
5870}
5871
5872static inline QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a,
5873 QRhiPassResourceTracker::TextureStage b)
5874{
5875 return QRhiPassResourceTracker::TextureStage(qMin(a: int(a), b: int(b)));
5876}
5877
5878static inline bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess access)
5879{
5880 return access == QRhiPassResourceTracker::TexStorageLoad
5881 || access == QRhiPassResourceTracker::TexStorageStore
5882 || access == QRhiPassResourceTracker::TexStorageLoadStore;
5883}
5884
5885void QRhiPassResourceTracker::registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage,
5886 const UsageState &state)
5887{
5888 auto it = m_textures.find(akey: tex);
5889 if (it != m_textures.end()) {
5890 if (it->access != *access) {
5891 // Different subresources of a texture may be used for both load
5892 // and store in the same pass. (think reading from one mip level
5893 // and writing to another one in a compute shader) This we can
5894 // handle by treating the entire resource as read-write.
5895 if (isImageLoadStore(access: it->access) && isImageLoadStore(access: *access)) {
5896 it->access = QRhiPassResourceTracker::TexStorageLoadStore;
5897 *access = it->access;
5898 } else {
5899 const QByteArray name = tex->name();
5900 qWarning(msg: "Texture %p (%s) used with different accesses within the same pass, this is not allowed.",
5901 tex, name.constData());
5902 }
5903 }
5904 if (it->stage != *stage) {
5905 it->stage = earlierStage(a: it->stage, b: *stage);
5906 *stage = it->stage;
5907 }
5908 return;
5909 }
5910
5911 Texture t;
5912 t.access = *access;
5913 t.stage = *stage;
5914 t.stateAtPassBegin = state; // first use -> initial state
5915 m_textures.insert(akey: tex, avalue: t);
5916}
5917
5918QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
5919{
5920 // pick the earlier stage (as this is going to be dstAccessMask)
5921 if (stages.testFlag(flag: QRhiShaderResourceBinding::VertexStage))
5922 return QRhiPassResourceTracker::BufVertexStage;
5923 if (stages.testFlag(flag: QRhiShaderResourceBinding::FragmentStage))
5924 return QRhiPassResourceTracker::BufFragmentStage;
5925 if (stages.testFlag(flag: QRhiShaderResourceBinding::ComputeStage))
5926 return QRhiPassResourceTracker::BufComputeStage;
5927
5928 Q_UNREACHABLE();
5929 return QRhiPassResourceTracker::BufVertexStage;
5930}
5931
5932QRhiPassResourceTracker::TextureStage QRhiPassResourceTracker::toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
5933{
5934 // pick the earlier stage (as this is going to be dstAccessMask)
5935 if (stages.testFlag(flag: QRhiShaderResourceBinding::VertexStage))
5936 return QRhiPassResourceTracker::TexVertexStage;
5937 if (stages.testFlag(flag: QRhiShaderResourceBinding::FragmentStage))
5938 return QRhiPassResourceTracker::TexFragmentStage;
5939 if (stages.testFlag(flag: QRhiShaderResourceBinding::ComputeStage))
5940 return QRhiPassResourceTracker::TexComputeStage;
5941
5942 Q_UNREACHABLE();
5943 return QRhiPassResourceTracker::TexVertexStage;
5944}
5945
5946QT_END_NAMESPACE
5947

source code of qtbase/src/gui/rhi/qrhi.cpp