Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qrhi.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qrhi_p.h"
6#include <qmath.h>
7#include <QLoggingCategory>
8#include "private/qloggingregistry_p.h"
9
10#include "qrhinull_p.h"
11#ifndef QT_NO_OPENGL
12#include "qrhigles2_p.h"
13#endif
14#if QT_CONFIG(vulkan)
15#include "qrhivulkan_p.h"
16#endif
17#ifdef Q_OS_WIN
18#include "qrhid3d11_p.h"
19#include "qrhid3d12_p.h"
20#endif
21#if QT_CONFIG(metal)
22#include "qrhimetal_p.h"
23#endif
24
25#include <limits>
26#include <memory>
27
28QT_BEGIN_NAMESPACE
29
30// Play nice with QSG_INFO since that is still the most commonly used
31// way to get graphics info printed from Qt Quick apps, and the Quick
32// scenegraph is our primary user.
33Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(QRHI_LOG_INFO, "QSG_INFO", "qt.rhi.general")
34
35Q_LOGGING_CATEGORY(QRHI_LOG_RUB, "qt.rhi.rub")
36
37/*!
38 \class QRhi
39 \ingroup painting-3D
40 \inmodule QtGuiPrivate
41 \inheaderfile rhi/qrhi.h
42 \since 6.6
43
44 \brief Accelerated 2D/3D graphics API abstraction.
45
46 The Qt Rendering Hardware Interface is an abstraction for hardware accelerated
47 graphics APIs, such as, \l{https://www.khronos.org/opengl/}{OpenGL},
48 \l{https://www.khronos.org/opengles/}{OpenGL ES},
49 \l{https://docs.microsoft.com/en-us/windows/desktop/direct3d}{Direct3D},
50 \l{https://developer.apple.com/metal/}{Metal}, and
51 \l{https://www.khronos.org/vulkan/}{Vulkan}.
52
53 \warning The QRhi family of classes in the Qt Gui module, including QShader
54 and QShaderDescription, offer limited compatibility guarantees. There are
55 no source or binary compatibility guarantees for these classes, meaning the
56 API is only guaranteed to work with the Qt version the application was
57 developed against. Source incompatible changes are however aimed to be kept
58 at a minimum and will only be made in minor releases (6.7, 6.8, and so on).
59 To use these classes in an application, link to
60 \c{Qt::GuiPrivate} (if using CMake), and include the headers with the \c
61 rhi prefix, for example \c{#include <rhi/qrhi.h>}.
62
63 Each QRhi instance is backed by a backend for a specific graphics API. The
64 selection of the backend is a run time choice and is up to the application
65 or library that creates the QRhi instance. Some backends are available on
66 multiple platforms (OpenGL, Vulkan, Null), while APIs specific to a given
67 platform are only available when running on the platform in question (Metal
68 on macOS/iOS, Direct3D on Windows).
69
70 The available backends currently are:
71
72 \list
73
74 \li OpenGL 2.1 / OpenGL ES 2.0 or newer. Some extensions and newer core
75 specification features are utilized when present, for example to enable
76 multisample framebuffers or compute shaders. Operating in core profile
77 contexts is supported as well. If necessary, applications can query the
78 \l{QRhi::Feature}{feature flags} at runtime to check for features that are
79 not supported in the OpenGL context backing the QRhi. The OpenGL backend
80 builds on QOpenGLContext, QOpenGLFunctions, and the related cross-platform
81 infrastructure of the Qt GUI module.
82
83 \li Direct3D 11.2 and newer (with DXGI 1.3 and newer), using Shader Model
84 5.0 or newer. When the D3D runtime has no support for 11.2 features or
85 Shader Model 5.0, initialization using an accelerated graphics device will
86 fail, but using the
87 \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/directx-warp}{software
88 adapter} is still an option.
89
90 \li Direct3D 12 on Windows 10 version 1703 and newer, with Shader Model 5.0
91 or newer. Qt requires ID3D12Device2 to be present, hence the requirement
92 for at least version 1703 of Windows 10. The D3D12 device is by default
93 created with specifying a minimum feature level of
94 \c{D3D_FEATURE_LEVEL_11_0}.
95
96 \li Metal 1.2 or newer.
97
98 \li Vulkan 1.0 or newer, optionally utilizing some Vulkan 1.1 level
99 features.
100
101 \li Null, a "dummy" backend that issues no graphics calls at all.
102
103 \endlist
104
105 In order to allow shader code to be written once in Qt applications and
106 libraries, all shaders are expected to be written in a single language
107 which is then compiled into SPIR-V. Versions for various shading language
108 are then generated from that, together with reflection information (inputs,
109 outputs, shader resources). This is then packed into easily and efficiently
110 serializable QShader instances. The compilers and tools to generate such
111 shaders are not part of QRhi and the Qt GUI module, but the core classes
112 for using such shaders, QShader and QShaderDescription, are. The APIs and
113 tools for performing compilation and translation are part of the Qt Shader
114 Tools module.
115
116 See the \l{RHI Window Example} for an introductory example of creating a
117 portable, cross-platform application that performs accelerated 3D rendering
118 onto a QWindow using QRhi.
119
120 \section1 An Impression of the API
121
122 To provide a quick look at the API with a short yet complete example that
123 does not involve window-related setup, the following is a complete,
124 runnable cross-platform application that renders 20 frames off-screen, and
125 then saves the generated images to files after reading back the texture
126 contents from the GPU. For an example that renders on-screen, which then
127 involves setting up a QWindow and a swapchain, refer to the
128 \l{RHI Window Example}.
129
130 For brevity, the initialization of the QRhi is done based on the platform:
131 the sample code here chooses Direct 3D 12 on Windows, Metal on macOS and
132 iOS, and Vulkan otherwise. OpenGL and Direct 3D 11 are never used by this
133 application, but support for those could be introduced with a few
134 additional lines.
135
136 \snippet rhioffscreen/main.cpp 0
137
138 The result of the application is 20 \c PNG images (frame0.png -
139 frame19.png). These contain a rotating triangle with varying opacity over a
140 green background.
141
142 The vertex and fragment shaders are expected to be processed and packaged
143 into \c{.qsb} files. The Vulkan-compatible GLSL source code is the
144 following:
145
146 \e color.vert
147 \snippet rhioffscreen/color.vert 0
148
149 \e color.frag
150 \snippet rhioffscreen/color.frag 0
151
152 To manually compile and transpile these shaders to a number of targets
153 (SPIR-V, HLSL, MSL, GLSL) and generate the \c{.qsb} files the application
154 loads at run time, run \c{qsb --qt6 color.vert -o color.vert.qsb} and
155 \c{qsb --qt6 color.frag -o color.frag.qsb}. Alternatively, the Qt Shader
156 Tools module offers build system integration for CMake, the
157 \c qt_add_shaders() CMake function, that can achieve the same at build time.
158
159 \section1 Security Considerations
160
161 All data consumed by QRhi and related classes such as QShader are considered
162 trusted content.
163
164 \warning Application developers are advised to carefully consider the
165 potential implications before allowing the feeding of user-provided content
166 that is not part of the application and is not under the developers'
167 control. (this includes all vertex/index data, shaders, pipeline and draw
168 call parameters, etc.)
169
170 \section1 Design Fundamentals
171
172 A QRhi cannot be instantiated directly. Instead, use the create()
173 function. Delete the QRhi instance normally to release the graphics device.
174
175 \section2 Resources
176
177 Instances of classes deriving from QRhiResource, such as, QRhiBuffer,
178 QRhiTexture, etc., encapsulate zero, one, or more native graphics
179 resources. Instances of such classes are always created via the \c new
180 functions of the QRhi, such as, newBuffer(), newTexture(),
181 newTextureRenderTarget(), newSwapChain().
182
183 \code
184 QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
185 if (!vbuf->create()) { error(); }
186 // ...
187 delete vbuf;
188 \endcode
189
190 \list
191
192 \li The returned value from functions like newBuffer() is always owned by
193 the caller.
194
195 \li Just creating an instance of a QRhiResource subclass never allocates or
196 initializes any native resources. That is only done when calling the
197 \c create() function of a subclass, for example, QRhiBuffer::create() or
198 QRhiTexture::create().
199
200 \li The exceptions are
201 QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor(),
202 QRhiSwapChain::newCompatibleRenderPassDescriptor(), and
203 QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor(). There is no
204 \c create() operation for these and the returned object is immediately
205 active.
206
207 \li The resource objects themselves are treated as immutable: once a
208 resource has create() called, changing any parameters via the setters, such as,
209 QRhiTexture::setPixelSize(), has no effect, unless the underlying native
210 resource is released and \c create() is called again. See more about resource
211 reuse in the sections below.
212
213 \li The underlying native resources are scheduled for releasing by the
214 QRhiResource destructor, or by calling QRhiResource::destroy(). Backends
215 often queue release requests and defer executing them to an unspecified
216 time, this is hidden from the applications. This way applications do not
217 have to worry about releasing native resources that may still be in use by
218 an in-flight frame.
219
220 \li Note that this does not mean that a QRhiResource can freely be
221 destroy()'ed or deleted within a frame (that is, in a
222 \l{QRhi::beginFrame()}{beginFrame()} - \l{QRhi::endFrame()}{endFrame()}
223 section). As a general rule, all referenced QRhiResource objects must stay
224 unchanged until the frame is submitted by calling
225 \l{QRhi::endFrame()}{endFrame()}. To ease this,
226 QRhiResource::deleteLater() is provided as a convenience.
227
228 \endlist
229
230 \section2 Command buffers and deferred command execution
231
232 Regardless of the design and capabilities of the underlying graphics API,
233 all QRhi backends implement some level of command buffers. No
234 QRhiCommandBuffer function issues any native bind or draw command (such as,
235 \c glDrawElements) directly. Commands are always recorded in a queue,
236 either native or provided by the QRhi backend. The command buffer is
237 submitted, and so execution starts only upon QRhi::endFrame() or
238 QRhi::finish().
239
240 The deferred nature has consequences for some types of objects. For example,
241 writing to a dynamic buffer multiple times within a frame, in case such
242 buffers are backed by host-visible memory, will result in making the
243 results of all writes are visible to all draw calls in the command buffer
244 of the frame, regardless of when the dynamic buffer update was recorded
245 relative to a draw call.
246
247 Furthermore, instances of QRhiResource subclasses must be treated immutable
248 within a frame in which they are referenced in any way. Create
249 all resources upfront, before starting to record commands for the next
250 frame. Reusing a QRhiResource instance within a frame (by calling \c create()
251 then referencing it again in the same \c{beginFrame - endFrame} section)
252 should be avoided as it may lead to unexpected results, depending on the
253 backend.
254
255 As a general rule, all referenced QRhiResource objects must stay valid and
256 unmodified until the frame is submitted by calling
257 \l{QRhi::endFrame()}{endFrame()}. On the other hand, calling
258 \l{QRhiResource::destroy()}{destroy()} or deleting the QRhiResource are
259 always safe once the frame is submitted, regardless of the status of the
260 underlying native resources (which may still be in use by the GPU - but
261 that is taken care of internally).
262
263 Unlike APIs like OpenGL, upload and copy type of commands cannot be mixed
264 with draw commands. The typical renderer will involve a sequence similar to
265 the following:
266
267 \list
268 \li (re)create resources
269 \li begin frame
270 \li record/issue uploads and copies
271 \li start recording a render pass
272 \li record draw calls
273 \li end render pass
274 \li end frame
275 \endlist
276
277 Recording copy type of operations happens via QRhiResourceUpdateBatch. Such
278 operations are committed typically on
279 \l{QRhiCommandBuffer::beginPass()}{beginPass()}.
280
281 When working with legacy rendering engines designed for OpenGL, the
282 migration to QRhi often involves redesigning from having a single \c render
283 step (that performs copies and uploads, clears buffers, and issues draw
284 calls, all mixed together) to a clearly separated, two phase \c prepare -
285 \c render setup where the \c render step only starts a renderpass and
286 records draw calls, while all resource creation and queuing of updates,
287 uploads and copies happens beforehand, in the \c prepare step.
288
289 QRhi does not at the moment allow freely creating and submitting command
290 buffers. This may be lifted in the future to some extent, in particular if
291 compute support is introduced, but the model of well defined
292 \c{frame-start} and \c{frame-end} points, combined with a dedicated,
293 "frame" command buffer, where \c{frame-end} implies presenting, is going to
294 remain the primary way of operating since this is what fits Qt's various UI
295 technologies best.
296
297 \section2 Threading
298
299 A QRhi instance and the associated resources can be created and used on any
300 thread but all usage must be limited to that one single thread. When
301 rendering to multiple QWindows in an application, having a dedicated thread
302 and QRhi instance for each window is often advisable, as this can eliminate
303 issues with unexpected throttling caused by presenting to multiple windows.
304 Conceptually that is then the same as how Qt Quick scene graph's threaded
305 render loop operates when working directly with OpenGL: one thread for each
306 window, one QOpenGLContext for each thread. When moving onto QRhi,
307 QOpenGLContext is replaced by QRhi, making the migration straightforward.
308
309 When it comes to externally created native objects, such as OpenGL contexts
310 passed in via QRhiGles2NativeHandles, it is up to the application to ensure
311 they are not misused by other threads.
312
313 Resources are not shareable between QRhi instances. This is an intentional
314 choice since QRhi hides most queue, command buffer, and resource
315 synchronization related tasks, and provides no API for them. Safe and
316 efficient concurrent use of graphics resources from multiple threads is
317 tied to those concepts, however, and is thus a topic that is currently out
318 of scope, but may be introduced in the future.
319
320 \note The Metal backend requires that an autorelease pool is available on
321 the rendering thread, ideally wrapping each iteration of the render loop.
322 This needs no action from the users of QRhi when rendering on the main
323 (gui) thread, but becomes important when a separate, dedicated render
324 thread is used.
325
326 \section2 Resource synchronization
327
328 QRhi does not expose APIs for resource barriers or image layout
329 transitions. Such synchronization is done implicitly by the backends, where
330 applicable (for example, Vulkan), by tracking resource usage as necessary.
331 Buffer and image barriers are inserted before render or compute passes
332 transparently to the application.
333
334 \note Resources within a render or compute pass are expected to be bound to
335 a single usage during that pass. For example, a buffer can be used as
336 vertex, index, uniform, or storage buffer, but not a combination of them
337 within a single pass. However, it is perfectly fine to use a buffer as a
338 storage buffer in a compute pass, and then as a vertex buffer in a render
339 pass, for example, assuming the buffer declared both usages upon creation.
340
341 \note Textures have this rule relaxed in certain cases, because using two
342 subresources (typically two different mip levels) of the same texture for
343 different access (one for load, one for store) is supported even within the
344 same pass.
345
346 \section2 Resource reuse
347
348 From the user's point of view a QRhiResource is reusable immediately after
349 calling QRhiResource::destroy(). With the exception of swapchains, calling
350 \c create() on an already created object does an implicit \c destroy(). This
351 provides a handy shortcut to reuse a QRhiResource instance with different
352 parameters, with a new native graphics object underneath.
353
354 The importance of reusing the same object lies in the fact that some
355 objects reference other objects: for example, a QRhiShaderResourceBindings
356 can reference QRhiBuffer, QRhiTexture, and QRhiSampler instances. If in a
357 later frame one of these buffers need to be resized or a sampler parameter
358 needs changing, destroying and creating a whole new QRhiBuffer or
359 QRhiSampler would invalidate all references to the old instance. By just
360 changing the appropriate parameters via QRhiBuffer::setSize() or similar
361 and then calling QRhiBuffer::create(), everything works as expected and
362 there is no need to touch the QRhiShaderResourceBindings at all, even
363 though there is a good chance that under the hood the QRhiBuffer is now
364 backed by a whole new native buffer.
365
366 \code
367 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 256);
368 ubuf->create();
369
370 QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings()
371 srb->setBindings({
372 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf)
373 });
374 srb->create();
375
376 // ...
377
378 // now in a later frame we need to grow the buffer to a larger size
379 ubuf->setSize(512);
380 ubuf->create(); // same as ubuf->destroy(); ubuf->create();
381
382 // srb needs no changes whatsoever, any references in it to ubuf
383 // stay valid. When it comes to internal details, such as that
384 // ubuf may now be backed by a completely different native buffer
385 // resource, that is is recognized and handled automatically by the
386 // next setShaderResources().
387 \endcode
388
389 QRhiTextureRenderTarget offers the same contract: calling
390 QRhiCommandBuffer::beginPass() is safe even when one of the render target's
391 associated textures or renderbuffers has been rebuilt (by calling \c
392 create() on it) since the creation of the render target object. This allows
393 the application to resize a texture by setting a new pixel size on the
394 QRhiTexture and calling create(), thus creating a whole new native texture
395 resource underneath, without having to update the QRhiTextureRenderTarget
396 as that will be done implicitly in beginPass().
397
398 \section2 Pooled objects
399
400 In addition to resources, there are pooled objects as well, such as,
401 QRhiResourceUpdateBatch. An instance is retrieved via a \c next function,
402 such as, nextResourceUpdateBatch(). The caller does not own the returned
403 instance in this case. The only valid way of operating here is calling
404 functions on the QRhiResourceUpdateBatch and then passing it to
405 QRhiCommandBuffer::beginPass() or QRhiCommandBuffer::endPass(). These
406 functions take care of returning the batch to the pool. Alternatively, a
407 batch can be "canceled" and returned to the pool without processing by
408 calling QRhiResourceUpdateBatch::release().
409
410 A typical pattern is thus:
411
412 \code
413 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
414 // ...
415 resUpdates->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
416 if (!image.isNull()) {
417 resUpdates->uploadTexture(texture, image);
418 image = QImage();
419 }
420 // ...
421 QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
422 // note the last argument
423 cb->beginPass(swapchain->currentFrameRenderTarget(), clearCol, clearDs, resUpdates);
424 \endcode
425
426 \section2 Swapchain specifics
427
428 QRhiSwapChain features some special semantics due to the peculiar nature of
429 swapchains.
430
431 \list
432
433 \li It has no \c create() but rather a QRhiSwapChain::createOrResize().
434 Repeatedly calling this function is \b not the same as calling
435 QRhiSwapChain::destroy() followed by QRhiSwapChain::createOrResize(). This
436 is because swapchains often have ways to handle the case where buffers need
437 to be resized in a manner that is more efficient than a brute force
438 destroying and recreating from scratch.
439
440 \li An active QRhiSwapChain must be released by calling
441 \l{QRhiSwapChain::destroy()}{destroy()}, or by destroying the object, before
442 the QWindow's underlying QPlatformWindow, and so the associated native
443 window object, is destroyed. It should not be postponed because releasing
444 the swapchain may become problematic (and with some APIs, like Vulkan, is
445 explicitly disallowed) when the native window is not around anymore, for
446 example because the QPlatformWindow got destroyed upon getting a
447 QWindow::close(). Therefore, releasing the swapchain must happen whenever
448 the targeted QWindow sends the
449 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed event. If the event does
450 not arrive before the destruction of the QWindow - this can happen when
451 using QCoreApplication::quit() -, then check QWindow::handle() after the
452 event loop exits and invoke the swapchain release when non-null (meaning
453 the underlying native window is still around).
454
455 \endlist
456
457 \section2 Ownership
458
459 The general rule is no ownership transfer. Creating a QRhi with an already
460 existing graphics device does not mean the QRhi takes ownership of the
461 device object. Similarly, ownership is not given away when a device or
462 texture object is "exported" via QRhi::nativeHandles() or
463 QRhiTexture::nativeTexture(). Most importantly, passing pointers in structs
464 and via setters does not transfer ownership.
465
466 \section1 Troubleshooting and Profiling
467
468 \section2 Error reporting
469
470 Functions such as \l QRhi::create() and the resource classes' \c create()
471 member functions (e.g., \l QRhiBuffer::create()) indicate failure with the
472 return value (\nullptr or
473 \c false, respectively). When working with QShader, \l QShader::fromSerialized()
474 returns an invalid QShader (for which \l{QShader::isValid()}{isValid()} returns
475 \c false) when the data passed to the function cannot be successfully deserialized.
476 Some functions, beginFrame() in particular, may also sometimes report "soft failures",
477 such as \l FrameOpSwapChainOutOfDate, which do not indicate an unrecoverable error,
478 but rather should be seen as a "try again later" response.
479
480 Warnings and errors may get printed at any time to the debug output via
481 qWarning(). It is therefore always advisable to inspect the output of the
482 application.
483
484 Additional debug messages can be enabled via the following logging
485 categories. Messages from these categories are not printed by default
486 unless explicitly enabled via QLoggingCategory or the \c QT_LOGGING_RULES
487 environment variable. For better interoperation with Qt Quick, the
488 environment variable \c{QSG_INFO} also enables these debug prints.
489
490 \list
491 \li \c{qt.rhi.general}
492 \endlist
493
494 Additionally, applications can query the \l{QRhi::backendName()}{QRhi
495 backend name} and
496 \l{QRhi::driverInfo()}{graphics device information} from a successfully
497 initialized QRhi. This can then be printed to the user or stored in the
498 application logs even in production builds, if desired.
499
500 \section2 Investigating rendering problems
501
502 When the rendering results are not as expected, or the application is
503 experiencing problems, always consider checking with the native 3D
504 APIs' debug and validation facilities. QRhi itself features limited error
505 checking since replicating the already existing, vast amount of
506 functionality in the underlying layers is not reasonable.
507
508 \list
509
510 \li For Vulkan, controlling the
511 \l{https://github.com/KhronosGroup/Vulkan-ValidationLayers}{Vulkan
512 Validation Layers} is not in the scope of the QRhi, but rather can be
513 achieved by configuring the \l QVulkanInstance with the appropriate layers.
514 For example, call \c{instance.setLayers({ "VK_LAYER_KHRONOS_validation" });}
515 before invoking \l{QVulkanInstance::create()}{create()} on the QVulkanInstance.
516 (note that this assumes that the validation layers are actually installed
517 and available, e.g. from the Vulkan SDK) By default, QVulkanInstance conveniently
518 redirects the Vulkan debug messages to qDebug, meaning the validation messages get
519 printed just like other Qt warnings.
520
521 \li With Direct 3D 11 and 12, a graphics device with the debug layer
522 enabled can be requested by toggling the \c enableDebugLayer flag in the
523 appropriate \l{QRhiD3D11InitParams}{init params struct}. With Direct 3D 12 the
524 messages are then printed via qDebug, just like the Vulkan validation
525 messages, as long as the debug layer supports message callbacks. Otherwise,
526 and always with Direct 3D 11, the messages appear on the debug output, which
527 is visible in Qt Creator's messages panel or via a tool such as
528 \l{https://learn.microsoft.com/en-us/sysinternals/downloads/debugview}{DebugView}.
529
530 \li For Metal, controlling Metal Validation is outside of QRhi's scope.
531 Rather, to enable validation, run the application with the environment
532 variable \c{METAL_DEVICE_WRAPPER_TYPE=1} set, or run the application within
533 XCode. There may also be further settings and environment variable in modern
534 XCode and macOS versions. See for instance
535 \l{https://developer.apple.com/documentation/metal/diagnosing_metal_programming_issues_early}{this
536 page}.
537
538 \endlist
539
540 \section2 Frame captures and performance profiling
541
542 A Qt application rendering with QRhi to a window while relying on a 3D API
543 under the hood, is, from the windowing and graphics pipeline perspective at
544 least, no different from any other (non-Qt) applications using the same 3D
545 API. This means that tools and practices for debugging and profiling
546 applications involving 3D graphics, such as games, all apply to such a Qt
547 application as well.
548
549 A few examples of tools that can provide insights into the rendering
550 internals of Qt applications that use QRhi, which includes Qt Quick and Qt
551 Quick 3D based projects as well:
552
553 \list
554
555 \li \l{https://renderdoc.org/}{RenderDoc} allows taking frame captures and
556 introspecting the recorded commands and pipeline state on Windows and Linux
557 for applications using OpenGL, Vulkan, D3D11, or D3D12. When trying to
558 figure out why some parts of the 3D scene do not show up as expected,
559 RenderDoc is often a fast and efficient way to check the pipeline stages
560 and the related state and discover the missing or incorrect value. It is
561 also a tool that is actively used when developing Qt itself.
562
563 \li For NVIDIA-based systems,
564 \l{https://developer.nvidia.com/nsight-graphics}{Nsight Graphics} provides
565 a graphics debugger tool on Windows and Linux. In addition to investigating the commands
566 in the frame and the pipeline, the vendor-specific tools allow looking at timings and
567 hardware performance information, which is not something simple frame captures can provide.
568
569 \li For AMD-based systems, the \l{https://gpuopen.com/rgp/}{Radeon GPU
570 Profiler} can be used to gain deeper insights into the application's
571 rendering and its performance.
572
573 \li Overlays showing live performance information can be highly useful as well, and
574 are often preferable to implementing simple frames-per-second counters within the
575 application itself, since they are more reliable and show more information. An example
576 is \l{https://game.intel.com/us/intel-presentmon/}{PresentMon}, which supports
577 graphics hardware from multiple vendors.
578
579 \li As QRhi supports Direct 3D 12, using
580 \l{https://devblogs.microsoft.com/pix/download/}{PIX}, a performance tuning
581 and debugging tool for DirectX 12 games on Windows is an option as well.
582
583 \li On macOS,
584 \l{https://developer.apple.com/documentation/metal/debugging_tools/viewing_your_gpu_workload_with_the_metal_debugger}{the
585 XCode Metal debugger} can be used to take and introspect frame
586 captures, to investigate performance details, and debug shaders. In macOS 13 it is also possible
587 to enable an overlay that displays frame rate and other information for any Metal-based window by
588 setting the environment variable \c{MTL_HUD_ENABLED=1}.
589
590 \endlist
591
592 On mobile and embedded platforms, there may be vendor and platform-specific
593 tools, provided by the GPU or SoC vendor, available to perform performance
594 profiling of application using OpenGL ES or Vulkan.
595
596 When capturing frames, remember that objects and groups of commands can be
597 named via debug markers, as long as \l{QRhi::EnableDebugMarkers}{debug
598 markers were enabled} for the QRhi, and the graphics API in use supports
599 this. To annotate the command stream, call
600 \l{QRhiCommandBuffer::debugMarkBegin()}{debugMarkBegin()},
601 \l{QRhiCommandBuffer::debugMarkEnd()}{debugMarkEnd()} and/or
602 \l{QRhiCommandBuffer::debugMarkMsg()}{debugMarkMsg()}.
603 This can be particularly useful in larger frames with multiple render passes.
604 Resources are named by calling \l{QRhiResource::setName()}{setName()} before create().
605
606 To perform basic timing measurements on the CPU and GPU side within the
607 application, \l QElapsedTimer and
608 \l QRhiCommandBuffer::lastCompletedGpuTime() can be used. The latter is
609 only available with select graphics APIs at the moment and requires opting
610 in via the \l QRhi::EnableTimestamps flag.
611
612 \section2 Resource leak checking
613
614 When destroying a QRhi object without properly destroying all buffers,
615 textures, and other resources created from it, warnings about this are
616 printed to the debug output whenever the application is a debug build, or
617 when the \c QT_RHI_LEAK_CHECK environment variable is set to a non-zero
618 value. This is a simple way to discover design issues around resource
619 handling within the application rendering logic. Note however that some
620 platforms and underlying graphics APIs may perform their own allocation and
621 resource leak detection as well, over which Qt will have no direct control.
622 For example, when using Vulkan, the memory allocator may raise failing
623 assertions in debug builds when resources that own graphics memory
624 allocations are not destroyed before the QRhi. In addition, the Vulkan
625 validation layer, when enabled, will issue warnings about native graphics
626 resources that were not released. Similarly, with Direct 3D warnings may
627 get printed about unreleased COM objects when the application does not
628 destroy the QRhi and its resources in the correct order.
629
630 \sa {RHI Window Example}, QRhiCommandBuffer, QRhiResourceUpdateBatch,
631 QRhiShaderResourceBindings, QShader, QRhiBuffer, QRhiTexture,
632 QRhiRenderBuffer, QRhiSampler, QRhiTextureRenderTarget,
633 QRhiGraphicsPipeline, QRhiComputePipeline, QRhiSwapChain
634 */
635
636/*!
637 \enum QRhi::Implementation
638 Describes which graphics API-specific backend gets used by a QRhi instance.
639
640 \value Null
641 \value Vulkan
642 \value OpenGLES2
643 \value D3D11
644 \value D3D12
645 \value Metal
646 */
647
648/*!
649 \enum QRhi::Flag
650 Describes what special features to enable.
651
652 \value EnableDebugMarkers Enables debug marker groups. Without this frame
653 debugging features like making debug groups and custom resource name
654 visible in external GPU debugging tools will not be available and functions
655 like QRhiCommandBuffer::debugMarkBegin() will become no-ops. Avoid enabling
656 in production builds as it may involve a small performance impact. Has no
657 effect when the QRhi::DebugMarkers feature is not reported as supported.
658
659 \value EnableTimestamps Enables GPU timestamp collection. When not set,
660 QRhiCommandBuffer::lastCompletedGpuTime() always returns 0. Enable this
661 only when needed since there may be a small amount of extra work involved
662 (e.g. timestamp queries), depending on the underlying graphics API. Has no
663 effect when the QRhi::Timestamps feature is not reported as supported.
664
665 \value PreferSoftwareRenderer Indicates that backends should prefer
666 choosing an adapter or physical device that renders in software on the CPU.
667 For example, with Direct3D there is typically a "Basic Render Driver"
668 adapter available with \c{DXGI_ADAPTER_FLAG_SOFTWARE}. Setting this flag
669 requests the backend to choose that adapter over any other, as long as no
670 specific adapter was forced by other backend-specific means. With Vulkan
671 this maps to preferring physical devices with
672 \c{VK_PHYSICAL_DEVICE_TYPE_CPU}. When not available, or when it is not
673 possible to decide if an adapter/device is software-based, this flag is
674 ignored. It may also be ignored with graphics APIs that have no concept and
675 means of enumerating adapters/devices.
676
677 \value EnablePipelineCacheDataSave Enables retrieving the pipeline cache
678 contents, where applicable. When not set, pipelineCacheData() will return
679 an empty blob always. With backends where retrieving and restoring the
680 pipeline cache contents is not supported, the flag has no effect and the
681 serialized cache data is always empty. The flag provides an opt-in
682 mechanism because the cost of maintaining the related data structures is
683 not insignificant with some backends. With Vulkan this feature maps
684 directly to VkPipelineCache, vkGetPipelineCacheData and
685 VkPipelineCacheCreateInfo::pInitialData. With Direct3D 11 there is no real
686 pipline cache, but the results of HLSL->DXBC compilations are stored and
687 can be serialized/deserialized via this mechanism. This allows skipping the
688 time consuming D3DCompile() in future runs of the applications for shaders
689 that come with HLSL source instead of offline pre-compiled bytecode. This
690 can provide a huge boost in startup and load times, if there is a lot of
691 HLSL source compilation happening. With OpenGL the "pipeline cache" is
692 simulated by retrieving and loading shader program binaries (if supported
693 by the driver). With OpenGL there are additional, disk-based caching
694 mechanisms for shader/program binaries provided by Qt. Writing to those may
695 get disabled whenever this flag is set since storing program binaries to
696 multiple caches is not sensible.
697
698 \value SuppressSmokeTestWarnings Indicates that, with backends where this
699 is relevant, certain, non-fatal QRhi::create() failures should not
700 produce qWarning() calls. For example, with D3D11, passing this flag
701 makes a number of warning messages (that appear due to QRhi::create()
702 failing) to become categorized debug prints instead under the commonly used
703 \c{qt.rhi.general} logging category. This can be used by engines, such as
704 Qt Quick, that feature fallback logic, i.e. they retry calling create()
705 with a different set of flags (such as, \l PreferSoftwareRenderer), in order
706 to hide the unconditional warnings from the output that would be printed
707 when the first create() attempt had failed.
708 */
709
710/*!
711 \enum QRhi::FrameOpResult
712 Describes the result of operations that can have a soft failure.
713
714 \value FrameOpSuccess Success
715
716 \value FrameOpError Unspecified error
717
718 \value FrameOpSwapChainOutOfDate The swapchain is in an inconsistent state
719 internally. This can be recoverable by attempting to repeat the operation
720 (such as, beginFrame()) later.
721
722 \value FrameOpDeviceLost The graphics device was lost. This can be
723 recoverable by attempting to repeat the operation (such as, beginFrame())
724 after releasing and reinitializing all objects backed by native graphics
725 resources. See isDeviceLost().
726 */
727
728/*!
729 \enum QRhi::Feature
730 Flag values to indicate what features are supported by the backend currently in use.
731
732 \value MultisampleTexture Indicates that textures with a sample count larger
733 than 1 are supported. In practice this feature will be unsupported with
734 OpenGL ES versions older than 3.1, and OpenGL older than 3.0.
735
736 \value MultisampleRenderBuffer Indicates that renderbuffers with a sample
737 count larger than 1 are supported. In practice this feature will be
738 unsupported with OpenGL ES 2.0, and may also be unsupported with OpenGL 2.x
739 unless the relevant extensions are present.
740
741 \value DebugMarkers Indicates that debug marker groups (and so
742 QRhiCommandBuffer::debugMarkBegin()) are supported.
743
744 \value Timestamps Indicates that command buffer timestamps are supported.
745 Relevant for QRhiCommandBuffer::lastCompletedGpuTime(). This can be
746 expected to be supported on Metal, Vulkan, Direct 3D 11 and 12, and OpenGL
747 contexts of version 3.3 or newer. However, with some of these APIs support
748 for timestamp queries is technically optional, and therefore it cannot be
749 guaranteed that this feature is always supported with every implementation
750 of them.
751
752 \value Instancing Indicates that instanced drawing is supported. In
753 practice this feature will be unsupported with OpenGL ES 2.0 and OpenGL
754 3.2 or older.
755
756 \value CustomInstanceStepRate Indicates that instance step rates other
757 than 1 are supported. In practice this feature will always be unsupported
758 with OpenGL. In addition, running with Vulkan 1.0 without
759 VK_EXT_vertex_attribute_divisor will also lead to reporting false for this
760 feature.
761
762 \value PrimitiveRestart Indicates that restarting the assembly of
763 primitives when encountering an index value of 0xFFFF
764 (\l{QRhiCommandBuffer::IndexUInt16}{IndexUInt16}) or 0xFFFFFFFF
765 (\l{QRhiCommandBuffer::IndexUInt32}{IndexUInt32}) is enabled, for certain
766 primitive topologies at least. QRhi will try to enable this with all
767 backends, but in some cases it will not be supported. Dynamically
768 controlling primitive restart is not possible since with some APIs
769 primitive restart with a fixed index is always on. Applications must assume
770 that whenever this feature is reported as supported, the above mentioned
771 index values \c may be treated specially, depending on the topology. The
772 only two topologies where primitive restart is guaranteed to behave
773 identically across backends, as long as this feature is reported as
774 supported, are \l{QRhiGraphicsPipeline::LineStrip}{LineStrip} and
775 \l{QRhiGraphicsPipeline::TriangleStrip}{TriangleStrip}.
776
777 \value NonDynamicUniformBuffers Indicates that creating buffers with the
778 usage \l{QRhiBuffer::UniformBuffer}{UniformBuffer} and the types
779 \l{QRhiBuffer::Immutable}{Immutable} or \l{QRhiBuffer::Static}{Static} is
780 supported. When reported as unsupported, uniform (constant) buffers must be
781 created as \l{QRhiBuffer::Dynamic}{Dynamic}. (which is recommended
782 regardless)
783
784 \value NonFourAlignedEffectiveIndexBufferOffset Indicates that effective
785 index buffer offsets (\c{indexOffset + firstIndex * indexComponentSize})
786 that are not 4 byte aligned are supported. When not supported, attempting
787 to issue a \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} with a
788 non-aligned effective offset may lead to unspecified behavior. Relevant in
789 particular for Metal, where this will be reported as unsupported.
790
791 \value NPOTTextureRepeat Indicates that the
792 \l{QRhiSampler::Repeat}{Repeat} wrap mode and mipmap filtering modes are
793 supported for textures with a non-power-of-two size. In practice this can
794 only be false with OpenGL ES 2.0 implementations without
795 \c{GL_OES_texture_npot}.
796
797 \value RedOrAlpha8IsRed Indicates that the
798 \l{QRhiTexture::RED_OR_ALPHA8}{RED_OR_ALPHA8} format maps to a one
799 component 8-bit \c red format. This is the case for all backends except
800 OpenGL when using either OpenGL ES or a non-core profile context. There
801 \c{GL_ALPHA}, a one component 8-bit \c alpha format, is used
802 instead. Using the special texture format allows having a single code
803 path for creating textures, leaving it up to the backend to decide the
804 actual format, while the feature flag can be used to pick the
805 appropriate shader variant for sampling the texture.
806
807 \value ElementIndexUint Indicates that 32-bit unsigned integer elements are
808 supported in the index buffer. In practice this is true everywhere except
809 when running on plain OpenGL ES 2.0 implementations without the necessary
810 extension. When false, only 16-bit unsigned elements are supported in the
811 index buffer.
812
813 \value Compute Indicates that compute shaders, image load/store, and
814 storage buffers are supported. OpenGL older than 4.3 and OpenGL ES older
815 than 3.1 have no compute support.
816
817 \value WideLines Indicates that lines with a width other than 1 are
818 supported. When reported as not supported, the line width set on the
819 graphics pipeline state is ignored. This can always be false with some
820 backends (D3D11, D3D12, Metal). With Vulkan, the value depends on the
821 implementation. With OpenGL, wide lines are not supported in core profile
822 contexts.
823
824 \value VertexShaderPointSize Indicates that the size of rasterized points
825 set via \c{gl_PointSize} in the vertex shader is taken into account. When
826 reported as not supported, drawing points with a size other than 1 is not
827 supported. Setting \c{gl_PointSize} in the shader is still valid then, but
828 is ignored. (for example, when generating HLSL, the assignment is silently
829 dropped from the generated code) Note that some APIs (Metal, Vulkan)
830 require the point size to be set in the shader explicitly whenever drawing
831 points, even when the size is 1, as they do not automatically default to 1.
832
833 \value BaseVertex Indicates that
834 \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} supports the \c
835 vertexOffset argument. When reported as not supported, the vertexOffset
836 value in an indexed draw is ignored. In practice this feature will be
837 unsupported with OpenGL and OpenGL ES versions lower than 3.2, and with
838 Metal on older iOS devices, including the iOS Simulator.
839
840 \value BaseInstance Indicates that instanced draw commands support the \c
841 firstInstance argument. When reported as not supported, the firstInstance
842 value is ignored and the instance ID starts from 0. In practice this feature
843 will be unsupported with Metal on older iOS devices, including the iOS
844 Simulator, and with OpenGL ES, which has no support for draw calls with a
845 base instance at all. With OpenGL it needs version 4.2 or newer, or
846 \c GL_ARB_base_instance. Applications relying on a non-zero base instance
847 should be aware of the InstanceIndexIncludesBaseInstance feature as well.
848
849 \value TriangleFanTopology Indicates that QRhiGraphicsPipeline::setTopology()
850 supports QRhiGraphicsPipeline::TriangleFan. In practice this feature will be
851 unsupported with Metal and Direct 3D 11/12.
852
853 \value ReadBackNonUniformBuffer Indicates that
854 \l{QRhiResourceUpdateBatch::readBackBuffer()}{reading buffer contents} is
855 supported for QRhiBuffer instances with a usage different than
856 UniformBuffer. In practice this feature will be unsupported with OpenGL ES
857 2.0.
858
859 \value ReadBackNonBaseMipLevel Indicates that specifying a mip level other
860 than 0 is supported when reading back texture contents. When not supported,
861 specifying a non-zero level in QRhiReadbackDescription leads to returning
862 an all-zero image. In practice this feature will be unsupported with OpenGL
863 ES 2.0.
864
865 \value TexelFetch Indicates that texelFetch() and textureLod() are available
866 in shaders. In practice this will be reported as unsupported with OpenGL ES
867 2.0 and OpenGL 2.x contexts, because GLSL 100 es and versions before 130 do
868 not support these functions.
869
870 \value RenderToNonBaseMipLevel Indicates that specifying a mip level other
871 than 0 is supported when creating a QRhiTextureRenderTarget with a
872 QRhiTexture as its color attachment. When not supported, create() will fail
873 whenever the target mip level is not zero. In practice this feature will be
874 unsupported with OpenGL ES 2.0.
875
876 \value IntAttributes Indicates that specifying input attributes with
877 signed and unsigned integer types for a shader pipeline is supported. When
878 not supported,
879 \l{QRhiGraphicsPipeline::create()}{QRhiGraphicsPipeline::create()} will
880 succeed but show a warning message and the values of the target attributes
881 will be broken. In practice this feature will be unsupported with OpenGL ES
882 2.0 and OpenGL 2.x.
883
884 \value ScreenSpaceDerivatives Indicates that functions such as dFdx(),
885 dFdy(), and fwidth() are supported in shaders. In practice this feature will
886 be unsupported with OpenGL ES 2.0 without the GL_OES_standard_derivatives
887 extension.
888
889 \value ReadBackAnyTextureFormat Indicates that reading back texture
890 contents can be expected to work for any QRhiTexture::Format. Backends
891 other than OpenGL can be expected to return true for this feature. When
892 reported as false, which will typically happen with OpenGL, only the
893 formats QRhiTexture::RGBA8 and QRhiTexture::BGRA8 are guaranteed to be
894 supported for readbacks. In addition, with OpenGL, but not OpenGL ES,
895 reading back the 1 byte per component formats QRhiTexture::R8 and
896 QRhiTexture::RED_OR_ALPHA8 are supported as well. Reading back floating
897 point formats QRhiTexture::RGBA16F and RGBA32F may work too with OpenGL, as
898 long as the implementation provides support for these, but QRhi can give no
899 guarantees, as indicated by this flag.
900
901 \value PipelineCacheDataLoadSave Indicates that the pipelineCacheData() and
902 setPipelineCacheData() functions are functional. When not supported, the
903 functions will not perform any action, the retrieved blob is always empty,
904 and thus no benefits can be expected from retrieving and, during a
905 subsequent run of the application, reloading the pipeline cache content.
906
907 \value ImageDataStride Indicates that specifying a custom stride (row
908 length) for raw image data in texture uploads is supported. When not
909 supported (which can happen when the underlying API is OpenGL ES 2.0 without
910 support for GL_UNPACK_ROW_LENGTH),
911 QRhiTextureSubresourceUploadDescription::setDataStride() must not be used.
912
913 \value RenderBufferImport Indicates that QRhiRenderBuffer::createFrom() is
914 supported. For most graphics APIs this is not sensible because
915 QRhiRenderBuffer encapsulates texture objects internally, just like
916 QRhiTexture. With OpenGL however, renderbuffer object exist as a separate
917 object type in the API, and in certain environments (for example, where one
918 may want to associated a renderbuffer object with an EGLImage object) it is
919 important to allow wrapping an existing OpenGL renderbuffer object with a
920 QRhiRenderBuffer.
921
922 \value ThreeDimensionalTextures Indicates that 3D textures are supported.
923 In practice this feature will be unsupported with OpenGL and OpenGL ES
924 versions lower than 3.0.
925
926 \value RenderTo3DTextureSlice Indicates that rendering to a slice in a 3D
927 texture is supported. This can be unsupported with Vulkan 1.0 due to
928 relying on VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT which is a Vulkan 1.1
929 feature.
930
931 \value TextureArrays Indicates that texture arrays are supported and
932 QRhi::newTextureArray() is functional. Note that even when texture arrays
933 are not supported, arrays of textures are still available as those are two
934 independent features.
935
936 \value Tessellation Indicates that the tessellation control and evaluation
937 stages are supported. When reported as supported, the topology of a
938 QRhiGraphicsPipeline can be set to
939 \l{QRhiGraphicsPipeline::Patches}{Patches}, the number of control points
940 can be set via
941 \l{QRhiGraphicsPipeline::setPatchControlPointCount()}{setPatchControlPointCount()},
942 and shaders for tessellation control and evaluation can be specified in the
943 QRhiShaderStage list. Tessellation shaders have portability issues between
944 APIs (for example, translating GLSL/SPIR-V to HLSL is problematic due to
945 the way hull shaders are structured, whereas Metal uses a somewhat
946 different tessellation pipeline than others), and therefore unexpected
947 issues may still arise, even though basic functionality is implemented
948 across all the underlying APIs. For Direct 3D in particular, handwritten
949 HLSL hull and domain shaders must be injected into each QShader for the
950 tessellation control and evaluation stages, respectively, since qsb cannot
951 generate these from SPIR-V. Note that isoline tessellation should be
952 avoided as it will not be supported by all backends. The maximum patch
953 control point count portable between backends is 32.
954
955 \value GeometryShader Indicates that the geometry shader stage is supported.
956 When supported, a geometry shader can be specified in the QRhiShaderStage
957 list. Geometry Shaders are considered an experimental feature in QRhi and
958 can only be expected to be supported with Vulkan, Direct 3D 11 and 12,
959 OpenGL (3.2+) and OpenGL ES (3.2+), assuming the implementation reports it
960 as supported at run time. Starting with Qt 6.11 geometry shaders are
961 automatically translated to HLSL, and therefore no injection of handwritten
962 HLSL geometry shaders is necessary anymore (but note that gl_in and
963 expressions such as gl_in[0].gl_Position are not supported; rather, pass the
964 position as an output variable from the vertex shader). Geometry shaders are
965 not supported with Metal.
966
967 \value TextureArrayRange Indicates that for
968 \l{QRhi::newTextureArray()}{texture arrays} it is possible to specify a
969 range that is exposed to the shaders. Normally all array layers are exposed
970 and it is up to the shader to select the layer (via the third coordinate
971 passed to texture() when sampling the \c sampler2DArray). When supported,
972 calling QRhiTexture::setArrayRangeStart() and
973 QRhiTexture::setArrayRangeLength() before
974 \l{QRhiTexture::create()}{building} or
975 \l{QRhiTexture::createFrom()}{importing} the native texture has an effect,
976 and leads to selecting only the specified range from the array. This will
977 be necessary in special cases, such as when working with accelerated video
978 decoding and Direct 3D 11, because a texture array with both
979 \c{D3D11_BIND_DECODER} and \c{D3D11_BIND_SHADER_RESOURCE} on it is only
980 usable as a shader resource if a single array layer is selected. Note that
981 all this is applicable only when the texture is used as a
982 QRhiShaderResourceBinding::SampledTexture or
983 QRhiShaderResourceBinding::Texture shader resource, and is not compatible
984 with image load/store. This feature is only available with some backends as
985 it does not map well to all graphics APIs, and it is only meant to provide
986 support for special cases anyhow. In practice the feature can be expected to
987 be supported with Direct3D 11/12 and Vulkan.
988
989 \value NonFillPolygonMode Indicates that setting a PolygonMode other than
990 the default Fill is supported for QRhiGraphicsPipeline. A common use case
991 for changing the mode to Line is to get wireframe rendering. This however
992 is not available as a core OpenGL ES feature, and is optional with Vulkan
993 as well as some mobile GPUs may not offer the feature.
994
995 \value OneDimensionalTextures Indicates that 1D textures are supported.
996 In practice this feature will be unsupported on OpenGL ES.
997
998 \value OneDimensionalTextureMipmaps Indicates that generating 1D texture
999 mipmaps is supported. In practice this feature will be unsupported on
1000 backends that do not report support for
1001 \l{OneDimensionalTextures}, Metal, and Direct 3D 12.
1002
1003 \value HalfAttributes Indicates that specifying input attributes with half
1004 precision (16bit) floating point types for a shader pipeline is supported.
1005 When not supported,
1006 \l{QRhiGraphicsPipeline::create()}{QRhiGraphicsPipeline::create()} will
1007 succeed but show a warning message and the values of the target attributes
1008 will be broken. In practice this feature will be unsupported in some OpenGL
1009 ES 2.0 and OpenGL 2.x
1010 implementations. Note that while Direct3D 11/12 does support half precision
1011 input attributes, it does not support the half3 type. The D3D backends pass
1012 half3 attributes as half4. To ensure cross platform compatibility, half3
1013 inputs should be padded to 8 bytes.
1014
1015 \value RenderToOneDimensionalTexture Indicates that 1D texture render
1016 targets are supported. In practice this feature will be unsupported on
1017 backends that do not report support for
1018 \l{OneDimensionalTextures}, and Metal.
1019
1020 \value ThreeDimensionalTextureMipmaps Indicates that generating 3D texture
1021 mipmaps is supported. This is typically supported with all backends starting
1022 with Qt 6.10.
1023
1024 \value MultiView Indicates that multiview, see e.g.
1025 \l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_multiview.html}{VK_KHR_multiview}
1026 is supported. With OpenGL ES 2.0, Direct 3D 11, and OpenGL (ES)
1027 implementations without \c{GL_OVR_multiview2} this feature will not be
1028 supported. With Vulkan 1.1 and newer, and Direct 3D 12 multiview is
1029 typically supported. When reported as supported, creating a
1030 QRhiTextureRenderTarget with a QRhiColorAttachment that references a texture
1031 array and has \l{QRhiColorAttachment::setMultiViewCount()}{multiViewCount}
1032 set enables recording a render pass that uses multiview rendering. In addition,
1033 any QRhiGraphicsPipeline used in that render pass must have
1034 \l{QRhiGraphicsPipeline::setMultiViewCount()}{the same view count set}. Note that
1035 multiview is only available in combination with 2D texture arrays. It cannot
1036 be used to optimize the rendering into individual textures (e.g. two, for
1037 the left and right eyes). Rather, the target of a multiview render pass is
1038 always a texture array, automatically rendering to the layer (array element)
1039 corresponding to each view. Therefore this feature implies \l TextureArrays
1040 as well. Multiview rendering is not supported in combination with
1041 tessellation or geometry shaders. See QRhiColorAttachment::setMultiViewCount()
1042 for further details on multiview rendering. This enum value has been introduced in Qt 6.7.
1043
1044 \value TextureViewFormat Indicates that setting a
1045 \l{QRhiTexture::setWriteViewFormat()}{view format} on a QRhiTexture is
1046 effective. When reported as supported, setting the read (sampling) or write
1047 (render target / image load-store) view mode changes the texture's viewing
1048 format. When unsupported, setting a view format has no effect. Note that Qt
1049 has no knowledge or control over format compatibility or resource view rules
1050 in the underlying 3D API and its implementation. Passing in unsuitable,
1051 incompatible formats may lead to errors and unspecified behavior. This is
1052 provided mainly to allow "casting" rendering into a texture created with an
1053 sRGB format to non-sRGB to avoid the unwanted linear->sRGB conversion on
1054 shader writes. Other types of casting may or may not be functional,
1055 depending on the underlying API. Currently implemented for Vulkan and Direct
1056 3D 12. With D3D12 the feature is available only if
1057 \c CastingFullyTypedFormatSupported is supported, see
1058 \l{https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html} (and
1059 note that QRhi always uses fully typed formats for textures.) This enum
1060 value has been introduced in Qt 6.8.
1061
1062 \value ResolveDepthStencil Indicates that resolving a multisample depth or
1063 depth-stencil texture is supported. Otherwise,
1064 \l{QRhiTextureRenderTargetDescription::setDepthResolveTexture()}{setting a
1065 depth resolve texture} is not functional and must be avoided. Direct 3D 11
1066 and 12 have no support for resolving depth/depth-stencil formats, and
1067 therefore this feature will never be supported with those. Vulkan 1.0 has no
1068 API to request resolving a depth-stencil attachment. Therefore, with Vulkan
1069 this feature will only be supported with Vulkan 1.2 and up, and on 1.1
1070 implementations with the appropriate extensions present. This feature is
1071 provided for the rare case when resolving into a non-multisample depth
1072 texture becomes necessary, for example when rendering into an
1073 OpenXR-provided depth texture (XR_KHR_composition_layer_depth). This enum
1074 value has been introduced in Qt 6.8.
1075
1076 \value VariableRateShading Indicates that per-draw (per-pipeline) variable
1077 rate shading is supported. When reported as supported, \l
1078 QRhiCommandBuffer::setShadingRate() is functional and has an effect for
1079 QRhiGraphicsPipeline objects that declared \l
1080 QRhiGraphicsPipeline::UsesShadingRate in their flags. Call \l
1081 QRhi::supportedShadingRates() to check which rates are supported. (1x1 is
1082 always supported, other typical values are 2x2, 1x2, 2x1, 2x4, 4x2, 4x4).
1083 This feature can be expected to be supported with Direct 3D 12 and Vulkan,
1084 assuming the implementation and GPU used at run time supports VRS. This enum
1085 value has been introduced in Qt 6.9.
1086
1087 \value VariableRateShadingMap Indicates that image-based specification of
1088 the shading rate is possible. The "image" is not necessarily a texture, it
1089 may be a native 3D API object, depending on the underlying backend and
1090 graphics API at run time. In practice this feature can be expected to be
1091 supported with Direct 3D 12, Vulkan, and Metal, assuming the GPU is modern
1092 enough to support VRS. To check if D3D12/Vulkan-style image-based VRS is
1093 supported, use VariableRateShadingMapWithTexture instead. When this feature
1094 is reported as supported, there are two possibilities: when
1095 VariableRateShadingMapWithTexture is also true, then QRhiShadingRateMap
1096 consumes QRhiTexture objects via the createFrom() overload taking a
1097 QRhiTexture argument. When VariableRateShadingMapWithTexture is false, then
1098 QRhiShadingRateMap consumes some other type of native objects, for example
1099 an MTLRasterizationRateMap in case of Metal. Use the createFrom() overload
1100 taking a NativeShadingRateMap in this case. This enum value has been
1101 introduced in Qt 6.9.
1102
1103 \value VariableRateShadingMapWithTexture Indicates that image-based
1104 specification of the shading rate is supported via regular textures. In
1105 practice this may be supported with Direct 3D 12 and Vulkan. This enum value
1106 has been introduced in Qt 6.9.
1107
1108 \value PerRenderTargetBlending Indicates that per rendertarget blending is
1109 supported i.e. different render targets in MRT framebuffer can have different
1110 blending modes. In practice this can be expected to be supported everywhere
1111 except OpenGL ES, where it is only available with GLES 3.2 implementations.
1112 This enum value has been introduced in Qt 6.9.
1113
1114 \value SampleVariables Indicates that gl_SampleID, gl_SamplePosition,
1115 gl_SampleMaskIn and gl_SampleMask variables are available in fragment shaders.
1116 In practice this can be expected to be supported everywhere except OpenGL ES,
1117 where it is only available with GLES 3.2 implementations.
1118 This enum value has been introduced in Qt 6.9.
1119
1120 \value InstanceIndexIncludesBaseInstance Indicates that \c gl_InstanceIndex
1121 includes the base instance (the \c firstInstance argument in draw calls) in
1122 its value. When this feature is unsupported, but BaseInstance is, it
1123 indicates that \c gl_InstanceIndex always starts at 0, not the base value.
1124 In practice this will be the case for Direct 3D 11 and 12 at the moment.
1125 With Vulkan and Metal this feature is expected to be reported as supported
1126 always. This enum value has been introduced in Qt 6.11.
1127
1128 \value [since 6.11] DepthClamp Indicates that enabling depth clamping is
1129 supported. When reported as unsupported, which will be the case with OpenGL
1130 ES, OpenGL versions before 3.2 without the relevant extension present, and
1131 Metal on the iOS Simulator, calling \l{QRhiGraphicsPipeline::setDepthClamp()}
1132 with an argument of \c true has no effect.
1133
1134 \value [since 6.12] DrawIndirect Indicates that the
1135 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
1136 and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}
1137 functions are available.
1138 In practice this can be expected to be supported everywhere except on
1139 OpenGL ES < 3.1.
1140
1141 \value [since 6.12] DrawIndirectMulti Indicates that a drawCount > 1 is natively
1142 supported by the backend in \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
1143 and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}.
1144 Otherwise, multiple draw calls are issued on the CPU by the RHI.
1145 In practice this can be expected to be supported on Vulkan 1.1+, OpenGL
1146 4.3+, D3D12, and Metal.
1147
1148 \value [since 6.12] ShaderDrawParameters Indicates that the \c{gl_BaseInstance},
1149 \c{gl_BaseVertex} and \c{gl_DrawID} built-in variables are available in shaders.
1150 In practice this can be expected to be supported on Vulkan 1.1+ and with desktop OpenGL
1151 4.6 or \c{GL_ARB_shader_draw_parameters}.
1152
1153 \value [since 6.13] DispatchIndirect Indicates that the
1154 \l{QRhiCommandBuffer::dispatchIndirect()}{dispatchIndirect()} function is
1155 available, allowing compute work group counts to be sourced from a
1156 \l QRhiBuffer at execution time. In practice this can be expected to be
1157 supported wherever the \l Compute feature is reported as supported, that is,
1158 on Vulkan, OpenGL 4.3+ / OpenGL ES 3.1+, Direct3D 11/12, and Metal.
1159
1160 \value [since 6.13] DrawIndirectCount Indicates that the
1161 \l{QRhiCommandBuffer::drawIndirectCount()}{drawIndirectCount()} and
1162 \l{QRhiCommandBuffer::drawIndexedIndirectCount()}{drawIndexedIndirectCount()}
1163 functions are available. These are GPU-driven multi-draw variants where the
1164 actual draw count is read from a buffer at execution time, capped to a
1165 CPU-supplied \c maxDrawCount. In practice this can be expected to be
1166 supported with Vulkan 1.2 and newer, when both the \c drawIndirectCount and
1167 \c multiDrawIndirect device features are present, with OpenGL 4.6 or when
1168 \c GL_ARB_indirect_parameters is available, with Direct3D 12, and with Metal
1169 on devices supporting Metal 3 and indirect command buffers. Direct3D 11 does
1170 not expose an equivalent entry point. Note that with Vulkan the two device
1171 features are queried from the physical device. When importing an existing
1172 VkDevice, the application must make sure the features were enabled when that
1173 device was created, because this cannot be queried afterwards. With Metal
1174 there is a further requirement that this feature flag cannot reflect: the
1175 graphics pipeline must have
1176 \l{QRhiGraphicsPipeline::UsesIndirectDraws}{UsesIndirectDraws} set, without
1177 which the draw is skipped with a warning.
1178 */
1179
1180/*!
1181 \enum QRhi::BeginFrameFlag
1182 Flag values for QRhi::beginFrame()
1183 */
1184
1185/*!
1186 \enum QRhi::EndFrameFlag
1187 Flag values for QRhi::endFrame()
1188
1189 \value SkipPresent Specifies that no present command is to be queued or no
1190 swapBuffers call is to be made. This way no image is presented. Generating
1191 multiple frames with all having this flag set is not recommended (except,
1192 for example, for benchmarking purposes - but keep in mind that backends may
1193 behave differently when it comes to waiting for command completion without
1194 presenting so the results are not comparable between them)
1195 */
1196
1197/*!
1198 \enum QRhi::ResourceLimit
1199 Describes the resource limit to query.
1200
1201 \value TextureSizeMin Minimum texture width and height. This is typically
1202 1. The minimum texture size is handled gracefully, meaning attempting to
1203 create a texture with an empty size will instead create a texture with the
1204 minimum size.
1205
1206 \value TextureSizeMax Maximum texture width and height. This depends on the
1207 graphics API and sometimes the platform or implementation as well.
1208 Typically the value is in the range 4096 - 16384. Attempting to create
1209 textures larger than this is expected to fail.
1210
1211 \value MaxColorAttachments The maximum number of color attachments for a
1212 QRhiTextureRenderTarget, in case multiple render targets are supported. When
1213 MRT is not supported, the value is 1. Otherwise this is typically 8, but
1214 watch out for the fact that OpenGL only mandates 4 as the minimum, and that
1215 is what some OpenGL ES implementations provide.
1216
1217 \value FramesInFlight The number of frames the backend may keep "in
1218 flight": with backends like Vulkan or Metal, it is the responsibility of
1219 QRhi to block whenever starting a new frame and finding the CPU is already
1220 \c{N - 1} frames ahead of the GPU (because the command buffer submitted in
1221 frame no. \c{current} - \c{N} has not yet completed). The value N is what
1222 is returned from here, and is typically 2. This can be relevant to
1223 applications that integrate rendering done directly with the graphics API,
1224 as such rendering code may want to perform double (if the value is 2)
1225 buffering for resources, such as, buffers, similarly to the QRhi backends
1226 themselves. The current frame slot index (a value running 0, 1, .., N-1,
1227 then wrapping around) is retrievable from QRhi::currentFrameSlot(). The
1228 value is 1 for backends where the graphics API offers no such low level
1229 control over the command submission process. Note that pipelining may still
1230 happen even when this value is 1 (some backends, such as D3D11, are
1231 designed to attempt to enable this, for instance, by using an update
1232 strategy for uniform buffers that does not stall the pipeline), but that is
1233 then not controlled by QRhi and so not reflected here in the API.
1234
1235 \value MaxAsyncReadbackFrames The number of \l{QRhi::endFrame()}{submitted}
1236 frames (including the one that contains the readback) after which an
1237 asynchronous texture or buffer readback is guaranteed to complete upon
1238 \l{QRhi::beginFrame()}{starting a new frame}.
1239
1240 \value MaxThreadGroupsPerDimension The maximum number of compute
1241 work/thread groups that can be dispatched. Effectively the maximum value
1242 for the arguments of QRhiCommandBuffer::dispatch(). Typically 65535.
1243
1244 \value MaxThreadsPerThreadGroup The maximum number of invocations in a
1245 single local work group, or in other terminology, the maximum number of
1246 threads in a thread group. Effectively the maximum value for the product of
1247 \c local_size_x, \c local_size_y, and \c local_size_z in the compute
1248 shader. Typical values are 128, 256, 512, 1024, or 1536. Watch out that
1249 both OpenGL ES and Vulkan specify only 128 as the minimum required limit
1250 for implementations. While uncommon for Vulkan, some OpenGL ES 3.1
1251 implementations for mobile/embedded devices only support the spec-mandated
1252 minimum value.
1253
1254 \value MaxThreadGroupX The maximum size of a work/thread group in the X
1255 dimension. Effectively the maximum value of \c local_size_x in the compute
1256 shader. Typically 256 or 1024.
1257
1258 \value MaxThreadGroupY The maximum size of a work/thread group in the Y
1259 dimension. Effectively the maximum value of \c local_size_y in the compute
1260 shader. Typically 256 or 1024.
1261
1262 \value MaxThreadGroupZ The maximum size of a work/thread group in the Z
1263 dimension. Effectively the maximum value of \c local_size_z in the compute
1264 shader. Typically 64 or 256.
1265
1266 \value TextureArraySizeMax Maximum texture array size. Typically in range
1267 256 - 2048. Attempting to \l{QRhi::newTextureArray()}{create a texture
1268 array} with more elements will likely fail.
1269
1270 \value MaxUniformBufferRange The number of bytes that can be exposed from a
1271 uniform buffer to the shaders at once. On OpenGL ES 2.0 and 3.0
1272 implementations this may be as low as 3584 bytes (224 four component, 32
1273 bits per component vectors). Elsewhere the value is typically 16384 (1024
1274 vec4s) or 65536 (4096 vec4s).
1275
1276 \value MaxVertexInputs The number of input attributes to the vertex shader.
1277 The location in a QRhiVertexInputAttribute must be in range \c{[0,
1278 MaxVertexInputs-1]}. The value may be as low as 8 with OpenGL ES 2.0.
1279 Elsewhere, typical values are 16, 31, or 32.
1280
1281 \value MaxVertexOutputs The maximum number of outputs (4 component vector
1282 \c out variables) from the vertex shader. The value may be as low as 8 with
1283 OpenGL ES 2.0, and 15 with OpenGL ES 3.0 and some Metal devices. Elsewhere,
1284 a typical value is 32.
1285
1286 \value ShadingRateImageTileSize The tile size for shading rate textures. 0
1287 if the QRhi::VariableRateShadingMapWithTexture feature is not supported.
1288 Otherwise a value such as 16, indicating, for example, a tile size of 16x16.
1289 Each byte in the (R8UI) shading rate texture defines then the shading rate
1290 for a tile of 16x16 pixels. See \l QRhiShadingRateMap for details.
1291
1292 \value [since 6.13] MaxVertexStorageBuffers The maximum number of
1293 storage buffers that can be bound for reading (bufferLoad) in the
1294 vertex stage. Can legitimately be 0: OpenGL ES makes vertex-stage
1295 storage blocks optional even on 3.1 and newer, and many mobile
1296 drivers report 0 while supporting them via Vulkan on the same GPU;
1297 Direct 3D 11 has no vertex-stage storage buffer support at all.
1298 Clients reading storage buffers in the vertex shader must therefore
1299 check this even when QRhi::Compute is supported. Write access can be
1300 more restricted than this value suggests: with Vulkan it additionally
1301 requires the vertexPipelineStoresAndAtomics device feature, and with
1302 Direct 3D 12 unordered access has lower, resource-binding-tier
1303 dependent limits. With Metal the value is the size of the buffer
1304 argument table, which is shared with vertex inputs and uniform
1305 buffers, so the full count is not available in combination with them.
1306
1307 \value [since 6.13] MaxFragmentStorageBuffers The maximum number of
1308 storage buffers that can be bound for reading (bufferLoad) in the
1309 fragment stage. Like the vertex stage, this is optional in OpenGL ES
1310 (only compute-stage storage blocks are mandatory), so 0 is a
1311 legitimate value. The write access and Metal argument table notes
1312 from MaxVertexStorageBuffers apply here as well; with Direct 3D 11
1313 the value reflects the unordered access view slots, which are shared
1314 with render target outputs.
1315 */
1316
1317/*!
1318 \class QRhiInitParams
1319 \inmodule QtGuiPrivate
1320 \inheaderfile rhi/qrhi.h
1321 \since 6.6
1322 \brief Base class for backend-specific initialization parameters.
1323
1324 Contains fields that are relevant to all backends.
1325
1326 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1327 for details.
1328 */
1329
1330/*!
1331 \class QRhiDepthStencilClearValue
1332 \inmodule QtGuiPrivate
1333 \inheaderfile rhi/qrhi.h
1334 \since 6.6
1335 \brief Specifies clear values for a depth or stencil buffer.
1336
1337 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1338 for details.
1339 */
1340
1341/*!
1342 \fn QRhiDepthStencilClearValue::QRhiDepthStencilClearValue() = default
1343
1344 Constructs a depth/stencil clear value with depth clear value 1.0f and
1345 stencil clear value 0.
1346 */
1347
1348/*!
1349 Constructs a depth/stencil clear value with depth clear value \a d and
1350 stencil clear value \a s.
1351 */
1352QRhiDepthStencilClearValue::QRhiDepthStencilClearValue(float d, quint32 s)
1353 : m_d(d),
1354 m_s(s)
1355{
1356}
1357
1358/*!
1359 \fn float QRhiDepthStencilClearValue::depthClearValue() const
1360 \return the depth clear value. In most cases this is 1.0f.
1361 */
1362
1363/*!
1364 \fn void QRhiDepthStencilClearValue::setDepthClearValue(float d)
1365 Sets the depth clear value to \a d.
1366 */
1367
1368/*!
1369 \fn quint32 QRhiDepthStencilClearValue::stencilClearValue() const
1370 \return the stencil clear value. In most cases this is 0.
1371 */
1372
1373/*!
1374 \fn void QRhiDepthStencilClearValue::setStencilClearValue(quint32 s)
1375 Sets the stencil clear value to \a s.
1376 */
1377
1378/*!
1379 \fn bool QRhiDepthStencilClearValue::operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1380
1381 \return \c true if the values in the two QRhiDepthStencilClearValue objects
1382 \a a and \a b are equal.
1383 */
1384
1385/*!
1386 \fn bool QRhiDepthStencilClearValue::operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1387
1388 \return \c false if the values in the two QRhiDepthStencilClearValue
1389 objects \a a and \a b are equal; otherwise returns \c true.
1390
1391*/
1392
1393/*!
1394 \fn size_t QRhiDepthStencilClearValue::qHash(const QRhiDepthStencilClearValue &key, size_t seed)
1395 \qhash{QRhiDepthStencilClearValue}
1396 */
1397
1398#ifndef QT_NO_DEBUG_STREAM
1399QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
1400{
1401 QDebugStateSaver saver(dbg);
1402 dbg.nospace() << "QRhiDepthStencilClearValue(depth-clear=" << v.depthClearValue()
1403 << " stencil-clear=" << v.stencilClearValue()
1404 << ')';
1405 return dbg;
1406}
1407#endif
1408
1409/*!
1410 \class QRhiViewport
1411 \inmodule QtGuiPrivate
1412 \inheaderfile rhi/qrhi.h
1413 \since 6.6
1414 \brief Specifies a viewport rectangle.
1415
1416 Used with QRhiCommandBuffer::setViewport().
1417
1418 QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
1419 bottom-left. Negative width or height are not allowed.
1420
1421 Typical usage is like the following:
1422
1423 \code
1424 const QSize outputSizeInPixels = swapchain->currentPixelSize();
1425 const QRhiViewport viewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height());
1426 cb->beginPass(swapchain->currentFrameRenderTarget(), Qt::black, { 1.0f, 0 });
1427 cb->setGraphicsPipeline(ps);
1428 cb->setViewport(viewport);
1429 // ...
1430 \endcode
1431
1432 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1433 for details.
1434
1435 \sa QRhiCommandBuffer::setViewport(), QRhi::clipSpaceCorrMatrix(), QRhiScissor
1436 */
1437
1438/*!
1439 \fn QRhiViewport::QRhiViewport() = default
1440
1441 Constructs a viewport description with an empty rectangle and a depth range
1442 of 0.0f - 1.0f.
1443
1444 \sa QRhi::clipSpaceCorrMatrix()
1445 */
1446
1447/*!
1448 Constructs a viewport description with the rectangle specified by \a x, \a
1449 y, \a w, \a h and the depth range \a minDepth and \a maxDepth.
1450
1451 \note \a x and \a y are assumed to be the bottom-left position. \a w and \a
1452 h should not be negative, the viewport will be ignored by
1453 QRhiCommandBuffer::setViewport() otherwise.
1454
1455 \sa QRhi::clipSpaceCorrMatrix()
1456 */
1457QRhiViewport::QRhiViewport(float x, float y, float w, float h, float minDepth, float maxDepth)
1458 : m_rect { { x, y, w, h } },
1459 m_minDepth(minDepth),
1460 m_maxDepth(maxDepth)
1461{
1462}
1463
1464/*!
1465 \fn std::array<float, 4> QRhiViewport::viewport() const
1466 \return the viewport x, y, width, and height.
1467 */
1468
1469/*!
1470 \fn void QRhiViewport::setViewport(float x, float y, float w, float h)
1471 Sets the viewport's position and size to \a x, \a y, \a w, and \a h.
1472
1473 \note Viewports are specified in a coordinate system that has its origin in
1474 the bottom-left.
1475 */
1476
1477/*!
1478 \fn float QRhiViewport::minDepth() const
1479 \return the minDepth value of the depth range of the viewport.
1480 */
1481
1482/*!
1483 \fn void QRhiViewport::setMinDepth(float minDepth)
1484 Sets the \a minDepth of the depth range of the viewport.
1485 By default this is set to 0.0f.
1486 */
1487
1488/*!
1489 \fn float QRhiViewport::maxDepth() const
1490 \return the maxDepth value of the depth range of the viewport.
1491 */
1492
1493/*!
1494 \fn void QRhiViewport::setMaxDepth(float maxDepth)
1495 Sets the \a maxDepth of the depth range of the viewport.
1496 By default this is set to 1.0f.
1497 */
1498
1499/*!
1500 \fn bool QRhiViewport::operator==(const QRhiViewport &a, const QRhiViewport &b) noexcept
1501
1502 \return \c true if the values in the two QRhiViewport objects
1503 \a a and \a b are equal.
1504 */
1505
1506/*!
1507 \fn bool QRhiViewport::operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept
1508
1509 \return \c false if the values in the two QRhiViewport
1510 objects \a a and \a b are equal; otherwise returns \c true.
1511*/
1512
1513/*!
1514 \fn size_t QRhiViewport::qHash(const QRhiViewport &key, size_t seed)
1515 \qhash{QRhiViewport}
1516 */
1517
1518#ifndef QT_NO_DEBUG_STREAM
1519QDebug operator<<(QDebug dbg, const QRhiViewport &v)
1520{
1521 QDebugStateSaver saver(dbg);
1522 const std::array<float, 4> r = v.viewport();
1523 dbg.nospace() << "QRhiViewport(bottom-left-x=" << r[0]
1524 << " bottom-left-y=" << r[1]
1525 << " width=" << r[2]
1526 << " height=" << r[3]
1527 << " minDepth=" << v.minDepth()
1528 << " maxDepth=" << v.maxDepth()
1529 << ')';
1530 return dbg;
1531}
1532#endif
1533
1534/*!
1535 \class QRhiScissor
1536 \inmodule QtGuiPrivate
1537 \inheaderfile rhi/qrhi.h
1538 \since 6.6
1539 \brief Specifies a scissor rectangle.
1540
1541 Used with QRhiCommandBuffer::setScissor(). Setting a scissor rectangle is
1542 only possible with a QRhiGraphicsPipeline that has
1543 QRhiGraphicsPipeline::UsesScissor set.
1544
1545 QRhi assumes OpenGL-style scissor coordinates, meaning x and y are
1546 bottom-left. Negative width or height are not allowed. However, apart from
1547 that, the flexible OpenGL semantics apply: negative x and y, partially out
1548 of bounds rectangles, etc. will be handled gracefully, clamping as
1549 appropriate. Therefore, any rendering logic targeting OpenGL can feed
1550 scissor rectangles into QRhiScissor as-is, without any adaptation.
1551
1552 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1553 for details.
1554
1555 \sa QRhiCommandBuffer::setScissor(), QRhiViewport
1556 */
1557
1558/*!
1559 \fn QRhiScissor::QRhiScissor() = default
1560
1561 Constructs an empty scissor.
1562 */
1563
1564/*!
1565 Constructs a scissor with the rectangle specified by \a x, \a y, \a w, and
1566 \a h.
1567
1568 \note \a x and \a y are assumed to be the bottom-left position. Negative \a w
1569 or \a h are not allowed, such scissor rectangles will be ignored by
1570 QRhiCommandBuffer. Other than that, the flexible OpenGL semantics apply:
1571 negative x and y, partially out of bounds rectangles, etc. will be handled
1572 gracefully, clamping as appropriate.
1573 */
1574QRhiScissor::QRhiScissor(int x, int y, int w, int h)
1575 : m_rect { { x, y, w, h } }
1576{
1577}
1578
1579/*!
1580 \fn std::array<int, 4> QRhiScissor::scissor() const
1581 \return the scissor position and size.
1582 */
1583
1584/*!
1585 \fn void QRhiScissor::setScissor(int x, int y, int w, int h)
1586 Sets the scissor position and size to \a x, \a y, \a w, \a h.
1587
1588 \note The position is always expected to be specified in a coordinate
1589 system that has its origin in the bottom-left corner, like OpenGL.
1590 */
1591
1592/*!
1593 \fn bool QRhiScissor::operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept
1594
1595 \return \c true if the values in the two QRhiScissor objects
1596 \a a and \a b are equal.
1597 */
1598
1599/*!
1600 \fn bool QRhiScissor::operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept
1601
1602 \return \c false if the values in the two QRhiScissor
1603 objects \a a and \a b are equal; otherwise returns \c true.
1604*/
1605
1606/*!
1607 \fn size_t QRhiScissor::qHash(const QRhiScissor &key, size_t seed)
1608 \qhash{QRhiScissor}
1609 */
1610
1611#ifndef QT_NO_DEBUG_STREAM
1612QDebug operator<<(QDebug dbg, const QRhiScissor &s)
1613{
1614 QDebugStateSaver saver(dbg);
1615 const std::array<int, 4> r = s.scissor();
1616 dbg.nospace() << "QRhiScissor(bottom-left-x=" << r[0]
1617 << " bottom-left-y=" << r[1]
1618 << " width=" << r[2]
1619 << " height=" << r[3]
1620 << ')';
1621 return dbg;
1622}
1623#endif
1624
1625/*!
1626 \class QRhiVertexInputBinding
1627 \inmodule QtGuiPrivate
1628 \inheaderfile rhi/qrhi.h
1629 \since 6.6
1630 \brief Describes a vertex input binding.
1631
1632 Specifies the stride (in bytes, must be a multiple of 4), the
1633 classification and optionally the instance step rate.
1634
1635 As an example, assume a vertex shader with the following inputs:
1636
1637 \badcode
1638 layout(location = 0) in vec4 position;
1639 layout(location = 1) in vec2 texcoord;
1640 \endcode
1641
1642 Now let's assume also that 3 component vertex positions \c{(x, y, z)} and 2
1643 component texture coordinates \c{(u, v)} are provided in a non-interleaved
1644 format in a buffer (or separate buffers even). Defining two bindings
1645 could then be done like this:
1646
1647 \code
1648 QRhiVertexInputLayout inputLayout;
1649 inputLayout.setBindings({
1650 { 3 * sizeof(float) },
1651 { 2 * sizeof(float) }
1652 });
1653 \endcode
1654
1655 Only the stride is interesting here since instancing is not used. The
1656 binding number is given by the index of the QRhiVertexInputBinding
1657 element in the bindings vector of the QRhiVertexInputLayout.
1658
1659 Once a graphics pipeline with this vertex input layout is bound, the vertex
1660 inputs could be set up like the following for drawing a cube with 36
1661 vertices, assuming we have a single buffer with first the positions and
1662 then the texture coordinates:
1663
1664 \code
1665 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1666 { cubeBuf, 0 },
1667 { cubeBuf, 36 * 3 * sizeof(float) }
1668 };
1669 cb->setVertexInput(0, 2, vbufBindings);
1670 \endcode
1671
1672 Note how the index defined by \c {startBinding + i}, where \c i is the
1673 index in the second argument of
1674 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}, matches the
1675 index of the corresponding entry in the \c bindings vector of the
1676 QRhiVertexInputLayout.
1677
1678 \note the stride must always be a multiple of 4.
1679
1680 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1681 for details.
1682
1683 \sa QRhiCommandBuffer::setVertexInput()
1684 */
1685
1686/*!
1687 \enum QRhiVertexInputBinding::Classification
1688 Describes the input data classification.
1689
1690 \value PerVertex Data is per-vertex
1691 \value PerInstance Data is per-instance
1692 */
1693
1694/*!
1695 \fn QRhiVertexInputBinding::QRhiVertexInputBinding() = default
1696
1697 Constructs a default vertex input binding description.
1698 */
1699
1700/*!
1701 Constructs a vertex input binding description with the specified \a stride,
1702 classification \a cls, and instance step rate \a stepRate.
1703
1704 \note \a stepRate other than 1 is only supported when
1705 QRhi::CustomInstanceStepRate is reported to be supported.
1706 */
1707QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cls, quint32 stepRate)
1708 : m_stride(stride),
1709 m_classification(cls),
1710 m_instanceStepRate(stepRate)
1711{
1712}
1713
1714/*!
1715 \fn quint32 QRhiVertexInputBinding::stride() const
1716 \return the stride in bytes.
1717 */
1718
1719/*!
1720 \fn void QRhiVertexInputBinding::setStride(quint32 s)
1721 Sets the stride to \a s.
1722 */
1723
1724/*!
1725 \fn QRhiVertexInputBinding::Classification QRhiVertexInputBinding::classification() const
1726 \return the input data classification.
1727 */
1728
1729/*!
1730 \fn void QRhiVertexInputBinding::setClassification(Classification c)
1731 Sets the input data classification \a c. By default this is set to PerVertex.
1732 */
1733
1734/*!
1735 \fn quint32 QRhiVertexInputBinding::instanceStepRate() const
1736 \return the instance step rate.
1737 */
1738
1739/*!
1740 \fn void QRhiVertexInputBinding::setInstanceStepRate(quint32 rate)
1741 Sets the instance step \a rate. By default this is set to 1.
1742 */
1743
1744/*!
1745 \fn bool QRhiVertexInputBinding::operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1746
1747 \return \c true if the values in the two QRhiVertexInputBinding objects
1748 \a a and \a b are equal.
1749 */
1750
1751/*!
1752 \fn bool QRhiVertexInputBinding::operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1753
1754 \return \c false if the values in the two QRhiVertexInputBinding
1755 objects \a a and \a b are equal; otherwise returns \c true.
1756*/
1757
1758/*!
1759 \fn size_t QRhiVertexInputBinding::qHash(const QRhiVertexInputBinding &key, size_t seed)
1760 \qhash{QRhiVertexInputBinding}
1761 */
1762
1763#ifndef QT_NO_DEBUG_STREAM
1764QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
1765{
1766 QDebugStateSaver saver(dbg);
1767 dbg.nospace() << "QRhiVertexInputBinding(stride=" << b.stride()
1768 << " cls=" << b.classification()
1769 << " step-rate=" << b.instanceStepRate()
1770 << ')';
1771 return dbg;
1772}
1773#endif
1774
1775/*!
1776 \class QRhiVertexInputAttribute
1777 \inmodule QtGuiPrivate
1778 \inheaderfile rhi/qrhi.h
1779 \since 6.6
1780 \brief Describes a single vertex input element.
1781
1782 The members specify the binding number, location, format, and offset for a
1783 single vertex input element.
1784
1785 \note For HLSL it is assumed that the vertex shader translated from SPIR-V
1786 uses
1787 \c{TEXCOORD<location>} as the semantic for each input. Hence no separate
1788 semantic name and index.
1789
1790 As an example, assume a vertex shader with the following inputs:
1791
1792 \badcode
1793 layout(location = 0) in vec4 position;
1794 layout(location = 1) in vec2 texcoord;
1795 \endcode
1796
1797 Now let's assume that we have 3 component vertex positions \c{(x, y, z)}
1798 and 2 component texture coordinates \c{(u, v)} are provided in a
1799 non-interleaved format in a buffer (or separate buffers even). Once two
1800 bindings are defined, the attributes could be specified as:
1801
1802 \code
1803 QRhiVertexInputLayout inputLayout;
1804 inputLayout.setBindings({
1805 { 3 * sizeof(float) },
1806 { 2 * sizeof(float) }
1807 });
1808 inputLayout.setAttributes({
1809 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1810 { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
1811 });
1812 \endcode
1813
1814 Once a graphics pipeline with this vertex input layout is bound, the vertex
1815 inputs could be set up like the following for drawing a cube with 36
1816 vertices, assuming we have a single buffer with first the positions and
1817 then the texture coordinates:
1818
1819 \code
1820 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1821 { cubeBuf, 0 },
1822 { cubeBuf, 36 * 3 * sizeof(float) }
1823 };
1824 cb->setVertexInput(0, 2, vbufBindings);
1825 \endcode
1826
1827 When working with interleaved data, there will typically be just one
1828 binding, with multiple attributes referring to that same buffer binding
1829 point:
1830
1831 \code
1832 QRhiVertexInputLayout inputLayout;
1833 inputLayout.setBindings({
1834 { 5 * sizeof(float) }
1835 });
1836 inputLayout.setAttributes({
1837 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1838 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
1839 });
1840 \endcode
1841
1842 and then:
1843
1844 \code
1845 const QRhiCommandBuffer::VertexInput vbufBinding(interleavedCubeBuf, 0);
1846 cb->setVertexInput(0, 1, &vbufBinding);
1847 \endcode
1848
1849 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1850 for details.
1851
1852 \sa QRhiCommandBuffer::setVertexInput()
1853 */
1854
1855/*!
1856 \enum QRhiVertexInputAttribute::Format
1857 Specifies the type of the element data.
1858
1859 \value Float4 Four component float vector
1860 \value Float3 Three component float vector
1861 \value Float2 Two component float vector
1862 \value Float Float
1863 \value UNormByte4 Four component normalized unsigned byte vector
1864 \value UNormByte2 Two component normalized unsigned byte vector
1865 \value UNormByte Normalized unsigned byte
1866 \value UInt4 Four component unsigned integer vector
1867 \value UInt3 Three component unsigned integer vector
1868 \value UInt2 Two component unsigned integer vector
1869 \value UInt Unsigned integer
1870 \value SInt4 Four component signed integer vector
1871 \value SInt3 Three component signed integer vector
1872 \value SInt2 Two component signed integer vector
1873 \value SInt Signed integer
1874 \value Half4 Four component half precision (16 bit) float vector
1875 \value Half3 Three component half precision (16 bit) float vector
1876 \value Half2 Two component half precision (16 bit) float vector
1877 \value Half Half precision (16 bit) float
1878 \value UShort4 Four component unsigned short (16 bit) integer vector
1879 \value UShort3 Three component unsigned short (16 bit) integer vector
1880 \value UShort2 Two component unsigned short (16 bit) integer vector
1881 \value UShort Unsigned short (16 bit) integer
1882 \value SShort4 Four component signed short (16 bit) integer vector
1883 \value SShort3 Three component signed short (16 bit) integer vector
1884 \value SShort2 Two component signed short (16 bit) integer vector
1885 \value SShort Signed short (16 bit) integer
1886
1887 \note Support for half precision floating point attributes is indicated at
1888 run time by the QRhi::Feature::HalfAttributes feature flag.
1889
1890 \note Direct3D 11/12 supports 16 bit input attributes, but does not support
1891 the Half3, UShort3 or SShort3 types. The D3D backends pass through Half3 as
1892 Half4, UShort3 as UShort4, and SShort3 as SShort4. To ensure cross platform
1893 compatibility, 16 bit inputs should be padded to 8 bytes.
1894 */
1895
1896/*!
1897 \fn QRhiVertexInputAttribute::QRhiVertexInputAttribute() = default
1898
1899 Constructs a default vertex input attribute description.
1900 */
1901
1902/*!
1903 Constructs a vertex input attribute description with the specified \a
1904 binding number, \a location, \a format, and \a offset.
1905
1906 \a matrixSlice should be -1 except when this attribute corresponds to a row
1907 or column of a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming
1908 4 consecutive vertex input locations), in which case it is the index of the
1909 row or column. \c{location - matrixSlice} must always be equal to the \c
1910 location for the first row or column of the unrolled matrix.
1911 */
1912QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset, int matrixSlice)
1913 : m_binding(binding),
1914 m_location(location),
1915 m_format(format),
1916 m_offset(offset),
1917 m_matrixSlice(matrixSlice)
1918{
1919}
1920
1921/*!
1922 \fn int QRhiVertexInputAttribute::binding() const
1923 \return the binding point index.
1924 */
1925
1926/*!
1927 \fn void QRhiVertexInputAttribute::setBinding(int b)
1928 Sets the binding point index to \a b.
1929 By default this is set to 0.
1930 */
1931
1932/*!
1933 \fn int QRhiVertexInputAttribute::location() const
1934 \return the location of the vertex input element.
1935 */
1936
1937/*!
1938 \fn void QRhiVertexInputAttribute::setLocation(int loc)
1939 Sets the location of the vertex input element to \a loc.
1940 By default this is set to 0.
1941 */
1942
1943/*!
1944 \fn QRhiVertexInputAttribute::Format QRhiVertexInputAttribute::format() const
1945 \return the format of the vertex input element.
1946 */
1947
1948/*!
1949 \fn void QRhiVertexInputAttribute::setFormat(Format f)
1950 Sets the format of the vertex input element to \a f.
1951 By default this is set to Float4.
1952 */
1953
1954/*!
1955 \fn quint32 QRhiVertexInputAttribute::offset() const
1956 \return the byte offset for the input element.
1957 */
1958
1959/*!
1960 \fn void QRhiVertexInputAttribute::setOffset(quint32 ofs)
1961 Sets the byte offset for the input element to \a ofs.
1962 */
1963
1964/*!
1965 \fn int QRhiVertexInputAttribute::matrixSlice() const
1966
1967 \return the matrix slice if the input element corresponds to a row or
1968 column of a matrix, or -1 if not relevant.
1969 */
1970
1971/*!
1972 \fn void QRhiVertexInputAttribute::setMatrixSlice(int slice)
1973
1974 Sets the matrix \a slice. By default this is set to -1, and should be set
1975 to a >= 0 value only when this attribute corresponds to a row or column of
1976 a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming 4
1977 consecutive vertex input locations), in which case it is the index of the
1978 row or column. \c{location - matrixSlice} must always be equal to the \c
1979 location for the first row or column of the unrolled matrix.
1980 */
1981
1982/*!
1983 \fn bool QRhiVertexInputAttribute::operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
1984
1985 \return \c true if the values in the two QRhiVertexInputAttribute objects
1986 \a a and \a b are equal.
1987 */
1988
1989/*!
1990 \fn bool QRhiVertexInputAttribute::operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
1991
1992 \return \c false if the values in the two QRhiVertexInputAttribute
1993 objects \a a and \a b are equal; otherwise returns \c true.
1994*/
1995
1996/*!
1997 \fn size_t QRhiVertexInputAttribute::qHash(const QRhiVertexInputAttribute &key, size_t seed)
1998 \qhash{QRhiVertexInputAttribute}
1999 */
2000
2001#ifndef QT_NO_DEBUG_STREAM
2002QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a)
2003{
2004 QDebugStateSaver saver(dbg);
2005 dbg.nospace() << "QRhiVertexInputAttribute(binding=" << a.binding()
2006 << " location=" << a.location()
2007 << " format=" << a.format()
2008 << " offset=" << a.offset()
2009 << ')';
2010 return dbg;
2011}
2012#endif
2013
2014QRhiVertexInputAttribute::Format QRhiImplementation::shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const
2015{
2016 switch (type) {
2017 case QShaderDescription::Vec4:
2018 return QRhiVertexInputAttribute::Float4;
2019 case QShaderDescription::Vec3:
2020 return QRhiVertexInputAttribute::Float3;
2021 case QShaderDescription::Vec2:
2022 return QRhiVertexInputAttribute::Float2;
2023 case QShaderDescription::Float:
2024 return QRhiVertexInputAttribute::Float;
2025
2026 case QShaderDescription::Int4:
2027 return QRhiVertexInputAttribute::SInt4;
2028 case QShaderDescription::Int3:
2029 return QRhiVertexInputAttribute::SInt3;
2030 case QShaderDescription::Int2:
2031 return QRhiVertexInputAttribute::SInt2;
2032 case QShaderDescription::Int:
2033 return QRhiVertexInputAttribute::SInt;
2034
2035 case QShaderDescription::Uint4:
2036 return QRhiVertexInputAttribute::UInt4;
2037 case QShaderDescription::Uint3:
2038 return QRhiVertexInputAttribute::UInt3;
2039 case QShaderDescription::Uint2:
2040 return QRhiVertexInputAttribute::UInt2;
2041 case QShaderDescription::Uint:
2042 return QRhiVertexInputAttribute::UInt;
2043
2044 case QShaderDescription::Half4:
2045 return QRhiVertexInputAttribute::Half4;
2046 case QShaderDescription::Half3:
2047 return QRhiVertexInputAttribute::Half3;
2048 case QShaderDescription::Half2:
2049 return QRhiVertexInputAttribute::Half2;
2050 case QShaderDescription::Half:
2051 return QRhiVertexInputAttribute::Half;
2052
2053 default:
2054 Q_UNREACHABLE_RETURN(QRhiVertexInputAttribute::Float);
2055 }
2056}
2057
2058quint32 QRhiImplementation::byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const
2059{
2060 switch (format) {
2061 case QRhiVertexInputAttribute::Float4:
2062 return 4 * sizeof(float);
2063 case QRhiVertexInputAttribute::Float3:
2064 return 4 * sizeof(float); // vec3 still takes 16 bytes
2065 case QRhiVertexInputAttribute::Float2:
2066 return 2 * sizeof(float);
2067 case QRhiVertexInputAttribute::Float:
2068 return sizeof(float);
2069
2070 case QRhiVertexInputAttribute::UNormByte4:
2071 return 4 * sizeof(quint8);
2072 case QRhiVertexInputAttribute::UNormByte2:
2073 return 2 * sizeof(quint8);
2074 case QRhiVertexInputAttribute::UNormByte:
2075 return sizeof(quint8);
2076
2077 case QRhiVertexInputAttribute::UInt4:
2078 return 4 * sizeof(quint32);
2079 case QRhiVertexInputAttribute::UInt3:
2080 return 4 * sizeof(quint32); // ivec3 still takes 16 bytes
2081 case QRhiVertexInputAttribute::UInt2:
2082 return 2 * sizeof(quint32);
2083 case QRhiVertexInputAttribute::UInt:
2084 return sizeof(quint32);
2085
2086 case QRhiVertexInputAttribute::SInt4:
2087 return 4 * sizeof(qint32);
2088 case QRhiVertexInputAttribute::SInt3:
2089 return 4 * sizeof(qint32); // uvec3 still takes 16 bytes
2090 case QRhiVertexInputAttribute::SInt2:
2091 return 2 * sizeof(qint32);
2092 case QRhiVertexInputAttribute::SInt:
2093 return sizeof(qint32);
2094
2095 case QRhiVertexInputAttribute::Half4:
2096 return 4 * sizeof(qfloat16);
2097 case QRhiVertexInputAttribute::Half3:
2098 return 4 * sizeof(qfloat16); // half3 still takes 8 bytes
2099 case QRhiVertexInputAttribute::Half2:
2100 return 2 * sizeof(qfloat16);
2101 case QRhiVertexInputAttribute::Half:
2102 return sizeof(qfloat16);
2103
2104 case QRhiVertexInputAttribute::UShort4:
2105 return 4 * sizeof(quint16);
2106 case QRhiVertexInputAttribute::UShort3:
2107 return 4 * sizeof(quint16); // ivec3 still takes 8 bytes
2108 case QRhiVertexInputAttribute::UShort2:
2109 return 2 * sizeof(quint16);
2110 case QRhiVertexInputAttribute::UShort:
2111 return sizeof(quint16);
2112
2113 case QRhiVertexInputAttribute::SShort4:
2114 return 4 * sizeof(qint16);
2115 case QRhiVertexInputAttribute::SShort3:
2116 return 4 * sizeof(qint16); // uvec3 still takes 8 bytes
2117 case QRhiVertexInputAttribute::SShort2:
2118 return 2 * sizeof(qint16);
2119 case QRhiVertexInputAttribute::SShort:
2120 return sizeof(qint16);
2121
2122 default:
2123 Q_UNREACHABLE_RETURN(1);
2124 }
2125}
2126
2127/*!
2128 \class QRhiVertexInputLayout
2129 \inmodule QtGuiPrivate
2130 \inheaderfile rhi/qrhi.h
2131 \since 6.6
2132 \brief Describes the layout of vertex inputs consumed by a vertex shader.
2133
2134 The vertex input layout is defined by the collections of
2135 QRhiVertexInputBinding and QRhiVertexInputAttribute.
2136
2137 As an example, let's assume that we have a single buffer with 3 component
2138 vertex positions and 2 component UV coordinates interleaved (\c x, \c y, \c
2139 z, \c u, \c v), that the position and UV are expected at input locations 0
2140 and 1 by the vertex shader, and that the vertex buffer will be bound at
2141 binding point 0 using
2142 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()} later on:
2143
2144 \code
2145 QRhiVertexInputLayout inputLayout;
2146 inputLayout.setBindings({
2147 { 5 * sizeof(float) }
2148 });
2149 inputLayout.setAttributes({
2150 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
2151 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
2152 });
2153 \endcode
2154
2155 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2156 for details.
2157 */
2158
2159/*!
2160 \fn QRhiVertexInputLayout::QRhiVertexInputLayout() = default
2161
2162 Constructs an empty vertex input layout description.
2163 */
2164
2165/*!
2166 \fn void QRhiVertexInputLayout::setBindings(std::initializer_list<QRhiVertexInputBinding> list)
2167 Sets the bindings from the specified \a list.
2168 */
2169
2170/*!
2171 \fn template<typename InputIterator> void QRhiVertexInputLayout::setBindings(InputIterator first, InputIterator last)
2172 Sets the bindings using the iterators \a first and \a last.
2173 */
2174
2175/*!
2176 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cbeginBindings() const
2177 \return a const iterator pointing to the first item in the binding list.
2178 */
2179
2180/*!
2181 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cendBindings() const
2182 \return a const iterator pointing just after the last item in the binding list.
2183 */
2184
2185/*!
2186 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::bindingAt(qsizetype index) const
2187 \return the binding at the given \a index.
2188 */
2189
2190/*!
2191 \fn qsizetype QRhiVertexInputLayout::bindingCount() const
2192 \return the number of bindings.
2193 */
2194
2195/*!
2196 \fn void QRhiVertexInputLayout::setAttributes(std::initializer_list<QRhiVertexInputAttribute> list)
2197 Sets the attributes from the specified \a list.
2198 */
2199
2200/*!
2201 \fn template<typename InputIterator> void QRhiVertexInputLayout::setAttributes(InputIterator first, InputIterator last)
2202 Sets the attributes using the iterators \a first and \a last.
2203 */
2204
2205/*!
2206 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cbeginAttributes() const
2207 \return a const iterator pointing to the first item in the attribute list.
2208 */
2209
2210/*!
2211 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cendAttributes() const
2212 \return a const iterator pointing just after the last item in the attribute list.
2213 */
2214
2215/*!
2216 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::attributeAt(qsizetype index) const
2217 \return the attribute at the given \a index.
2218 */
2219
2220/*!
2221 \fn qsizetype QRhiVertexInputLayout::attributeCount() const
2222 \return the number of attributes.
2223 */
2224
2225/*!
2226 \fn bool QRhiVertexInputLayout::operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2227
2228 \return \c true if the values in the two QRhiVertexInputLayout objects
2229 \a a and \a b are equal.
2230 */
2231
2232/*!
2233 \fn bool QRhiVertexInputLayout::operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2234
2235 \return \c false if the values in the two QRhiVertexInputLayout
2236 objects \a a and \a b are equal; otherwise returns \c true.
2237*/
2238
2239/*!
2240 \fn size_t QRhiVertexInputLayout::qHash(const QRhiVertexInputLayout &key, size_t seed)
2241 \qhash{QRhiVertexInputLayout}
2242 */
2243
2244#ifndef QT_NO_DEBUG_STREAM
2245QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
2246{
2247 QDebugStateSaver saver(dbg);
2248 dbg.nospace() << "QRhiVertexInputLayout(bindings=" << v.m_bindings
2249 << " attributes=" << v.m_attributes
2250 << ')';
2251 return dbg;
2252}
2253#endif
2254
2255/*!
2256 \class QRhiShaderStage
2257 \inmodule QtGuiPrivate
2258 \inheaderfile rhi/qrhi.h
2259 \since 6.6
2260 \brief Specifies the type and the shader code for a shader stage in the pipeline.
2261
2262 When setting up a QRhiGraphicsPipeline, a collection of shader stages are
2263 specified. The QRhiShaderStage contains a QShader and some associated
2264 metadata, such as the graphics pipeline stage, and the
2265 \l{QShader::Variant}{shader variant} to select. There is no need to specify
2266 the shader language or version because the QRhi backend in use at runtime
2267 will take care of choosing the appropriate shader version from the
2268 collection within the QShader.
2269
2270 The typical usage is in combination with
2271 QRhiGraphicsPipeline::setShaderStages(), shown here with a simple approach
2272 to load the QShader from \c{.qsb} files generated offline or at build time:
2273
2274 \code
2275 QShader getShader(const QString &name)
2276 {
2277 QFile f(name);
2278 return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
2279 }
2280
2281 QShader vs = getShader("material.vert.qsb");
2282 QShader fs = getShader("material.frag.qsb");
2283 pipeline->setShaderStages({
2284 { QRhiShaderStage::Vertex, vs },
2285 { QRhiShaderStage::Fragment, fs }
2286 });
2287 \endcode
2288
2289 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2290 for details.
2291 */
2292
2293/*!
2294 \enum QRhiShaderStage::Type
2295 Specifies the type of the shader stage.
2296
2297 \value Vertex Vertex stage
2298
2299 \value TessellationControl Tessellation control (hull shader) stage. Must
2300 be used only when the QRhi::Tessellation feature is supported.
2301
2302 \value TessellationEvaluation Tessellation evaluation (domain shader)
2303 stage. Must be used only when the QRhi::Tessellation feature is supported.
2304
2305 \value Fragment Fragment (pixel shader) stage
2306
2307 \value Compute Compute stage. Must be used only when the QRhi::Compute
2308 feature is supported.
2309
2310 \value Geometry Geometry stage. Must be used only when the
2311 QRhi::GeometryShader feature is supported.
2312 */
2313
2314/*!
2315 \fn QRhiShaderStage::QRhiShaderStage() = default
2316
2317 Constructs a shader stage description for the vertex stage with an empty
2318 QShader.
2319 */
2320
2321/*!
2322 \fn QRhiShaderStage::Type QRhiShaderStage::type() const
2323 \return the type of the stage.
2324 */
2325
2326/*!
2327 \fn void QRhiShaderStage::setType(Type t)
2328
2329 Sets the type of the stage to \a t. Setters should rarely be needed in
2330 pratice. Most applications will likely use the QRhiShaderStage constructor
2331 in most cases.
2332 */
2333
2334/*!
2335 \fn QShader QRhiShaderStage::shader() const
2336 \return the QShader to be used for this stage in the graphics pipeline.
2337 */
2338
2339/*!
2340 \fn void QRhiShaderStage::setShader(const QShader &s)
2341 Sets the shader collection \a s.
2342 */
2343
2344/*!
2345 \fn QShader::Variant QRhiShaderStage::shaderVariant() const
2346 \return the requested shader variant.
2347 */
2348
2349/*!
2350 \fn void QRhiShaderStage::setShaderVariant(QShader::Variant v)
2351 Sets the requested shader variant \a v.
2352 */
2353
2354/*!
2355 Constructs a shader stage description with the \a type of the stage and the
2356 \a shader.
2357
2358 The shader variant \a v defaults to QShader::StandardShader. A
2359 QShader contains multiple source and binary versions of a shader.
2360 In addition, it can also contain variants of the shader with slightly
2361 modified code. \a v can then be used to select the desired variant.
2362 */
2363QRhiShaderStage::QRhiShaderStage(Type type, const QShader &shader, QShader::Variant v)
2364 : m_type(type),
2365 m_shader(shader),
2366 m_shaderVariant(v)
2367{
2368}
2369
2370/*!
2371 \fn bool QRhiShaderStage::operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2372
2373 \return \c true if the values in the two QRhiShaderStage objects
2374 \a a and \a b are equal.
2375 */
2376
2377/*!
2378 \fn bool QRhiShaderStage::operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2379
2380 \return \c false if the values in the two QRhiShaderStage
2381 objects \a a and \a b are equal; otherwise returns \c true.
2382*/
2383
2384/*!
2385 \fn size_t QRhiShaderStage::qHash(const QRhiShaderStage &key, size_t seed)
2386 \qhash{QRhiShaderStage}
2387 */
2388
2389#ifndef QT_NO_DEBUG_STREAM
2390QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
2391{
2392 QDebugStateSaver saver(dbg);
2393 dbg.nospace() << "QRhiShaderStage(type=" << s.type()
2394 << " shader=" << s.shader()
2395 << " variant=" << s.shaderVariant()
2396 << ')';
2397 return dbg;
2398}
2399#endif
2400
2401/*!
2402 \class QRhiColorAttachment
2403 \inmodule QtGuiPrivate
2404 \inheaderfile rhi/qrhi.h
2405 \since 6.6
2406 \brief Describes the a single color attachment of a render target.
2407
2408 A color attachment is either a QRhiTexture or a QRhiRenderBuffer. The
2409 former, i.e. when texture() is set, is used in most cases.
2410 QRhiColorAttachment is commonly used in combination with
2411 QRhiTextureRenderTargetDescription.
2412
2413 \note texture() and renderBuffer() cannot be both set (be non-null at the
2414 same time).
2415
2416 Setting renderBuffer instead is recommended only when multisampling is
2417 needed. Relying on QRhi::MultisampleRenderBuffer is a better choice than
2418 QRhi::MultisampleTexture in practice since the former is available in more
2419 run time configurations (e.g. when running on OpenGL ES 3.0 which has no
2420 support for multisample textures, but does support multisample
2421 renderbuffers).
2422
2423 When targeting a non-multisample texture, the layer() and level() indicate
2424 the targeted layer (face index \c{0-5} for cubemaps) and mip level. For 3D
2425 textures layer() specifies the slice (one 2D image within the 3D texture)
2426 to render to. For texture arrays layer() is the array index.
2427
2428 When texture() or renderBuffer() is multisample, resolveTexture() can be
2429 set optionally. When set, samples are resolved automatically into that
2430 (non-multisample) texture at the end of the render pass. When rendering
2431 into a multisample renderbuffers, this is the only way to get resolved,
2432 non-multisample content out of them. Multisample textures allow sampling in
2433 shaders so for them this is just one option.
2434
2435 \note when resolving is enabled, the multisample data may not be written
2436 out at all. This means that the multisample texture() must not be used
2437 afterwards with shaders for sampling when resolveTexture() is set.
2438
2439 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2440 for details.
2441
2442 \sa QRhiTextureRenderTargetDescription
2443 */
2444
2445/*!
2446 \fn QRhiColorAttachment::QRhiColorAttachment() = default
2447
2448 Constructs an empty color attachment description.
2449 */
2450
2451/*!
2452 Constructs a color attachment description that specifies \a texture as the
2453 associated color buffer.
2454 */
2455QRhiColorAttachment::QRhiColorAttachment(QRhiTexture *texture)
2456 : m_texture(texture)
2457{
2458}
2459
2460/*!
2461 Constructs a color attachment description that specifies \a renderBuffer as
2462 the associated color buffer.
2463 */
2464QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
2465 : m_renderBuffer(renderBuffer)
2466{
2467}
2468
2469/*!
2470 \fn QRhiTexture *QRhiColorAttachment::texture() const
2471
2472 \return the texture this attachment description references, or \nullptr if
2473 there is none.
2474 */
2475
2476/*!
2477 \fn void QRhiColorAttachment::setTexture(QRhiTexture *tex)
2478
2479 Sets the texture \a tex.
2480
2481 \note texture() and renderBuffer() cannot be both set (be non-null at the
2482 same time).
2483 */
2484
2485/*!
2486 \fn QRhiRenderBuffer *QRhiColorAttachment::renderBuffer() const
2487
2488 \return the renderbuffer this attachment description references, or
2489 \nullptr if there is none.
2490
2491 In practice associating a QRhiRenderBuffer with a QRhiColorAttachment makes
2492 the most sense when setting up multisample rendering via a multisample
2493 \l{QRhiRenderBuffer::Type}{color} renderbuffer that is then resolved into a
2494 non-multisample texture at the end of the render pass.
2495 */
2496
2497/*!
2498 \fn void QRhiColorAttachment::setRenderBuffer(QRhiRenderBuffer *rb)
2499
2500 Sets the renderbuffer \a rb.
2501
2502 \note texture() and renderBuffer() cannot be both set (be non-null at the
2503 same time).
2504 */
2505
2506/*!
2507 \fn int QRhiColorAttachment::layer() const
2508 \return the layer index (cubemap face or array layer). 0 by default.
2509 */
2510
2511/*!
2512 \fn void QRhiColorAttachment::setLayer(int layer)
2513 Sets the \a layer index.
2514 */
2515
2516/*!
2517 \fn int QRhiColorAttachment::level() const
2518 \return the mip level. 0 by default.
2519 */
2520
2521/*!
2522 \fn void QRhiColorAttachment::setLevel(int level)
2523 Sets the mip \a level.
2524 */
2525
2526/*!
2527 \fn QRhiTexture *QRhiColorAttachment::resolveTexture() const
2528
2529 \return the resolve texture this attachment description references, or
2530 \nullptr if there is none.
2531
2532 Setting a non-null resolve texture is applicable when the attachment
2533 references a multisample texture or renderbuffer. The QRhiTexture in the
2534 resolveTexture() is then a non-multisample 2D texture (or texture array)
2535 with the same size (but a sample count of 1). The multisample content is
2536 automatically resolved into this texture at the end of each render pass.
2537 */
2538
2539/*!
2540 \fn void QRhiColorAttachment::setResolveTexture(QRhiTexture *tex)
2541
2542 Sets the resolve texture \a tex.
2543
2544 \a tex is expected to be a 2D texture or a 2D texture array. In either
2545 case, resolving targets a single mip level of a single layer (array
2546 element) of \a tex. The mip level and array layer are specified by
2547 resolveLevel() and resolveLayer().
2548
2549 An exception is \l{setMultiViewCount()}{multiview}: when the color
2550 attachment is associated with a texture array and multiview is enabled, the
2551 resolve texture must also be a texture array with sufficient elements for
2552 all views. In this case all elements that correspond to views are resolved
2553 automatically; the behavior is similar to the following pseudo-code:
2554 \badcode
2555 for (i = 0; i < multiViewCount(); ++i)
2556 resolve texture's layer() + i into resolveTexture's resolveLayer() + i
2557 \endcode
2558
2559 Setting a non-multisample texture to resolve a multisample texture or
2560 renderbuffer automatically at the end of the render pass is often
2561 preferable to working with multisample textures (and not setting a resolve
2562 texture), because it avoids the need for writing dedicated fragment shaders
2563 that work exclusively with multisample textures (\c sampler2DMS, \c
2564 texelFetch, etc.), and rather allows using the same shader as one would if
2565 the attachment's texture was not multisampled to begin with. This comes at
2566 the expense of an additional resource (the non-multisample \a tex).
2567 */
2568
2569/*!
2570 \fn int QRhiColorAttachment::resolveLayer() const
2571 \return the currently set resolve texture layer. Defaults to 0.
2572 */
2573
2574/*!
2575 \fn void QRhiColorAttachment::setResolveLayer(int layer)
2576 Sets the resolve texture \a layer to use.
2577 */
2578
2579/*!
2580 \fn int QRhiColorAttachment::resolveLevel() const
2581 \return the currently set resolve texture mip level. Defaults to 0.
2582 */
2583
2584/*!
2585 \fn void QRhiColorAttachment::setResolveLevel(int level)
2586 Sets the resolve texture mip \a level to use.
2587 */
2588
2589/*!
2590 \fn int QRhiColorAttachment::multiViewCount() const
2591
2592 \return the currently set number of views. Defaults to 0 which indicates
2593 the render target with this color attachment is not going to be used with
2594 multiview rendering.
2595
2596 \since 6.7
2597 */
2598
2599/*!
2600 \fn void QRhiColorAttachment::setMultiViewCount(int count)
2601
2602 Sets the view \a count. Setting a value larger than 1 indicates that the
2603 render target with this color attachment is going to be used with multiview
2604 rendering. The default value is 0. Values smaller than 2 indicate no
2605 multiview rendering.
2606
2607 When \a count is set to \c 2 or greater, the color attachment must be
2608 associated with a 2D texture array. layer() and multiViewCount() together
2609 define the range of texture array elements that are targeted during
2610 multiview rendering.
2611
2612 For example, if \c layer is \c 0 and \c multiViewCount is \c 2, the texture
2613 array must have 2 (or more) elements, and the multiview rendering will
2614 target elements 0 and 1. The \c{gl_ViewIndex} variable in the shaders has a
2615 value of \c 0 or \c 1 then, where view \c 0 corresponds to the texture array
2616 element \c 0, and view \c 1 to the array element \c 1.
2617
2618 \note Setting a \a count larger than 1, using a texture array as texture(),
2619 and calling \l{QRhiCommandBuffer::beginPass()}{beginPass()} on a
2620 QRhiTextureRenderTarget with this color attachment implies multiview
2621 rendering for the entire render pass. multiViewCount() should not be set
2622 unless multiview rendering is wanted. Multiview cannot be used with texture
2623 types other than 2D texture arrays. (although 3D textures may work,
2624 depending on the graphics API and backend; applications are nonetheless
2625 advised not to rely on that and only use 2D texture arrays as the render
2626 targets of multiview rendering)
2627
2628 See
2629 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2630 for more details regarding multiview rendering. Do note that Qt requires
2631 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview2.txt}{GL_OVR_multiview2}
2632 as well, when running on OpenGL (ES).
2633
2634 Multiview rendering is available only when the
2635 \l{QRhi::MultiView}{MultiView} feature is reported as supported from
2636 \l{QRhi::isFeatureSupported()}{isFeatureSupported()}.
2637
2638 \note For portability, be aware of limitations that exist for multiview
2639 rendering with some of the graphics APIs. It is recommended that multiview
2640 render passes do not rely on any of the features that
2641 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2642 declares as unsupported. The one exception is shader stage outputs other
2643 than \c{gl_Position} depending on \c{gl_ViewIndex}: that can be relied on
2644 (even with OpenGL) because QRhi never reports multiview as supported without
2645 \c{GL_OVR_multiview2} also being present.
2646
2647 \note Multiview rendering is not supported in combination with tessellation
2648 or geometry shaders, even though some implementations of some graphics APIs
2649 may allow this.
2650
2651 \since 6.7
2652 */
2653
2654/*!
2655 \class QRhiTextureRenderTargetDescription
2656 \inmodule QtGuiPrivate
2657 \inheaderfile rhi/qrhi.h
2658 \since 6.6
2659 \brief Describes the color and depth or depth/stencil attachments of a render target.
2660
2661 A texture render target has zero or more textures as color attachments,
2662 zero or one renderbuffer as combined depth/stencil buffer or zero or one
2663 texture as depth buffer.
2664
2665 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2666 non-null at the same time).
2667
2668 Let's look at some example usages in combination with
2669 QRhiTextureRenderTarget.
2670
2671 Due to the constructors, the targeting a texture (and no depth/stencil
2672 buffer) is simple:
2673
2674 \code
2675 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256), 1, QRhiTexture::RenderTarget);
2676 texture->create();
2677 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture }));
2678 \endcode
2679
2680 The following creates a texture render target that is set up to target mip
2681 level #2 of a texture:
2682
2683 \code
2684 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget | QRhiTexture::MipMapped);
2685 texture->create();
2686 QRhiColorAttachment colorAtt(texture);
2687 colorAtt.setLevel(2);
2688 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt });
2689 \endcode
2690
2691 Another example, this time to render into a depth texture:
2692
2693 \code
2694 QRhiTexture *shadowMap = rhi->newTexture(QRhiTexture::D32F, QSize(1024, 1024), 1, QRhiTexture::RenderTarget);
2695 shadowMap->create();
2696 QRhiTextureRenderTargetDescription rtDesc;
2697 rtDesc.setDepthTexture(shadowMap);
2698 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2699 \endcode
2700
2701 A very common case, having a texture as the color attachment and a
2702 renderbuffer as depth/stencil to enable depth testing:
2703
2704 \code
2705 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2706 texture->create();
2707 QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512));
2708 depthStencil->create();
2709 QRhiTextureRenderTargetDescription rtDesc({ texture }, depthStencil);
2710 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2711 \endcode
2712
2713 Finally, to enable multisample rendering in a portable manner (so also
2714 supporting OpenGL ES 3.0), using a QRhiRenderBuffer as the (multisample)
2715 color buffer and then resolving into a regular (non-multisample) 2D
2716 texture. To enable depth testing, a depth-stencil buffer, which also must
2717 use the same sample count, is used as well:
2718
2719 \code
2720 QRhiRenderBuffer *colorBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4); // 4x MSAA
2721 colorBuffer->create();
2722 QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512), 4);
2723 depthStencil->create();
2724 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2725 texture->create();
2726 QRhiColorAttachment colorAtt(colorBuffer);
2727 colorAtt.setResolveTexture(texture);
2728 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt, depthStencil });
2729 \endcode
2730
2731 \note when multisample resolving is enabled, the multisample data may not be
2732 written out at all. This means that the multisample texture in a color
2733 attachment must not be used afterwards with shaders for sampling (or other
2734 purposes) whenever a resolve texture is set, since the multisample color
2735 buffer is merely an intermediate storage then that gets no data written back
2736 on some GPU architectures at all. See
2737 \l{QRhiTextureRenderTarget::Flag}{PreserveColorContents} for more details.
2738
2739 \note When using setDepthTexture(), not setDepthStencilBuffer(), and the
2740 depth (stencil) data is not of interest afterwards, set the
2741 DoNotStoreDepthStencilContents flag on the QRhiTextureRenderTarget. This
2742 allows indicating to the underlying 3D API that the depth/stencil data can
2743 be discarded, leading potentially to better performance with tiled GPU
2744 architectures. When the depth-stencil buffer is a QRhiRenderBuffer (and also
2745 for the multisample color texture, see previous note) this is implicit, but
2746 with a depth (stencil) QRhiTexture the intention needs to be declared
2747 explicitly. By default QRhi assumes that the data is of interest (e.g., the
2748 depth texture is sampled in a shader afterwards).
2749
2750 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2751 for details.
2752
2753 \sa QRhiColorAttachment, QRhiTextureRenderTarget
2754 */
2755
2756/*!
2757 \fn QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription() = default
2758
2759 Constructs an empty texture render target description.
2760 */
2761
2762/*!
2763 Constructs a texture render target description with one attachment
2764 described by \a colorAttachment.
2765 */
2766QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment)
2767{
2768 m_colorAttachments.append(colorAttachment);
2769}
2770
2771/*!
2772 Constructs a texture render target description with two attachments, a
2773 color attachment described by \a colorAttachment, and a depth/stencil
2774 attachment with \a depthStencilBuffer.
2775 */
2776QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2777 QRhiRenderBuffer *depthStencilBuffer)
2778 : m_depthStencilBuffer(depthStencilBuffer)
2779{
2780 m_colorAttachments.append(colorAttachment);
2781}
2782
2783/*!
2784 Constructs a texture render target description with two attachments, a
2785 color attachment described by \a colorAttachment, and a depth attachment
2786 with \a depthTexture.
2787
2788 \note \a depthTexture must have a suitable format, such as QRhiTexture::D16
2789 or QRhiTexture::D32F.
2790 */
2791QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2792 QRhiTexture *depthTexture)
2793 : m_depthTexture(depthTexture)
2794{
2795 m_colorAttachments.append(colorAttachment);
2796}
2797
2798/*!
2799 \fn void QRhiTextureRenderTargetDescription::setColorAttachments(std::initializer_list<QRhiColorAttachment> list)
2800 Sets the \a list of color attachments.
2801 */
2802
2803/*!
2804 \fn template<typename InputIterator> void QRhiTextureRenderTargetDescription::setColorAttachments(InputIterator first, InputIterator last)
2805 Sets the list of color attachments via the iterators \a first and \a last.
2806 */
2807
2808/*!
2809 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cbeginColorAttachments() const
2810 \return a const iterator pointing to the first item in the attachment list.
2811 */
2812
2813/*!
2814 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cendColorAttachments() const
2815 \return a const iterator pointing just after the last item in the attachment list.
2816 */
2817
2818/*!
2819 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::colorAttachmentAt(qsizetype index) const
2820 \return the color attachment at the specified \a index.
2821 */
2822
2823/*!
2824 \fn qsizetype QRhiTextureRenderTargetDescription::colorAttachmentCount() const
2825 \return the number of currently set color attachments.
2826 */
2827
2828/*!
2829 \fn QRhiRenderBuffer *QRhiTextureRenderTargetDescription::depthStencilBuffer() const
2830 \return the renderbuffer used as depth-stencil buffer, or \nullptr if none was set.
2831 */
2832
2833/*!
2834 \fn void QRhiTextureRenderTargetDescription::setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer)
2835
2836 Sets the \a renderBuffer for depth-stencil. Not mandatory, e.g. when no
2837 depth test/write or stencil-related features are used within any graphics
2838 pipelines in any of the render passes for this render target, it can be
2839 left set to \nullptr.
2840
2841 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2842 non-null at the same time).
2843
2844 Using a QRhiRenderBuffer over a 2D QRhiTexture as the depth or
2845 depth/stencil buffer is very common, and is the recommended approach for
2846 applications. Using a QRhiTexture, and so setDepthTexture() becomes
2847 relevant if the depth data is meant to be accessed (e.g. sampled in a
2848 shader) afterwards, or when
2849 \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering} is
2850 involved (because then the depth texture must be a texture array).
2851
2852 \sa setDepthTexture()
2853 */
2854
2855/*!
2856 \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthTexture() const
2857 \return the currently referenced depth texture, or \nullptr if none was set.
2858 */
2859
2860/*!
2861 \fn void QRhiTextureRenderTargetDescription::setDepthTexture(QRhiTexture *texture)
2862
2863 Sets the \a texture for depth-stencil. This is an alternative to
2864 setDepthStencilBuffer(), where instead of a QRhiRenderBuffer a QRhiTexture
2865 with a suitable type (e.g., QRhiTexture::D32F) is provided.
2866
2867 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2868 non-null at the same time).
2869
2870 \a texture can either be a 2D texture or a 2D texture array (when texture
2871 arrays are supported). Specifying a texture array is relevant in particular
2872 with
2873 \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering}.
2874
2875 \note If \a texture is a format with a stencil component, such as
2876 \l QRhiTexture::D24S8, it will serve as the stencil buffer as well.
2877
2878 \sa setDepthStencilBuffer()
2879 */
2880
2881/*!
2882 \fn int QRhiTextureRenderTargetDescription::depthLayer() const
2883 \return the array slice index to be used for the depth/stencil attachment,
2884 or -1 by default.
2885
2886 \since 6.12
2887 \sa setDepthLayer(), setDepthTexture()
2888 */
2889
2890/*!
2891 \fn void QRhiTextureRenderTargetDescription::setDepthLayer(int depthLayer)
2892
2893 Sets the array slice index to be used for the depth/stencil attachment.
2894
2895 Pass -1 (the default) to not target a particular layer. When set to a
2896 non-negative value, the render target attaches a view that targets exactly
2897 that layer (slice) of the depth texture. This is only effective when a 2D
2898 array depth texture is provided via setDepthTexture(); otherwise the value
2899 is ignored.
2900
2901 The value must be within the array size of the depth texture; passing an
2902 out-of-range index leads to undefined behavior. The index is absolute
2903 with respect to the underlying texture, regardless of any array range
2904 that may have been specified when creating the texture.
2905
2906 Specifying a \a depthLayer disables layered/multiview rendering for the
2907 depth attachment.
2908
2909 \since 6.12
2910 \sa depthLayer(), setDepthTexture()
2911 */
2912
2913/*!
2914 \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthResolveTexture() const
2915
2916 \return the texture to which a multisample depth (or depth-stencil) texture
2917 (or texture array) is resolved to. \nullptr if there is none, which is the
2918 most common case.
2919
2920 \since 6.8
2921 \sa QRhiColorAttachment::resolveTexture(), depthTexture()
2922 */
2923
2924/*!
2925 \fn void QRhiTextureRenderTargetDescription::setDepthResolveTexture(QRhiTexture *tex)
2926
2927 Sets the depth (or depth-stencil) resolve texture \a tex.
2928
2929 \a tex is expected to be a 2D texture or a 2D texture array with a format
2930 matching the texture set via setDepthTexture().
2931
2932 \note Resolving depth (or depth-stencil) data is only functional when the
2933 \l QRhi::ResolveDepthStencil feature is reported as supported at run time.
2934 Support for depth-stencil resolve is not universally available among the
2935 graphics APIs. Designs assuming unconditional availability of depth-stencil
2936 resolve are therefore non-portable, and should be avoided.
2937
2938 \note As an additional limitation for OpenGL ES in particular, setting a
2939 depth resolve texture may only be functional in combination with
2940 setDepthTexture(), not with setDepthStencilBuffer().
2941
2942 \since 6.8
2943 \sa QRhiColorAttachment::setResolveTexture(), setDepthTexture()
2944 */
2945
2946/*!
2947 \fn QRhiShadingRateMap *QRhiTextureRenderTargetDescription::shadingRateMap() const
2948 \return the currently set QRhiShadingRateMap. By default this is \nullptr.
2949 \since 6.9
2950 */
2951
2952/*!
2953 \fn void QRhiTextureRenderTargetDescription::setShadingRateMap(QRhiShadingRateMap *map)
2954
2955 Associates with the specified QRhiShadingRateMap \a map. This is functional
2956 only when the \l QRhi::VariableRateShadingMap feature is reported as
2957 supported.
2958
2959 When QRhiCommandBuffer::setShadingRate() is also called, the higher of the
2960 two shading rates is used for each tile. There is currently no control
2961 offered over the combiner behavior.
2962
2963 \note When the render target had already been built (create() was called
2964 successfully), setting a shading rate map implies that a different, new
2965 QRhiRenderPassDescriptor is needed and thus a rebuild is needed. Call
2966 setRenderPassDescriptor() again (outside of a render pass) and then rebuild
2967 by calling create(). This has other rolling consequences as well, for
2968 example for graphics pipelines: those also need to be associated with the
2969 new QRhiRenderPassDescriptor and then rebuilt. See \l
2970 QRhiRenderPassDescriptor::serializedFormat() for some suggestions on how to
2971 deal with this. Remember to set the QRhiGraphicsPipeline::UsesShadingRate
2972 flag as well.
2973
2974 \since 6.9
2975 */
2976
2977/*!
2978 \class QRhiTextureSubresourceUploadDescription
2979 \inmodule QtGuiPrivate
2980 \inheaderfile rhi/qrhi.h
2981 \since 6.6
2982 \brief Describes the source for one mip level in a layer in a texture upload operation.
2983
2984 The source content is specified either as a QImage or as a raw blob. The
2985 former is only allowed for uncompressed textures with a format that can be
2986 mapped to QImage, while the latter is supported for all formats, including
2987 floating point and compressed.
2988
2989 \note image() and data() cannot be both set at the same time.
2990
2991 destinationTopLeft() specifies the top-left corner of the target
2992 rectangle. Defaults to (0, 0).
2993
2994 An empty sourceSize() (the default) indicates that size is assumed to be
2995 the size of the subresource. With QImage-based uploads this implies that
2996 the size of the source image() must match the subresource. When providing
2997 raw data instead, sufficient number of bytes must be provided in data().
2998
2999 sourceTopLeft() is supported only for QImage-based uploads, and specifies
3000 the top-left corner of the source rectangle.
3001
3002 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3003 internally, depending on the format and the backend.
3004
3005 When providing raw data, and the stride is not specified via
3006 setDataStride(), the stride (row pitch, row length in bytes) of the
3007 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
3008 the number of bytes used for one pixel, and there must be no additional
3009 padding between rows. There is no row start alignment requirement.
3010
3011 When there is unused data at the end of each row in the input raw data,
3012 call setDataStride() with the total number of bytes per row. The stride
3013 must always be a multiple of the number of bytes for one pixel. The row
3014 stride is only applicable to image data for textures with an uncompressed
3015 format.
3016
3017 \note The format of the source data must be compatible with the texture
3018 format. With many graphics APIs the data is copied as-is into a staging
3019 buffer, there is no intermediate format conversion provided by QRhi. This
3020 applies to floating point formats as well, with, for example, RGBA16F
3021 requiring half floats in the source data.
3022
3023 \note Setting the stride via setDataStride() is only functional when
3024 QRhi::ImageDataStride is reported as
3025 \l{QRhi::isFeatureSupported()}{supported}. In practice this can be expected
3026 to be supported everywhere except for OpenGL ES 2.0.
3027
3028 \note When a QImage is given, the stride returned from
3029 QImage::bytesPerLine() is taken into account automatically.
3030
3031 \warning When a QImage is given and the QImage does not own the underlying
3032 pixel data, it is up to the caller to ensure that the associated data stays
3033 valid until the end of the frame. (just submitting the resource update batch
3034 is not sufficient, the data must stay valid until QRhi::endFrame() is called
3035 in order to be portable across all backends) If this cannot be ensured, the
3036 caller is strongly encouraged to call QImage::detach() on the image before
3037 passing it to uploadTexture().
3038
3039 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3040 for details.
3041
3042 \sa QRhiTextureUploadDescription
3043 */
3044
3045/*!
3046 \fn QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription() = default
3047
3048 Constructs an empty subresource description.
3049
3050 \note an empty QRhiTextureSubresourceUploadDescription is not useful on its
3051 own and should not be submitted to a QRhiTextureUploadEntry. At minimum
3052 image or data must be set first.
3053 */
3054
3055/*!
3056 Constructs a mip level description with a \a image.
3057
3058 The \l{QImage::size()}{size} of \a image must match the size of the mip
3059 level. For level 0 that is the \l{QRhiTexture::pixelSize()}{texture size}.
3060
3061 The bit depth of \a image must be compatible with the
3062 \l{QRhiTexture::Format}{texture format}.
3063
3064 To describe a partial upload, call setSourceSize(), setSourceTopLeft(), or
3065 setDestinationTopLeft() afterwards.
3066 */
3067QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QImage &image)
3068 : m_image(image)
3069{
3070}
3071
3072/*!
3073 Constructs a mip level description with the image data is specified by \a
3074 data and \a size. This is suitable for floating point and compressed
3075 formats as well.
3076
3077 \a data can safely be destroyed or changed once this function returns.
3078 */
3079QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const void *data, quint32 size)
3080 : m_data(reinterpret_cast<const char *>(data), size)
3081{
3082}
3083
3084/*!
3085 Constructs a mip level description with the image data specified by \a
3086 data. This is suitable for floating point and compressed formats as well.
3087 */
3088QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QByteArray &data)
3089 : m_data(data)
3090{
3091}
3092
3093/*!
3094 \fn QImage QRhiTextureSubresourceUploadDescription::image() const
3095 \return the currently set QImage.
3096 */
3097
3098/*!
3099 \fn void QRhiTextureSubresourceUploadDescription::setImage(const QImage &image)
3100
3101 Sets \a image.
3102 Upon textures loading, the image data will be read as is, with no formats conversions.
3103
3104 \note image() and data() cannot be both set at the same time.
3105 */
3106
3107/*!
3108 \fn QByteArray QRhiTextureSubresourceUploadDescription::data() const
3109 \return the currently set raw pixel data.
3110 */
3111
3112/*!
3113 \fn void QRhiTextureSubresourceUploadDescription::setData(const QByteArray &data)
3114
3115 Sets \a data.
3116
3117 \note image() and data() cannot be both set at the same time.
3118 */
3119
3120/*!
3121 \fn quint32 QRhiTextureSubresourceUploadDescription::dataStride() const
3122 \return the currently set data stride.
3123 */
3124
3125/*!
3126 \fn void QRhiTextureSubresourceUploadDescription::setDataStride(quint32 stride)
3127
3128 Sets the data \a stride in bytes. By default this is 0 and not always
3129 relevant. When providing raw data(), and the stride is not specified via
3130 setDataStride(), the stride (row pitch, row length in bytes) of the
3131 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
3132 the number of bytes used for one pixel, and there must be no additional
3133 padding between rows. Otherwise, if there is additional space between the
3134 lines, set a non-zero \a stride. All this is applicable only when raw image
3135 data is provided, and is not necessary when working QImage since that has
3136 its own \l{QImage::bytesPerLine()}{stride} value.
3137
3138 \note When a non-zero \a stride is set, make sure the data contains the
3139 trailing padding for the last row as well, i.e. at least \c{stride * height}
3140 bytes in total. While providing the data without the last row's padding
3141 (i.e., interpreting stride as not applicable to the last row) could be safe,
3142 and is in fact safe with Vulkan, OpenGL, and D3D12, this cannot be
3143 guaranteed for all backends, so the safe approach is to avoid this and treat
3144 the last line like all others.
3145
3146 \note Setting the stride via setDataStride() is only functional when
3147 QRhi::ImageDataStride is reported as
3148 \l{QRhi::isFeatureSupported()}{supported}.
3149
3150 \note When a QImage is given, the stride returned from
3151 QImage::bytesPerLine() is taken into account automatically and therefore
3152 there is no need to set the data stride manually.
3153 */
3154
3155/*!
3156 \fn QPoint QRhiTextureSubresourceUploadDescription::destinationTopLeft() const
3157 \return the currently set destination top-left position. Defaults to (0, 0).
3158 */
3159
3160/*!
3161 \fn void QRhiTextureSubresourceUploadDescription::setDestinationTopLeft(const QPoint &p)
3162 Sets the destination top-left position \a p.
3163
3164 \note In the most common case of sourcing the image data from a QImage, Qt
3165 performs clamping of invalid texture upload sizes when the destination
3166 position + the source size exceeds the size of the targeted texture
3167 subresource (i.e, the size at the given mip level). There is also a
3168 qWarning() message printed on the debug output in this case. This is done in
3169 order to avoid confusion when the underlying 3D APIs crash and lead to GPU
3170 device removals at a later point when submitting the commands. Regardless,
3171 developers are encouraged to always validate applications by running with the
3172 Vulkan, D3D12, or Metal validation/debug layers enabled, since those offer a
3173 much wider range of checks on API usage.
3174 */
3175
3176/*!
3177 \fn QSize QRhiTextureSubresourceUploadDescription::sourceSize() const
3178
3179 \return the source size in pixels. Defaults to a default-constructed QSize,
3180 which indicates the entire subresource.
3181 */
3182
3183/*!
3184 \fn void QRhiTextureSubresourceUploadDescription::setSourceSize(const QSize &size)
3185
3186 Sets the source \a size in pixels.
3187
3188 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3189 internally, depending on the format and the backend.
3190 */
3191
3192/*!
3193 \fn QPoint QRhiTextureSubresourceUploadDescription::sourceTopLeft() const
3194 \return the currently set source top-left position. Defaults to (0, 0).
3195 */
3196
3197/*!
3198 \fn void QRhiTextureSubresourceUploadDescription::setSourceTopLeft(const QPoint &p)
3199
3200 Sets the source top-left position \a p.
3201
3202 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3203 internally, depending on the format and the backend.
3204 */
3205
3206/*!
3207 \class QRhiTextureUploadEntry
3208 \inmodule QtGuiPrivate
3209 \inheaderfile rhi/qrhi.h
3210 \since 6.6
3211
3212 \brief Describes one layer (face for cubemaps, slice for 3D textures,
3213 element for texture arrays) in a texture upload operation.
3214
3215 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3216 for details.
3217 */
3218
3219/*!
3220 \fn QRhiTextureUploadEntry::QRhiTextureUploadEntry()
3221
3222 Constructs an empty QRhiTextureUploadEntry targeting layer 0 and level 0.
3223
3224 \note an empty QRhiTextureUploadEntry should not be submitted without
3225 setting a QRhiTextureSubresourceUploadDescription via setDescription()
3226 first.
3227 */
3228
3229/*!
3230 Constructs a QRhiTextureUploadEntry targeting the given \a layer and mip
3231 \a level, with the subresource contents described by \a desc.
3232 */
3233QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
3234 const QRhiTextureSubresourceUploadDescription &desc)
3235 : m_layer(layer),
3236 m_level(level),
3237 m_desc(desc)
3238{
3239}
3240
3241/*!
3242 \fn int QRhiTextureUploadEntry::layer() const
3243 \return the currently set layer index (cubemap face, array layer). Defaults to 0.
3244 */
3245
3246/*!
3247 \fn void QRhiTextureUploadEntry::setLayer(int layer)
3248 Sets the \a layer.
3249 */
3250
3251/*!
3252 \fn int QRhiTextureUploadEntry::level() const
3253 \return the currently set mip level. Defaults to 0.
3254 */
3255
3256/*!
3257 \fn void QRhiTextureUploadEntry::setLevel(int level)
3258 Sets the mip \a level.
3259 */
3260
3261/*!
3262 \fn QRhiTextureSubresourceUploadDescription QRhiTextureUploadEntry::description() const
3263 \return the currently set subresource description.
3264 */
3265
3266/*!
3267 \fn void QRhiTextureUploadEntry::setDescription(const QRhiTextureSubresourceUploadDescription &desc)
3268 Sets the subresource description \a desc.
3269 */
3270
3271/*!
3272 \class QRhiTextureUploadDescription
3273 \inmodule QtGuiPrivate
3274 \inheaderfile rhi/qrhi.h
3275 \since 6.6
3276 \brief Describes a texture upload operation.
3277
3278 Used with QRhiResourceUpdateBatch::uploadTexture(). That function has two
3279 variants: one taking a QImage and one taking a
3280 QRhiTextureUploadDescription. The former is a convenience version,
3281 internally creating a QRhiTextureUploadDescription with a single image
3282 targeting level 0 for layer 0.
3283
3284 An example of the common, simple case of wanting to upload the contents
3285 of a QImage to a QRhiTexture with a matching pixel size:
3286
3287 \code
3288 QImage image(256, 256, QImage::Format_RGBA8888);
3289 image.fill(Qt::green); // or could use a QPainter targeting image
3290 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256));
3291 texture->create();
3292 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
3293 u->uploadTexture(texture, image);
3294 \endcode
3295
3296 When cubemaps, pre-generated mip images, compressed textures, or partial
3297 uploads are involved, applications will have to use this class instead.
3298
3299 QRhiTextureUploadDescription also enables specifying batched uploads, which
3300 are useful for example when generating an atlas or glyph cache texture:
3301 multiple, partial uploads for the same subresource (meaning the same layer
3302 and level) are supported, and can be, depending on the backend and the
3303 underlying graphics API, more efficient when batched into the same
3304 QRhiTextureUploadDescription as opposed to issuing individual
3305 \l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} commands for
3306 each of them.
3307
3308 \note Cubemaps have one layer for each of the six faces in the order +X,
3309 -X, +Y, -Y, +Z, -Z.
3310
3311 For example, specifying the faces of a cubemap could look like the following:
3312
3313 \code
3314 QImage faces[6];
3315 // ...
3316 QVarLengthArray<QRhiTextureUploadEntry, 6> entries;
3317 for (int i = 0; i < 6; ++i)
3318 entries.append(QRhiTextureUploadEntry(i, 0, faces[i]));
3319 QRhiTextureUploadDescription desc;
3320 desc.setEntries(entries.cbegin(), entries.cend());
3321 resourceUpdates->uploadTexture(texture, desc);
3322 \endcode
3323
3324 Another example that specifies mip images for a compressed texture:
3325
3326 \code
3327 QList<QRhiTextureUploadEntry> entries;
3328 const int mipCount = rhi->mipLevelsForSize(compressedTexture->pixelSize());
3329 for (int level = 0; level < mipCount; ++level) {
3330 const QByteArray compressedDataForLevel = ..
3331 entries.append(QRhiTextureUploadEntry(0, level, compressedDataForLevel));
3332 }
3333 QRhiTextureUploadDescription desc;
3334 desc.setEntries(entries.cbegin(), entries.cend());
3335 resourceUpdates->uploadTexture(compressedTexture, desc);
3336 \endcode
3337
3338 With partial uploads targeting the same subresource, it is recommended to
3339 batch them into a single upload request, whenever possible:
3340
3341 \code
3342 QRhiTextureSubresourceUploadDescription subresDesc(image);
3343 subresDesc.setSourceSize(QSize(10, 10));
3344 subResDesc.setDestinationTopLeft(QPoint(50, 40));
3345 QRhiTextureUploadEntry entry(0, 0, subresDesc); // layer 0, level 0
3346
3347 QRhiTextureSubresourceUploadDescription subresDesc2(image);
3348 subresDesc2.setSourceSize(QSize(30, 40));
3349 subResDesc2.setDestinationTopLeft(QPoint(100, 200));
3350 QRhiTextureUploadEntry entry2(0, 0, subresDesc2); // layer 0, level 0, i.e. same subresource
3351
3352 QRhiTextureUploadDescription desc({ entry, entry2});
3353 resourceUpdates->uploadTexture(texture, desc);
3354 \endcode
3355
3356 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3357 for details.
3358
3359 \sa QRhiResourceUpdateBatch
3360 */
3361
3362/*!
3363 \fn QRhiTextureUploadDescription::QRhiTextureUploadDescription()
3364
3365 Constructs an empty texture upload description.
3366 */
3367
3368/*!
3369 Constructs a texture upload description with a single subresource upload
3370 described by \a entry.
3371 */
3372QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry)
3373{
3374 m_entries.append(entry);
3375}
3376
3377/*!
3378 Constructs a texture upload description with the specified \a list of entries.
3379
3380 \note \a list can also contain multiple QRhiTextureUploadEntry elements
3381 with the same layer and level. This makes sense when those uploads are
3382 partial, meaning their subresource description has a source size or image
3383 smaller than the subresource dimensions, and can be more efficient than
3384 issuing separate uploadTexture()'s.
3385 */
3386QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list)
3387 : m_entries(list)
3388{
3389}
3390
3391/*!
3392 \fn void QRhiTextureUploadDescription::setEntries(std::initializer_list<QRhiTextureUploadEntry> list)
3393 Sets the \a list of entries.
3394 */
3395
3396/*!
3397 \fn template<typename InputIterator> void QRhiTextureUploadDescription::setEntries(InputIterator first, InputIterator last)
3398 Sets the list of entries using the iterators \a first and \a last.
3399 */
3400
3401/*!
3402 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cbeginEntries() const
3403 \return a const iterator pointing to the first item in the entry list.
3404 */
3405
3406/*!
3407 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cendEntries() const
3408 \return a const iterator pointing just after the last item in the entry list.
3409 */
3410
3411/*!
3412 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::entryAt(qsizetype index) const
3413 \return the entry at \a index.
3414 */
3415
3416/*!
3417 \fn qsizetype QRhiTextureUploadDescription::entryCount() const
3418 \return the number of entries.
3419 */
3420
3421/*!
3422 \class QRhiTextureCopyDescription
3423 \inmodule QtGuiPrivate
3424 \inheaderfile rhi/qrhi.h
3425 \since 6.6
3426 \brief Describes a texture-to-texture copy operation.
3427
3428 An empty pixelSize() indicates that the entire subresource is to be copied.
3429 A default constructed copy description therefore leads to copying the
3430 entire subresource at level 0 of layer 0.
3431
3432 \note The source texture must be created with
3433 QRhiTexture::UsedAsTransferSource.
3434
3435 \note The source and destination rectangles defined by pixelSize(),
3436 sourceTopLeft(), and destinationTopLeft() must fit the source and
3437 destination textures, respectively. The behavior is undefined otherwise.
3438
3439 With cubemaps, 3D textures, and texture arrays one face or slice can be
3440 copied at a time. The face or slice is specified by the source and
3441 destination layer indices. With mipmapped textures one mip level can be
3442 copied at a time. The source and destination layer and mip level indices can
3443 differ, but the size and position must be carefully controlled to avoid out
3444 of bounds copies, in which case the behavior is undefined.
3445
3446 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3447 for details.
3448 */
3449
3450/*!
3451 \fn QRhiTextureCopyDescription::QRhiTextureCopyDescription()
3452
3453 Constructs an empty texture copy description.
3454 */
3455
3456/*!
3457 \fn QSize QRhiTextureCopyDescription::pixelSize() const
3458 \return the size of the region to copy.
3459
3460 \note An empty pixelSize() indicates that the entire subresource is to be
3461 copied. A default constructed copy description therefore leads to copying
3462 the entire subresource at level 0 of layer 0.
3463 */
3464
3465/*!
3466 \fn void QRhiTextureCopyDescription::setPixelSize(const QSize &sz)
3467 Sets the size of the region to copy to \a sz.
3468 */
3469
3470/*!
3471 \fn int QRhiTextureCopyDescription::sourceLayer() const
3472 \return the source array layer (cubemap face or array layer index). Defaults to 0.
3473 */
3474
3475/*!
3476 \fn void QRhiTextureCopyDescription::setSourceLayer(int layer)
3477 Sets the source array \a layer.
3478 */
3479
3480/*!
3481 \fn int QRhiTextureCopyDescription::sourceLevel() const
3482 \return the source mip level. Defaults to 0.
3483 */
3484
3485/*!
3486 \fn void QRhiTextureCopyDescription::setSourceLevel(int level)
3487 Sets the source mip \a level.
3488 */
3489
3490/*!
3491 \fn QPoint QRhiTextureCopyDescription::sourceTopLeft() const
3492 \return the source top-left position (in pixels). Defaults to (0, 0).
3493 */
3494
3495/*!
3496 \fn void QRhiTextureCopyDescription::setSourceTopLeft(const QPoint &p)
3497 Sets the source top-left position to \a p.
3498 */
3499
3500/*!
3501 \fn int QRhiTextureCopyDescription::destinationLayer() const
3502 \return the destination array layer (cubemap face or array layer index). Default to 0.
3503 */
3504
3505/*!
3506 \fn void QRhiTextureCopyDescription::setDestinationLayer(int layer)
3507 Sets the destination array \a layer.
3508 */
3509
3510/*!
3511 \fn int QRhiTextureCopyDescription::destinationLevel() const
3512 \return the destionation mip level. Defaults to 0.
3513 */
3514
3515/*!
3516 \fn void QRhiTextureCopyDescription::setDestinationLevel(int level)
3517 Sets the destination mip \a level.
3518 */
3519
3520/*!
3521 \fn QPoint QRhiTextureCopyDescription::destinationTopLeft() const
3522 \return the destionation top-left position in pixels. Defaults to (0, 0).
3523 */
3524
3525/*!
3526 \fn void QRhiTextureCopyDescription::setDestinationTopLeft(const QPoint &p)
3527 Sets the destination top-left position \a p.
3528 */
3529
3530/*!
3531 \class QRhiReadbackDescription
3532 \inmodule QtGuiPrivate
3533 \inheaderfile rhi/qrhi.h
3534 \since 6.6
3535 \brief Describes a readback (reading back texture contents from possibly GPU-only memory) operation.
3536
3537 The source of the readback operation is either a QRhiTexture or the
3538 current backbuffer of the currently targeted QRhiSwapChain. When
3539 texture() is not set, the swapchain is used. Otherwise the specified
3540 QRhiTexture is treated as the source.
3541
3542 \note Textures used in readbacks must be created with
3543 QRhiTexture::UsedAsTransferSource.
3544
3545 \note Swapchains used in readbacks must be created with
3546 QRhiSwapChain::UsedAsTransferSource.
3547
3548 layer() and level() are only applicable when the source is a QRhiTexture.
3549
3550 \note Multisample textures cannot be read back. Readbacks are supported for
3551 multisample swapchain buffers however.
3552
3553 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3554 for details.
3555 */
3556
3557/*!
3558 \fn QRhiReadbackDescription::QRhiReadbackDescription() = default
3559
3560 Constructs an empty texture readback description.
3561
3562 \note The source texture is set to null by default, which is still a valid
3563 readback: it specifies that the backbuffer of the current swapchain is to
3564 be read back. (current meaning the frame's target swapchain at the time of
3565 committing the QRhiResourceUpdateBatch with the
3566 \l{QRhiResourceUpdateBatch::readBackTexture()}{texture readback} on it)
3567 */
3568
3569/*!
3570 Constructs an texture readback description that specifies that level 0 of
3571 layer 0 of \a texture is to be read back.
3572
3573 \note \a texture can also be null in which case this constructor is
3574 identical to the argumentless variant.
3575 */
3576QRhiReadbackDescription::QRhiReadbackDescription(QRhiTexture *texture)
3577 : m_texture(texture)
3578{
3579}
3580
3581/*!
3582 \fn QRhiTexture *QRhiReadbackDescription::texture() const
3583
3584 \return the QRhiTexture that is read back. Can be left set to \nullptr
3585 which indicates that the backbuffer of the current swapchain is to be used
3586 instead.
3587 */
3588
3589/*!
3590 \fn void QRhiReadbackDescription::setTexture(QRhiTexture *tex)
3591
3592 Sets the texture \a tex as the source of the readback operation.
3593
3594 Setting \nullptr is valid too, in which case the current swapchain's
3595 current backbuffer is used. (but then the readback cannot be issued in a
3596 non-swapchain-based frame)
3597
3598 \note Multisample textures cannot be read back. Readbacks are supported for
3599 multisample swapchain buffers however.
3600
3601 \note Textures used in readbacks must be created with
3602 QRhiTexture::UsedAsTransferSource.
3603
3604 \note Swapchains used in readbacks must be created with
3605 QRhiSwapChain::UsedAsTransferSource.
3606 */
3607
3608/*!
3609 \fn int QRhiReadbackDescription::layer() const
3610
3611 \return the currently set array layer (cubemap face, array index). Defaults to 0.
3612
3613 Applicable only when the source of the readback is a QRhiTexture.
3614 */
3615
3616/*!
3617 \fn void QRhiReadbackDescription::setLayer(int layer)
3618 Sets the array \a layer to read back.
3619 */
3620
3621/*!
3622 \fn int QRhiReadbackDescription::level() const
3623
3624 \return the currently set mip level. Defaults to 0.
3625
3626 Applicable only when the source of the readback is a QRhiTexture.
3627 */
3628
3629/*!
3630 \fn void QRhiReadbackDescription::setLevel(int level)
3631 Sets the mip \a level to read back.
3632 */
3633
3634/*!
3635 \fn const QRect &QRhiReadbackDescription::rect() const
3636 \since 6.10
3637
3638 \return the rectangle to read back. Defaults to an invalid rectangle.
3639
3640 If invalid, the entire texture or swapchain backbuffer is read back.
3641 */
3642
3643/*!
3644 \fn void QRhiReadbackDescription::setRect(const QRect &rectangle)
3645 \since 6.10
3646
3647 Sets the \a rectangle to read back.
3648 */
3649
3650/*!
3651 \class QRhiReadbackResult
3652 \inmodule QtGuiPrivate
3653 \inheaderfile rhi/qrhi.h
3654 \since 6.6
3655 \brief Describes the results of a potentially asynchronous buffer or texture readback operation.
3656
3657 When \l completed is set, the function is invoked when the \l data is
3658 available. \l format and \l pixelSize are set upon completion together with
3659 \l data.
3660
3661 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3662 for details.
3663 */
3664
3665/*!
3666 \variable QRhiReadbackResult::completed
3667
3668 Callback that is invoked upon completion, on the thread the QRhi operates
3669 on. Can be left set to \nullptr, in which case no callback is invoked.
3670 */
3671
3672/*!
3673 \variable QRhiReadbackResult::format
3674
3675 Valid only for textures, the texture format.
3676 */
3677
3678/*!
3679 \variable QRhiReadbackResult::pixelSize
3680
3681 Valid only for textures, the size in pixels.
3682 */
3683
3684/*!
3685 \variable QRhiReadbackResult::data
3686
3687 The buffer or image data.
3688
3689 \sa QRhiResourceUpdateBatch::readBackTexture(), QRhiResourceUpdateBatch::readBackBuffer()
3690 */
3691
3692
3693/*!
3694 \class QRhiNativeHandles
3695 \inmodule QtGuiPrivate
3696 \inheaderfile rhi/qrhi.h
3697 \since 6.6
3698 \brief Base class for classes exposing backend-specific collections of native resource objects.
3699
3700 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3701 for details.
3702 */
3703
3704/*!
3705 \class QRhiResource
3706 \inmodule QtGuiPrivate
3707 \inheaderfile rhi/qrhi.h
3708 \since 6.6
3709 \brief Base class for classes encapsulating native resource objects.
3710
3711 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3712 for details.
3713 */
3714
3715/*!
3716 \enum QRhiResource::Type
3717 Specifies type of the resource.
3718
3719 \value Buffer
3720 \value Texture
3721 \value Sampler
3722 \value RenderBuffer
3723 \value RenderPassDescriptor
3724 \value SwapChainRenderTarget
3725 \value TextureRenderTarget
3726 \value ShaderResourceBindings
3727 \value GraphicsPipeline
3728 \value SwapChain
3729 \value ComputePipeline
3730 \value CommandBuffer
3731 \value ShadingRateMap
3732 \value [since 6.13] IndirectCommandBuffer
3733 */
3734
3735/*!
3736 \fn virtual QRhiResource::Type QRhiResource::resourceType() const = 0
3737
3738 \return the type of the resource.
3739 */
3740
3741/*!
3742 \internal
3743 */
3744QRhiResource::QRhiResource(QRhiImplementation *rhi)
3745 : m_rhi(rhi)
3746{
3747 m_id = QRhiGlobalObjectIdGenerator::newId();
3748}
3749
3750/*!
3751 Destructor.
3752
3753 Releases (or requests deferred releasing of) the underlying native graphics
3754 resources, if there are any.
3755
3756 \note Resources referenced by commands for the current frame should not be
3757 released until the frame is submitted by QRhi::endFrame().
3758
3759 \sa destroy()
3760 */
3761QRhiResource::~QRhiResource()
3762{
3763 // destroy() cannot be called here, due to virtuals; it is up to the
3764 // subclasses to do that.
3765}
3766
3767/*!
3768 \fn virtual void QRhiResource::destroy() = 0
3769
3770 Releases (or requests deferred releasing of) the underlying native graphics
3771 resources. Safe to call multiple times, subsequent invocations will be a
3772 no-op then.
3773
3774 Once destroy() is called, the QRhiResource instance can be reused, by
3775 calling \c create() again. That will then result in creating new native
3776 graphics resources underneath.
3777
3778 \note Resources referenced by commands for the current frame should not be
3779 released until the frame is submitted by QRhi::endFrame().
3780
3781 The QRhiResource destructor also performs the same task, so calling this
3782 function is not necessary before deleting a QRhiResource.
3783
3784 \sa deleteLater()
3785 */
3786
3787/*!
3788 When called without a frame being recorded, this function is equivalent to
3789 deleting the object. Between a QRhi::beginFrame() and QRhi::endFrame()
3790 however the behavior is different: the QRhiResource will not be destroyed
3791 until the frame is submitted via QRhi::endFrame(), thus satisfying the QRhi
3792 requirement of not altering QRhiResource objects that are referenced by the
3793 frame being recorded.
3794
3795 If the QRhi that created this object is already destroyed, the object is
3796 deleted immediately.
3797
3798 Using deleteLater() can be a useful convenience in many cases, and it
3799 complements the low-level guarantee (that the underlying native graphics
3800 objects are never destroyed until it is safe to do so and it is known for
3801 sure that they are not used by the GPU in an still in-flight frame), by
3802 offering a way to make sure the C++ object instances (of QRhiBuffer,
3803 QRhiTexture, etc.) themselves also stay valid until the end of the current
3804 frame.
3805
3806 The following example shows a convenient way of creating a throwaway buffer
3807 that is only used in one frame and gets automatically released in
3808 endFrame(). (when it comes to the underlying native buffer(s), the usual
3809 guarantee applies: the QRhi backend defers the releasing of those until it
3810 is guaranteed that the frame in which the buffer is accessed by the GPU has
3811 completed)
3812
3813 \code
3814 rhi->beginFrame(swapchain);
3815 QRhiBuffer *buf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, 256);
3816 buf->deleteLater(); // !
3817 u = rhi->nextResourceUpdateBatch();
3818 u->uploadStaticBuffer(buf, data);
3819 // ... draw with buf
3820 rhi->endFrame();
3821 \endcode
3822
3823 \sa destroy()
3824 */
3825void QRhiResource::deleteLater()
3826{
3827 if (m_rhi)
3828 m_rhi->addDeleteLater(this);
3829 else
3830 delete this;
3831}
3832
3833/*!
3834 \return the currently set object name. By default the name is empty.
3835 */
3836QByteArray QRhiResource::name() const
3837{
3838 return m_objectName;
3839}
3840
3841/*!
3842 Sets a \a name for the object.
3843
3844 This allows getting descriptive names for the native graphics
3845 resources visible in graphics debugging tools, such as
3846 \l{https://renderdoc.org/}{RenderDoc} and
3847 \l{https://developer.apple.com/xcode/}{XCode}.
3848
3849 When it comes to naming native objects by relaying the name via the
3850 appropriate graphics API, note that the name is ignored when
3851 QRhi::DebugMarkers are not supported, and may, depending on the backend,
3852 also be ignored when QRhi::EnableDebugMarkers is not set.
3853
3854 \note The name may be ignored for objects other than buffers,
3855 renderbuffers, and textures, depending on the backend.
3856
3857 \note The name may be modified. For slotted resources, such as a QRhiBuffer
3858 backed by multiple native buffers, QRhi will append a suffix to make the
3859 underlying native buffers easily distinguishable from each other.
3860 */
3861void QRhiResource::setName(const QByteArray &name)
3862{
3863 m_objectName = name;
3864}
3865
3866/*!
3867 \return the global, unique identifier of this QRhiResource.
3868
3869 User code rarely needs to deal with the value directly. It is used
3870 internally for tracking and bookkeeping purposes.
3871 */
3872quint64 QRhiResource::globalResourceId() const
3873{
3874 return m_id;
3875}
3876
3877/*!
3878 \return the QRhi that created this resource.
3879
3880 If the QRhi that created this object is already destroyed, the result is
3881 \nullptr.
3882 */
3883QRhi *QRhiResource::rhi() const
3884{
3885 return m_rhi ? m_rhi->q : nullptr;
3886}
3887
3888/*!
3889 \class QRhiBuffer
3890 \inmodule QtGuiPrivate
3891 \inheaderfile rhi/qrhi.h
3892 \since 6.6
3893 \brief Vertex, index, or uniform (constant) buffer resource.
3894
3895 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3896 for details.
3897
3898 A QRhiBuffer encapsulates zero, one, or more native buffer objects (such as
3899 a \c VkBuffer or \c MTLBuffer). With some graphics APIs and backends
3900 certain types of buffers may not use a native buffer object at all (e.g.
3901 OpenGL if uniform buffer objects are not used), but this is transparent to
3902 the user of the QRhiBuffer API. Similarly, the fact that some types of
3903 buffers may use two or three native buffers underneath, in order to allow
3904 efficient per-frame content update without stalling the GPU pipeline, is
3905 mostly invisible to the applications and libraries.
3906
3907 A QRhiBuffer instance is always created by calling
3908 \l{QRhi::newBuffer()}{the QRhi's newBuffer() function}. This creates no
3909 native graphics resources. To do that, call create() after setting the
3910 appropriate options, such as the type, usage flags, size, although in most cases these
3911 are already set based on the arguments passed to
3912 \l{QRhi::newBuffer()}{newBuffer()}.
3913
3914 \section2 Example usage
3915
3916 To create a uniform buffer for a shader where the GLSL uniform block
3917 contains a single \c mat4 member, and update the contents:
3918
3919 \code
3920 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64);
3921 if (!ubuf->create()) { error(); }
3922 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3923 QMatrix4x4 mvp;
3924 // ... set up the modelview-projection matrix
3925 batch->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
3926 // ...
3927 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
3928 \endcode
3929
3930 An example of creating a buffer with vertex data:
3931
3932 \code
3933 const float vertices[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f };
3934 QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices));
3935 if (!vbuf->create()) { error(); }
3936 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3937 batch->uploadStaticBuffer(vbuf, vertices);
3938 // ...
3939 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
3940 \endcode
3941
3942 An index buffer:
3943
3944 \code
3945 static const quint16 indices[] = { 0, 1, 2 };
3946 QRhiBuffer *ibuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices));
3947 if (!ibuf->create()) { error(); }
3948 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3949 batch->uploadStaticBuffer(ibuf, indices);
3950 // ...
3951 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
3952 \endcode
3953
3954 \section2 Common patterns
3955
3956 A call to create() destroys any existing native resources if create() was
3957 successfully called before. If those native resources are still in use by
3958 an in-flight frame (i.e., there's a chance they are still read by the GPU),
3959 the destroying of those resources is deferred automatically. Thus a very
3960 common and convenient pattern to safely increase the size of an already
3961 initialized buffer is the following. In practice this drops and creates a
3962 whole new set of native resources underneath, so it is not necessarily a
3963 cheap operation, but is more convenient and still faster than the
3964 alternatives, because by not destroying the \c buf object itself, all
3965 references to it stay valid in other data structures (e.g., in any
3966 QRhiShaderResourceBinding the QRhiBuffer is referenced from).
3967
3968 \code
3969 if (buf->size() < newSize) {
3970 buf->setSize(newSize);
3971 if (!buf->create()) { error(); }
3972 }
3973 // continue using buf, fill it with new data
3974 \endcode
3975
3976 When working with uniform buffers, it will sometimes be necessary to
3977 combine data for multiple draw calls into a single buffer for efficiency
3978 reasons. Be aware of the aligment requirements: with some graphics APIs
3979 offsets for a uniform buffer must be aligned to 256 bytes. This applies
3980 both to QRhiShaderResourceBinding and to the dynamic offsets passed to
3981 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}. Use the
3982 \l{QRhi::ubufAlignment()}{ubufAlignment()} and
3983 \l{QRhi::ubufAligned()}{ubufAligned()} functions to create portable code.
3984 As an example, the following is an outline for issuing multiple (\c N) draw
3985 calls with the same pipeline and geometry, but with a different data in the
3986 uniform buffers exposed at binding point 0. This assumes the buffer is
3987 exposed via
3988 \l{QRhiShaderResourceBinding::uniformBufferWithDynamicOffset()}{uniformBufferWithDynamicOffset()}
3989 which allows passing a QRhiCommandBuffer::DynamicOffset list to
3990 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}.
3991
3992 \code
3993 const int N = 2;
3994 const int UB_SIZE = 64 + 4; // assuming a uniform block with { mat4 matrix; float opacity; }
3995 const int ONE_UBUF_SIZE = rhi->ubufAligned(UB_SIZE);
3996 const int TOTAL_UBUF_SIZE = N * ONE_UBUF_SIZE;
3997 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, TOTAL_UBUF_SIZE);
3998 if (!ubuf->create()) { error(); }
3999 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4000 for (int i = 0; i < N; ++i) {
4001 batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE, 64, matrix.constData());
4002 batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE + 64, 4, &opacity);
4003 }
4004 // ...
4005 // beginPass(), set pipeline, etc., and then:
4006 for (int i = 0; i < N; ++i) {
4007 QRhiCommandBuffer::DynamicOffset dynOfs[] = { { 0, i * ONE_UBUF_SIZE } };
4008 cb->setShaderResources(srb, 1, dynOfs);
4009 cb->draw(36);
4010 }
4011 \endcode
4012
4013 \sa QRhiResourceUpdateBatch, QRhi, QRhiCommandBuffer
4014 */
4015
4016/*!
4017 \enum QRhiBuffer::Type
4018 Specifies storage type of buffer resource.
4019
4020 \value Immutable Indicates that the data is not expected to change ever
4021 after the initial upload. Under the hood such buffer resources are
4022 typically placed in device local (GPU) memory (on systems where
4023 applicable). Uploading new data is possible, but may be expensive. The
4024 upload typically happens by copying to a separate, host visible staging
4025 buffer from which a GPU buffer-to-buffer copy is issued into the actual
4026 GPU-only buffer.
4027
4028 \value Static Indicates that the data is expected to change only
4029 infrequently. Typically placed in device local (GPU) memory, where
4030 applicable. On backends where host visible staging buffers are used for
4031 uploading, the staging buffers are kept around for this type, unlike with
4032 Immutable, so subsequent uploads do not suffer in performance. Frequent
4033 updates, especially updates in consecutive frames, should be avoided.
4034
4035 \value Dynamic Indicates that the data is expected to change frequently.
4036 Not recommended for large buffers. Typically backed by host visible memory
4037 in 2 copies in order to allow for changing without stalling the graphics
4038 pipeline. The double buffering is managed transparently to the applications
4039 and is not exposed in the API here in any form. This is the recommended,
4040 and, with some backends, the only possible, type for buffers with
4041 UniformBuffer usage.
4042 */
4043
4044/*!
4045 \enum QRhiBuffer::UsageFlag
4046 Flag values to specify how the buffer is going to be used.
4047
4048 \value VertexBuffer Vertex buffer. This allows the QRhiBuffer to be used in
4049 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
4050
4051 \value IndexBuffer Index buffer. This allows the QRhiBuffer to be used in
4052 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
4053
4054 \value UniformBuffer Uniform buffer (also called constant buffer). This
4055 allows the QRhiBuffer to be used in combination with
4056 \l{QRhiShaderResourceBinding::UniformBuffer}{UniformBuffer}. When
4057 \l{QRhi::NonDynamicUniformBuffers}{NonDynamicUniformBuffers} is reported as
4058 not supported, this usage can only be combined with the type Dynamic.
4059
4060 \value StorageBuffer Storage buffer. This allows the QRhiBuffer to be used
4061 in combination with \l{QRhiShaderResourceBinding::BufferLoad}{BufferLoad},
4062 \l{QRhiShaderResourceBinding::BufferStore}{BufferStore}, or
4063 \l{QRhiShaderResourceBinding::BufferLoadStore}{BufferLoadStore}. This usage
4064 can only be combined with the types Immutable or Static, and is only
4065 available when the \l{QRhi::Compute}{Compute feature} is reported as
4066 supported.
4067
4068 \value [since 6.12] IndirectBuffer Indirect draw or dispatch buffer. This
4069 allows the QRhiBuffer to be used in
4070 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()},
4071 \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}, and
4072 \l{QRhiCommandBuffer::dispatchIndirect()}{dispatchIndirect()}.
4073 This usage can be combined with types Immutable or Static. Combining it with
4074 Dynamic is unsupported with D3D11, where create() will fail. This usage may
4075 also be combined with StorageBuffer on backends that support
4076 \l{QRhi::Compute}{compute shaders}, allowing indirect draw or dispatch
4077 commands to be generated by compute shaders and consumed by indirect
4078 draw/dispatch calls.
4079 */
4080
4081/*!
4082 \class QRhiBuffer::NativeBuffer
4083 \inmodule QtGuiPrivate
4084 \inheaderfile rhi/qrhi.h
4085 \brief Contains information about the underlying native resources of a buffer.
4086 */
4087
4088/*!
4089 \variable QRhiBuffer::NativeBuffer::objects
4090 \brief an array with pointers to the native object handles.
4091
4092 With OpenGL, the native handle is a GLuint value, so the elements in the \c
4093 objects array are pointers to a GLuint. With Vulkan, the native handle is a
4094 VkBuffer, so the elements of the array are pointers to a VkBuffer. With
4095 Direct3D 11 and Metal the elements are pointers to a ID3D11Buffer or
4096 MTLBuffer pointer, respectively. With Direct3D 12, the elements are
4097 pointers to a ID3D12Resource.
4098
4099 \note Pay attention to the fact that the elements are always pointers to
4100 the native buffer handle type, even if the native type itself is a pointer.
4101 (so the elements are \c{VkBuffer *} on Vulkan, even though VkBuffer itself
4102 is a pointer on 64-bit architectures).
4103 */
4104
4105/*!
4106 \variable QRhiBuffer::NativeBuffer::slotCount
4107 \brief Specifies the number of valid elements in the objects array.
4108
4109 The value can be 0, 1, 2, or 3 in practice. 0 indicates that the QRhiBuffer
4110 is not backed by any native buffer objects. This can happen with
4111 QRhiBuffers with the usage UniformBuffer when the underlying API does not
4112 support (or the backend chooses not to use) native uniform buffers. 1 is
4113 commonly used for Immutable and Static types (but some backends may
4114 differ). 2 or 3 is typical when the type is Dynamic (but some backends may
4115 differ).
4116
4117 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4118 */
4119
4120/*!
4121 \internal
4122 */
4123QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, quint32 size_)
4124 : QRhiResource(rhi),
4125 m_type(type_), m_usage(usage_), m_size(size_)
4126{
4127}
4128
4129/*!
4130 \return the resource type.
4131 */
4132QRhiResource::Type QRhiBuffer::resourceType() const
4133{
4134 return Buffer;
4135}
4136
4137/*!
4138 \fn virtual bool QRhiBuffer::create() = 0
4139
4140 Creates the corresponding native graphics resources. If there are already
4141 resources present due to an earlier create() with no corresponding
4142 destroy(), then destroy() is called implicitly first.
4143
4144 \return \c true when successful, \c false when a graphics operation failed.
4145 Regardless of the return value, calling destroy() is always safe.
4146 */
4147
4148/*!
4149 \fn QRhiBuffer::Type QRhiBuffer::type() const
4150 \return the buffer type.
4151 */
4152
4153/*!
4154 \fn void QRhiBuffer::setType(Type t)
4155 Sets the buffer's type to \a t.
4156 */
4157
4158/*!
4159 \fn QRhiBuffer::UsageFlags QRhiBuffer::usage() const
4160 \return the buffer's usage flags.
4161 */
4162
4163/*!
4164 \fn void QRhiBuffer::setUsage(UsageFlags u)
4165 Sets the buffer's usage flags to \a u.
4166 */
4167
4168/*!
4169 \fn quint32 QRhiBuffer::size() const
4170
4171 \return the buffer's size in bytes.
4172
4173 This is always the value that was passed to setSize() or QRhi::newBuffer().
4174 Internally, the native buffers may be bigger if that is required by the
4175 underlying graphics API.
4176 */
4177
4178/*!
4179 \fn void QRhiBuffer::setSize(quint32 sz)
4180
4181 Sets the size of the buffer in bytes. The size is normally specified in
4182 QRhi::newBuffer() so this function is only used when the size has to be
4183 changed. As with other setters, the size only takes effect when calling
4184 create(), and for already created buffers this involves releasing the previous
4185 native resource and creating new ones under the hood.
4186
4187 Backends may choose to allocate buffers bigger than \a sz in order to
4188 fulfill alignment requirements. This is hidden from the applications and
4189 size() will always report the size requested in \a sz.
4190 */
4191
4192/*!
4193 \return the underlying native resources for this buffer. The returned value
4194 will be empty if exposing the underlying native resources is not supported by
4195 the backend.
4196
4197 A QRhiBuffer may be backed by multiple native buffer objects, depending on
4198 the type() and the QRhi backend in use. When this is the case, all of them
4199 are returned in the objects array in the returned struct, with slotCount
4200 specifying the number of native buffer objects. While
4201 \l{QRhi::beginFrame()}{recording a frame}, QRhi::currentFrameSlot() can be
4202 used to determine which of the native buffers QRhi is using for operations
4203 that read or write from this QRhiBuffer within the frame being recorded.
4204
4205 In some cases a QRhiBuffer will not be backed by a native buffer object at
4206 all. In this case slotCount will be set to 0 and no valid native objects
4207 are returned. This is not an error, and is perfectly valid when a given
4208 backend does not use native buffers for QRhiBuffers with certain types or
4209 usages.
4210
4211 \note Be aware that QRhi backends may employ various buffer update
4212 strategies. Unlike textures, where uploading image data always means
4213 recording a buffer-to-image (or similar) copy command on the command
4214 buffer, buffers, in particular Dynamic and UniformBuffer ones, can operate
4215 in many different ways. For example, a QRhiBuffer with usage type
4216 UniformBuffer may not even be backed by a native buffer object at all if
4217 uniform buffers are not used or supported by a given backend and graphics
4218 API. There are also differences to how data is written to the buffer and
4219 the type of backing memory used. For buffers backed by host visible memory,
4220 calling this function guarantees that pending host writes are executed for
4221 all the returned native buffers.
4222
4223 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4224 */
4225QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
4226{
4227 return { {}, 0 };
4228}
4229
4230/*!
4231 \return a pointer to a memory block with the host visible buffer data.
4232
4233 This is a shortcut for medium-to-large dynamic uniform buffers that have
4234 their \b entire contents (or at least all regions that are read by the
4235 shaders in the current frame) changed \b{in every frame} and the
4236 QRhiResourceUpdateBatch-based update mechanism is seen too heavy due to the
4237 amount of data copying involved.
4238
4239 The call to this function must be eventually followed by a call to
4240 endFullDynamicUniformBufferUpdateForCurrentFrame(), before recording any
4241 render or compute pass that relies on this buffer.
4242
4243 \warning Updating data via this method is not compatible with
4244 QRhiResourceUpdateBatch-based updates and readbacks. Unexpected behavior
4245 may occur when attempting to combine the two update models for the same
4246 buffer. Similarly, the data updated this direct way may not be visible to
4247 \l{QRhiResourceUpdateBatch::readBackBuffer()}{readBackBuffer operations},
4248 depending on the backend.
4249
4250 \warning When updating buffer data via this method, the update must be done
4251 in every frame, otherwise backends that perform double or triple buffering
4252 of resources may end up in unexpected behavior.
4253
4254 \warning Partial updates are not possible with this approach since some
4255 backends may choose a strategy where the previous contents of the buffer is
4256 lost upon calling this function. Data must be written to all regions that
4257 are read by shaders in the frame currently being prepared.
4258
4259 \warning This function can only be called when recording a frame, so
4260 between QRhi::beginFrame() and QRhi::endFrame().
4261
4262 \warning This function can only be called on Dynamic buffers.
4263 */
4264char *QRhiBuffer::beginFullDynamicBufferUpdateForCurrentFrame()
4265{
4266 return nullptr;
4267}
4268
4269/*!
4270 To be called when the entire contents of the buffer data has been updated
4271 in the memory block returned from
4272 beginFullDynamicBufferUpdateForCurrentFrame().
4273 */
4274void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
4275{
4276}
4277
4278/*!
4279 \internal
4280 */
4281void QRhiBuffer::fullDynamicBufferUpdateForCurrentFrame(const void *data, quint32 size)
4282{
4283 char *p = beginFullDynamicBufferUpdateForCurrentFrame();
4284 if (p) {
4285 memcpy(p, data, size > 0 ? size : m_size);
4286 endFullDynamicBufferUpdateForCurrentFrame();
4287 }
4288}
4289
4290/*!
4291 \class QRhiRenderBuffer
4292 \inmodule QtGuiPrivate
4293 \inheaderfile rhi/qrhi.h
4294 \since 6.6
4295 \brief Renderbuffer resource.
4296
4297 Renderbuffers cannot be sampled or read but have some benefits over
4298 textures in some cases:
4299
4300 A \l DepthStencil renderbuffer may be lazily allocated and be backed by
4301 transient memory with some APIs. On some platforms this may mean the
4302 depth/stencil buffer uses no physical backing at all.
4303
4304 That transient nature has a consequence: the contents of a \l DepthStencil
4305 renderbuffer are not guaranteed to survive if a backend has to interrupt and
4306 restart a render pass internally. With Metal this happens when a draw call
4307 is implemented via indirect command buffers, which is the case for
4308 \l{QRhiCommandBuffer::drawIndirectCount()}{drawIndirectCount()} and its
4309 indexed variant, for a high draw count
4310 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()} or
4311 \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}, and
4312 also when tessellation is used. Draws recorded after such a call then
4313 depth-test against a depth buffer that lost its contents. When this matters,
4314 set the \l NoTransientBacking flag, which makes the contents preservable at
4315 the cost of the memory and bandwidth that the transient backing was saving.
4316 Alternatively, where a QRhiTextureRenderTarget is used anyway, attach a depth
4317 or depth-stencil QRhiTexture with
4318 \l{QRhiTextureRenderTargetDescription::setDepthTexture()}{setDepthTexture()}
4319 instead of a renderbuffer: that is preserved across an interruption, unless
4320 QRhiTextureRenderTarget::DoNotStoreDepthStencilContents is set.
4321
4322 Note that the indirect drawing cases above are avoidable. A
4323 QRhiIndirectCommandBuffer executed with
4324 \l{QRhiCommandBuffer::executeIndirect()}{executeIndirect()} is prepared
4325 before the render pass begins, so it never interrupts the pass however many
4326 commands it holds, and none of this applies to it. Only tessellation then
4327 remains as a reason to consider \l NoTransientBacking.
4328
4329 \l Color renderbuffers are useful since QRhi::MultisampleRenderBuffer may be
4330 supported even when QRhi::MultisampleTexture is not.
4331
4332 How the renderbuffer is implemented by a backend is not exposed to the
4333 applications. In some cases it may be backed by ordinary textures, while in
4334 others there may be a different kind of native resource used.
4335
4336 Renderbuffers that are used as (and are only used as) depth-stencil buffers
4337 in combination with a QRhiSwapChain's color buffers should have the
4338 UsedWithSwapChainOnly flag set. This serves a double purpose: such buffers,
4339 depending on the backend and the underlying APIs, be more efficient, and
4340 QRhi provides automatic sizing behavior to match the color buffers, which
4341 means calling setPixelSize() and create() are not necessary for such
4342 renderbuffers.
4343
4344 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4345 for details.
4346 */
4347
4348/*!
4349 \enum QRhiRenderBuffer::Type
4350 Specifies the type of the renderbuffer
4351
4352 \value DepthStencil Combined depth/stencil
4353 \value Color Color
4354 */
4355
4356/*!
4357 \struct QRhiRenderBuffer::NativeRenderBuffer
4358 \inmodule QtGuiPrivate
4359 \inheaderfile rhi/qrhi.h
4360 \brief Wraps a native renderbuffer object.
4361 */
4362
4363/*!
4364 \variable QRhiRenderBuffer::NativeRenderBuffer::object
4365 \brief 64-bit integer containing the native object handle.
4366
4367 Used with QRhiRenderBuffer::createFrom().
4368
4369 With OpenGL the native handle is a GLuint value. \c object is expected to
4370 be a valid OpenGL renderbuffer object ID.
4371 */
4372
4373/*!
4374 \enum QRhiRenderBuffer::Flag
4375 Flag values for flags() and setFlags()
4376
4377 \value UsedWithSwapChainOnly For DepthStencil renderbuffers this indicates
4378 that the renderbuffer is only used in combination with a QRhiSwapChain, and
4379 never in any other way. This provides automatic sizing and resource
4380 rebuilding, so calling setPixelSize() or create() is not needed whenever
4381 this flag is set. This flag value may also trigger backend-specific
4382 behavior, for example with OpenGL, where a separate windowing system
4383 interface API is in use (EGL, GLX, etc.), the flag is especially important
4384 as it avoids creating any actual renderbuffer resource as there is already
4385 a windowing system provided depth/stencil buffer as requested by
4386 QSurfaceFormat.
4387
4388 \value [since 6.13] NoTransientBacking Requests that the renderbuffer is not
4389 backed by transient, lazily allocated memory. Only relevant for
4390 \l DepthStencil renderbuffers, and only with backends that would otherwise
4391 choose such storage, which in practice means Metal on Apple GPUs. Set this
4392 when the contents have to survive a render pass being interrupted and
4393 continued internally by a backend, as described in the
4394 \l{QRhiRenderBuffer}{class documentation}. It costs actual memory and
4395 bandwidth for the depth/stencil buffer, so do not set it when not needed.
4396 In particular it is not needed on account of
4397 \l{QRhiCommandBuffer::executeIndirect()}{executeIndirect()}, which never
4398 interrupts the pass.
4399 */
4400
4401/*!
4402 \internal
4403 */
4404QRhiRenderBuffer::QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
4405 int sampleCount_, Flags flags_,
4406 QRhiTexture::Format backingFormatHint_)
4407 : QRhiResource(rhi),
4408 m_type(type_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_),
4409 m_backingFormatHint(backingFormatHint_)
4410{
4411}
4412
4413/*!
4414 \return the resource type.
4415 */
4416QRhiResource::Type QRhiRenderBuffer::resourceType() const
4417{
4418 return RenderBuffer;
4419}
4420
4421/*!
4422 \fn virtual bool QRhiRenderBuffer::create() = 0
4423
4424 Creates the corresponding native graphics resources. If there are already
4425 resources present due to an earlier create() with no corresponding
4426 destroy(), then destroy() is called implicitly first.
4427
4428 \return \c true when successful, \c false when a graphics operation failed.
4429 Regardless of the return value, calling destroy() is always safe.
4430 */
4431
4432/*!
4433 Similar to create() except that no new native renderbuffer objects are
4434 created. Instead, the native renderbuffer object specified by \a src is
4435 used.
4436
4437 This allows importing an existing renderbuffer object (which must belong to
4438 the same device or sharing context, depending on the graphics API) from an
4439 external graphics engine.
4440
4441 \note This is currently applicable to OpenGL only. This function exists
4442 solely to allow importing a renderbuffer object that is bound to some
4443 special, external object, such as an EGLImageKHR. Once the application
4444 performed the glEGLImageTargetRenderbufferStorageOES call, the renderbuffer
4445 object can be passed to this function to create a wrapping
4446 QRhiRenderBuffer, which in turn can be passed in as a color attachment to
4447 a QRhiTextureRenderTarget to enable rendering to the EGLImage.
4448
4449 \note pixelSize(), sampleCount(), and flags() must still be set correctly.
4450 Passing incorrect sizes and other values to QRhi::newRenderBuffer() and
4451 then following it with a createFrom() expecting that the native
4452 renderbuffer object alone is sufficient to deduce such values is \b wrong
4453 and will lead to problems.
4454
4455 \note QRhiRenderBuffer does not take ownership of the native object, and
4456 destroy() will not release that object.
4457
4458 \note This function is only implemented when the QRhi::RenderBufferImport
4459 feature is reported as \l{QRhi::isFeatureSupported()}{supported}. Otherwise,
4460 the function does nothing and the return value is \c false.
4461
4462 \return \c true when successful, \c false when not supported.
4463 */
4464bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
4465{
4466 Q_UNUSED(src);
4467 return false;
4468}
4469
4470/*!
4471 \fn QRhiRenderBuffer::Type QRhiRenderBuffer::type() const
4472 \return the renderbuffer type.
4473 */
4474
4475/*!
4476 \fn void QRhiRenderBuffer::setType(Type t)
4477 Sets the type to \a t.
4478 */
4479
4480/*!
4481 \fn QSize QRhiRenderBuffer::pixelSize() const
4482 \return the pixel size.
4483 */
4484
4485/*!
4486 \fn void QRhiRenderBuffer::setPixelSize(const QSize &sz)
4487 Sets the size (in pixels) to \a sz.
4488 */
4489
4490/*!
4491 \fn int QRhiRenderBuffer::sampleCount() const
4492 \return the sample count. 1 means no multisample antialiasing.
4493 */
4494
4495/*!
4496 \fn void QRhiRenderBuffer::setSampleCount(int s)
4497 Sets the sample count to \a s.
4498 */
4499
4500/*!
4501 \fn QRhiRenderBuffer::Flags QRhiRenderBuffer::flags() const
4502 \return the flags.
4503 */
4504
4505/*!
4506 \fn void QRhiRenderBuffer::setFlags(Flags f)
4507 Sets the flags to \a f.
4508 */
4509
4510/*!
4511 \fn virtual QRhiTexture::Format QRhiRenderBuffer::backingFormat() const = 0
4512
4513 \internal
4514 */
4515
4516/*!
4517 \class QRhiTexture
4518 \inmodule QtGuiPrivate
4519 \inheaderfile rhi/qrhi.h
4520 \since 6.6
4521 \brief Texture resource.
4522
4523 A QRhiTexture encapsulates a native texture object, such as a \c VkImage or
4524 \c MTLTexture.
4525
4526 A QRhiTexture instance is always created by calling
4527 \l{QRhi::newTexture()}{the QRhi's newTexture() function}. This creates no
4528 native graphics resources. To do that, call create() after setting the
4529 appropriate options, such as the format and size, although in most cases
4530 these are already set based on the arguments passed to
4531 \l{QRhi::newTexture()}{newTexture()}.
4532
4533 Setting the \l{QRhiTexture::Flags}{flags} correctly is essential, otherwise
4534 various errors can occur depending on the underlying QRhi backend and
4535 graphics API. For example, when a texture will be rendered into from a
4536 render pass via QRhiTextureRenderTarget, the texture must be created with
4537 the \l RenderTarget flag set. Similarly, when the texture is going to be
4538 \l{QRhiResourceUpdateBatch::readBackTexture()}{read back}, the \l
4539 UsedAsTransferSource flag must be set upfront. Mipmapped textures must have
4540 the MipMapped flag set. And so on. It is not possible to change the flags
4541 once create() has succeeded. To release the existing and create a new
4542 native texture object with the changed settings, call the setters and call
4543 create() again. This then might be a potentially expensive operation.
4544
4545 \section2 Example usage
4546
4547 To create a 2D texture with a size of 512x512 pixels and set its contents to all green:
4548
4549 \code
4550 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512));
4551 if (!texture->create()) { error(); }
4552 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4553 QImage image(512, 512, QImage::Format_RGBA8888);
4554 image.fill(Qt::green);
4555 batch->uploadTexture(texture, image);
4556 // ...
4557 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4558 \endcode
4559
4560 \section2 Common patterns
4561
4562 A call to create() destroys any existing native resources if create() was
4563 successfully called before. If those native resources are still in use by
4564 an in-flight frame (i.e., there's a chance they are still read by the GPU),
4565 the destroying of those resources is deferred automatically. Thus a very
4566 common and convenient pattern to safely change the size of an already
4567 existing texture is the following. In practice this drops and creates a
4568 whole new native texture resource underneath, so it is not necessarily a
4569 cheap operation, but is more convenient and still faster than the
4570 alternatives, because by not destroying the \c texture object itself, all
4571 references to it stay valid in other data structures (e.g., in any
4572 QShaderResourceBinding the QRhiTexture is referenced from).
4573
4574 \code
4575 // determine newSize, e.g. based on the swapchain's output size or other factors
4576 if (texture->pixelSize() != newSize) {
4577 texture->setPixelSize(newSize);
4578 if (!texture->create()) { error(); }
4579 }
4580 // continue using texture, fill it with new data
4581 \endcode
4582
4583 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4584 for details.
4585
4586 \sa QRhiResourceUpdateBatch, QRhi, QRhiTextureRenderTarget
4587 */
4588
4589/*!
4590 \enum QRhiTexture::Flag
4591
4592 Flag values to specify how the texture is going to be used. Not honoring
4593 the flags set before create() and attempting to use the texture in ways that
4594 was not declared upfront can lead to unspecified behavior or decreased
4595 performance depending on the backend and the underlying graphics API.
4596
4597 \value RenderTarget The texture going to be used in combination with
4598 QRhiTextureRenderTarget.
4599
4600 \value CubeMap The texture is a cubemap. Such textures have 6 layers, one
4601 for each face in the order of +X, -X, +Y, -Y, +Z, -Z. Cubemap textures
4602 cannot be multisample.
4603
4604 \value MipMapped The texture has mipmaps. The appropriate mip count is
4605 calculated automatically and can also be retrieved via
4606 QRhi::mipLevelsForSize(). The images for the mip levels have to be
4607 provided in the texture uploaded or generated via
4608 QRhiResourceUpdateBatch::generateMips(). Multisample textures cannot have
4609 mipmaps.
4610
4611 \value sRGB Use an sRGB format.
4612
4613 \value UsedAsTransferSource The texture is used as the source of a texture
4614 copy or readback, meaning the texture is given as the source in
4615 QRhiResourceUpdateBatch::copyTexture() or
4616 QRhiResourceUpdateBatch::readBackTexture().
4617
4618 \value UsedWithGenerateMips The texture is going to be used with
4619 QRhiResourceUpdateBatch::generateMips().
4620
4621 \value UsedWithLoadStore The texture is going to be used with image
4622 load/store operations, for example, in a compute shader.
4623
4624 \value UsedAsCompressedAtlas The texture has a compressed format and the
4625 dimensions of subresource uploads may not match the texture size.
4626
4627 \value ExternalOES The texture should use the GL_TEXTURE_EXTERNAL_OES
4628 target with OpenGL. This flag is ignored with other graphics APIs.
4629
4630 \value ThreeDimensional The texture is a 3D texture. Such textures should
4631 be created with the QRhi::newTexture() overload taking a depth in addition
4632 to width and height. A 3D texture can have mipmaps but cannot be
4633 multisample. When rendering into, or uploading data to a 3D texture, the \c
4634 layer specified in the render target's color attachment or the upload
4635 description refers to a single slice in range [0..depth-1]. The underlying
4636 graphics API may not support 3D textures at run time. Support is indicated
4637 by the QRhi::ThreeDimensionalTextures feature.
4638
4639 \value TextureRectangleGL The texture should use the GL_TEXTURE_RECTANGLE
4640 target with OpenGL. This flag is ignored with other graphics APIs. Just
4641 like ExternalOES, this flag is useful when working with platform APIs where
4642 native OpenGL texture objects received from the platform are wrapped in a
4643 QRhiTexture, and the platform can only provide textures for a non-2D
4644 texture target.
4645
4646 \value TextureArray The texture is a texture array, i.e. a single texture
4647 object that is a homogeneous array of 2D textures. Texture arrays are
4648 created with QRhi::newTextureArray(). The underlying graphics API may not
4649 support texture array objects at run time. Support is indicated by the
4650 QRhi::TextureArrays feature. When rendering into, or uploading data to a
4651 texture array, the \c layer specified in the render target's color
4652 attachment or the upload description selects a single element in the array.
4653
4654 \value OneDimensional The texture is a 1D texture. Such textures can be
4655 created by passing a 0 height and depth to QRhi::newTexture(). Note that
4656 there can be limitations on one dimensional textures depending on the
4657 underlying graphics API. For example, rendering to them or using them with
4658 mipmap-based filtering may be unsupported. This is indicated by the
4659 QRhi::OneDimensionalTextures and QRhi::OneDimensionalTextureMipmaps
4660 feature flags.
4661
4662 \value UsedAsShadingRateMap
4663 */
4664
4665/*!
4666 \enum QRhiTexture::Format
4667
4668 Specifies the texture format. See also QRhi::isTextureFormatSupported() and
4669 note that flags() can modify the format when QRhiTexture::sRGB is set.
4670
4671 \value UnknownFormat Not a valid format. This cannot be passed to setFormat().
4672
4673 \value RGBA8 Four components, unsigned normalized 8-bit per component. Always supported. (32 bits total)
4674
4675 \value BGRA8 Four components, unsigned normalized 8-bit per component. (32 bits total)
4676
4677 \value R8 One component, unsigned normalized 8-bit. (8 bits total)
4678
4679 \value RG8 Two components, unsigned normalized 8-bit. (16 bits total)
4680
4681 \value R16 One component, unsigned normalized 16-bit. (16 bits total)
4682
4683 \value RG16 Two components, unsigned normalized 16-bit. (32 bits total)
4684
4685 \value RED_OR_ALPHA8 Either same as R8, or is a similar format with the component swizzled to alpha,
4686 depending on \l{QRhi::RedOrAlpha8IsRed}{RedOrAlpha8IsRed}. (8 bits total)
4687
4688 \value RGBA16F Four components, 16-bit float. (64 bits total)
4689
4690 \value RGBA32F Four components, 32-bit float. (128 bits total)
4691
4692 \value R16F One component, 16-bit float. (16 bits total)
4693
4694 \value R32F One component, 32-bit float. (32 bits total)
4695
4696 \value RGB10A2 Four components, unsigned normalized 10 bit R, G, and B,
4697 2-bit alpha. This is a packed format so native endianness applies. Note
4698 that there is no BGR10A2. This is because RGB10A2 maps to
4699 DXGI_FORMAT_R10G10B10A2_UNORM with D3D, MTLPixelFormatRGB10A2Unorm with
4700 Metal, VK_FORMAT_A2B10G10R10_UNORM_PACK32 with Vulkan, and
4701 GL_RGB10_A2/GL_RGB/GL_UNSIGNED_INT_2_10_10_10_REV on OpenGL (ES). This is
4702 the only universally supported RGB30 option. The corresponding QImage
4703 formats are QImage::Format_BGR30 and QImage::Format_A2BGR30_Premultiplied.
4704 (32 bits total)
4705
4706 \value D16 16-bit depth (normalized unsigned integer)
4707
4708 \value D24 24-bit depth (normalized unsigned integer)
4709
4710 \value D24S8 24-bit depth (normalized unsigned integer), 8 bit stencil
4711
4712 \value D32F 32-bit depth (32-bit float)
4713
4714 \value [since 6.9] D32FS8 32-bit depth (32-bit float), 8 bits of stencil, 24 bits unused
4715 (64 bits total)
4716
4717 \value BC1
4718 \value BC2
4719 \value BC3
4720 \value BC4
4721 \value BC5
4722 \value BC6H
4723 \value BC7
4724
4725 \value ETC2_RGB8
4726 \value ETC2_RGB8A1
4727 \value ETC2_RGBA8
4728
4729 \value ASTC_4x4
4730 \value ASTC_5x4
4731 \value ASTC_5x5
4732 \value ASTC_6x5
4733 \value ASTC_6x6
4734 \value ASTC_8x5
4735 \value ASTC_8x6
4736 \value ASTC_8x8
4737 \value ASTC_10x5
4738 \value ASTC_10x6
4739 \value ASTC_10x8
4740 \value ASTC_10x10
4741 \value ASTC_12x10
4742 \value ASTC_12x12
4743
4744 \value [since 6.9] R8UI One component, unsigned 8-bit. (8 bits total)
4745 \value [since 6.9] R32UI One component, unsigned 32-bit. (32 bits total)
4746 \value [since 6.9] RG32UI Two components, unsigned 32-bit. (64 bits total)
4747 \value [since 6.9] RGBA32UI Four components, unsigned 32-bit. (128 bits total)
4748
4749 \value [since 6.10] R8SI One component, signed 8-bit. (8 bits total)
4750 \value [since 6.10] R32SI One component, signed 32-bit. (32 bits total)
4751 \value [since 6.10] RG32SI Two components, signed 32-bit. (64 bits total)
4752 \value [since 6.10] RGBA32SI Four components, signed 32-bit. (128 bits total)
4753 */
4754
4755// When adding new texture formats, update void tst_QRhi::textureFormats_data().
4756
4757/*!
4758 \struct QRhiTexture::NativeTexture
4759 \inmodule QtGuiPrivate
4760 \inheaderfile rhi/qrhi.h
4761 \brief Contains information about the underlying native resources of a texture.
4762 */
4763
4764/*!
4765 \variable QRhiTexture::NativeTexture::object
4766 \brief 64-bit integer containing the native object handle.
4767
4768 With OpenGL, the native handle is a GLuint value, so \c object can then be
4769 cast to a GLuint. With Vulkan, the native handle is a VkImage, so \c object
4770 can be cast to a VkImage. With Direct3D 11 and Metal \c object contains a
4771 ID3D11Texture2D or MTLTexture pointer, respectively. With Direct3D 12
4772 \c object contains a ID3D12Resource pointer.
4773 */
4774
4775/*!
4776 \variable QRhiTexture::NativeTexture::layout
4777 \brief Specifies the current image layout for APIs like Vulkan.
4778
4779 For Vulkan, \c layout contains a \c VkImageLayout value.
4780 */
4781
4782/*!
4783 \internal
4784 */
4785QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
4786 int arraySize_, int sampleCount_, Flags flags_)
4787 : QRhiResource(rhi),
4788 m_format(format_), m_pixelSize(pixelSize_), m_depth(depth_),
4789 m_arraySize(arraySize_), m_sampleCount(sampleCount_), m_flags(flags_)
4790{
4791}
4792
4793/*!
4794 \return the resource type.
4795 */
4796QRhiResource::Type QRhiTexture::resourceType() const
4797{
4798 return Texture;
4799}
4800
4801/*!
4802 \fn virtual bool QRhiTexture::create() = 0
4803
4804 Creates the corresponding native graphics resources. If there are already
4805 resources present due to an earlier create() with no corresponding
4806 destroy(), then destroy() is called implicitly first.
4807
4808 \return \c true when successful, \c false when a graphics operation failed.
4809 Regardless of the return value, calling destroy() is always safe.
4810 */
4811
4812/*!
4813 \return the underlying native resources for this texture. The returned value
4814 will be empty if exposing the underlying native resources is not supported by
4815 the backend.
4816
4817 \sa createFrom()
4818 */
4819QRhiTexture::NativeTexture QRhiTexture::nativeTexture()
4820{
4821 return {};
4822}
4823
4824/*!
4825 Similar to create(), except that no new native textures are created.
4826 Instead, the native texture resources specified by \a src is used.
4827
4828 This allows importing an existing native texture object (which must belong
4829 to the same device or sharing context, depending on the graphics API) from
4830 an external graphics engine.
4831
4832 \return true if the specified existing native texture object has been
4833 successfully wrapped as a non-owning QRhiTexture.
4834
4835 \note format(), pixelSize(), sampleCount(), and flags() must still be set
4836 correctly. Passing incorrect sizes and other values to QRhi::newTexture()
4837 and then following it with a createFrom() expecting that the native texture
4838 object alone is sufficient to deduce such values is \b wrong and will lead
4839 to problems.
4840
4841 \note QRhiTexture does not take ownership of the texture object. destroy()
4842 does not free the object or any associated memory.
4843
4844 The opposite of this operation, exposing a QRhiTexture-created native
4845 texture object to a foreign engine, is possible via nativeTexture().
4846
4847 \note When importing a 3D texture, or a texture array object, or, with
4848 OpenGL ES, an external texture, it is then especially important to set the
4849 corresponding flags (ThreeDimensional, TextureArray, ExternalOES) via
4850 setFlags() before calling this function.
4851*/
4852bool QRhiTexture::createFrom(QRhiTexture::NativeTexture src)
4853{
4854 Q_UNUSED(src);
4855 return false;
4856}
4857
4858/*!
4859 With some graphics APIs, such as Vulkan, integrating custom rendering code
4860 that uses the graphics API directly needs special care when it comes to
4861 image layouts. This function allows communicating the expected \a layout the
4862 image backing the QRhiTexture is in after the native rendering commands.
4863
4864 For example, consider rendering into a QRhiTexture's VkImage directly with
4865 Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and
4866 QRhiCommandBuffer::endExternal(), followed by using the image for texture
4867 sampling in a QRhi-based render pass. To avoid potentially incorrect image
4868 layout transitions, this function can be used to indicate what the image
4869 layout will be once the commands recorded in said code block complete.
4870
4871 Calling this function makes sense only after
4872 QRhiCommandBuffer::endExternal() and before a subsequent
4873 QRhiCommandBuffer::beginPass().
4874
4875 This function has no effect with QRhi backends where the underlying
4876 graphics API does not expose a concept of image layouts.
4877
4878 \note With Vulkan \a layout is a \c VkImageLayout. With Direct 3D 12 \a
4879 layout is a value composed of the bits from \c D3D12_RESOURCE_STATES.
4880 */
4881void QRhiTexture::setNativeLayout(int layout)
4882{
4883 Q_UNUSED(layout);
4884}
4885
4886/*!
4887 \fn QRhiTexture::Format QRhiTexture::format() const
4888 \return the texture format.
4889 */
4890
4891/*!
4892 \fn void QRhiTexture::setFormat(QRhiTexture::Format fmt)
4893
4894 Sets the requested texture format to \a fmt.
4895
4896 \note The value set is only taken into account upon the next call to
4897 create(), i.e. when the underlying graphics resource are (re)created.
4898 Setting a new value is futile otherwise and must be avoided since it can
4899 lead to inconsistent state.
4900 */
4901
4902/*!
4903 \fn QSize QRhiTexture::pixelSize() const
4904 \return the size in pixels.
4905 */
4906
4907/*!
4908 \fn void QRhiTexture::setPixelSize(const QSize &sz)
4909
4910 Sets the texture size, specified in pixels, to \a sz.
4911
4912 \note The value set is only taken into account upon the next call to
4913 create(), i.e. when the underlying graphics resource are (re)created.
4914 Setting a new value is futile otherwise and must be avoided since it can
4915 lead to inconsistent state. The same applies to all other setters as well.
4916 */
4917
4918/*!
4919 \fn int QRhiTexture::depth() const
4920 \return the depth for 3D textures.
4921 */
4922
4923/*!
4924 \fn void QRhiTexture::setDepth(int depth)
4925 Sets the \a depth for a 3D texture.
4926 */
4927
4928/*!
4929 \fn int QRhiTexture::arraySize() const
4930 \return the texture array size.
4931 */
4932
4933/*!
4934 \fn void QRhiTexture::setArraySize(int arraySize)
4935 Sets the texture \a arraySize.
4936 */
4937
4938/*!
4939 \fn int QRhiTexture::arrayRangeStart() const
4940
4941 \return the first array layer when setArrayRange() was called.
4942
4943 \sa setArrayRange()
4944 */
4945
4946/*!
4947 \fn int QRhiTexture::arrayRangeLength() const
4948
4949 \return the exposed array range size when setArrayRange() was called.
4950
4951 \sa setArrayRange()
4952*/
4953
4954/*!
4955 \fn void QRhiTexture::setArrayRange(int startIndex, int count)
4956
4957 Normally all array layers are exposed and it is up to the shader to select
4958 the layer via the third coordinate passed to the \c{texture()} GLSL
4959 function when sampling the \c sampler2DArray. When QRhi::TextureArrayRange
4960 is reported as supported, calling setArrayRange() before create() or
4961 createFrom() requests selecting only the specified range, \a count elements
4962 starting from \a startIndex. The shader logic can then be written with this
4963 in mind.
4964
4965 \sa QRhi::TextureArrayRange
4966 */
4967
4968/*!
4969 \fn Flags QRhiTexture::flags() const
4970 \return the texture flags.
4971 */
4972
4973/*!
4974 \fn void QRhiTexture::setFlags(Flags f)
4975 Sets the texture flags to \a f.
4976 */
4977
4978/*!
4979 \fn int QRhiTexture::sampleCount() const
4980 \return the sample count. 1 means no multisample antialiasing.
4981 */
4982
4983/*!
4984 \fn void QRhiTexture::setSampleCount(int s)
4985 Sets the sample count to \a s.
4986 */
4987
4988/*!
4989 \struct QRhiTexture::ViewFormat
4990 \inmodule QtGuiPrivate
4991 \inheaderfile rhi/qrhi.h
4992 \since 6.8
4993 \brief Specifies the view format for reading or writing from or to the texture.
4994
4995 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4996 for details.
4997 */
4998
4999/*!
5000 \variable QRhiTexture::ViewFormat::format
5001 */
5002
5003/*!
5004 \variable QRhiTexture::ViewFormat::srgb
5005 */
5006
5007/*!
5008 \fn QRhiTexture::ViewFormat QRhiTexture::readViewFormat() const
5009 \since 6.8
5010 \return the view format used when sampling the texture. When not called, the view
5011 format is assumed to be the same as format().
5012 */
5013
5014/*!
5015 \fn void QRhiTexture::setReadViewFormat(const ViewFormat &fmt)
5016 \since 6.8
5017
5018 Sets the shader resource view format (or the format of the view used for
5019 sampling the texture) to \a fmt. By default the same format (and sRGB-ness)
5020 is used as the texture itself, and in most cases this function does not need
5021 to be called.
5022
5023 This setting is only taken into account when the \l QRhi::TextureViewFormat
5024 feature is reported as supported.
5025
5026 \note This functionality is provided to allow "casting" between
5027 non-sRGB and sRGB in order to get the shader reads perform, or not perform,
5028 the implicit sRGB conversions. Other types of casting may or may not be
5029 functional.
5030 */
5031
5032/*!
5033 \fn QRhiTexture::ViewFormat QRhiTexture::writeViewFormat() const
5034 \since 6.8
5035 \return the view format used when writing to the texture and when using it
5036 with image load/store. When not called, the view format is assumed to be the
5037 same as format().
5038 */
5039
5040/*!
5041 \fn void QRhiTexture::setWriteViewFormat(const ViewFormat &fmt)
5042 \since 6.8
5043
5044 Sets the render target view format to \a fmt. By default the same format
5045 (and sRGB-ness) is used as the texture itself, and in most cases this
5046 function does not need to be called.
5047
5048 One common use case for providing a write view format is working with
5049 externally provided textures that, outside of our control, use an sRGB
5050 format with 3D APIs such as Vulkan or Direct 3D, but the rendering engine is
5051 already prepared to handle linearization and conversion to sRGB at the end
5052 of its shading pipeline. In this case what is wanted when rendering into
5053 such a texture is a render target view (e.g. VkImageView) that has the same,
5054 but non-sRGB format. (if e.g. from an OpenXR implementation one gets a
5055 VK_FORMAT_R8G8B8A8_SRGB texture, it is likely that rendering into it should
5056 be done using a VK_FORMAT_R8G8B8A8_UNORM view, if that is what the rendering
5057 engine's pipeline requires; in this example one would call this function
5058 with a ViewFormat that has a format of QRhiTexture::RGBA8 and \c srgb set to
5059 \c false).
5060
5061 This setting is only taken into account when the \l QRhi::TextureViewFormat
5062 feature is reported as supported.
5063
5064 \note This functionality is provided to allow "casting" between
5065 non-sRGB and sRGB in order to get the shader write not perform, or perform,
5066 the implicit sRGB conversions. Other types of casting may or may not be
5067 functional.
5068 */
5069
5070/*!
5071 \class QRhiSampler
5072 \inmodule QtGuiPrivate
5073 \inheaderfile rhi/qrhi.h
5074 \since 6.6
5075 \brief Sampler resource.
5076
5077 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5078 for details.
5079 */
5080
5081/*!
5082 \enum QRhiSampler::Filter
5083 Specifies the minification, magnification, or mipmap filtering
5084
5085 \value None Applicable only for mipmapMode(), indicates no mipmaps to be used
5086 \value Nearest
5087 \value Linear
5088 */
5089
5090/*!
5091 \enum QRhiSampler::AddressMode
5092 Specifies the addressing mode
5093
5094 \value Repeat
5095 \value ClampToEdge
5096 \value Mirror
5097 */
5098
5099/*!
5100 \enum QRhiSampler::CompareOp
5101 Specifies the texture comparison function.
5102
5103 \value Never (default)
5104 \value Less
5105 \value Equal
5106 \value LessOrEqual
5107 \value Greater
5108 \value NotEqual
5109 \value GreaterOrEqual
5110 \value Always
5111 */
5112
5113/*!
5114 \internal
5115 */
5116QRhiSampler::QRhiSampler(QRhiImplementation *rhi,
5117 Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
5118 AddressMode u_, AddressMode v_, AddressMode w_)
5119 : QRhiResource(rhi),
5120 m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_),
5121 m_addressU(u_), m_addressV(v_), m_addressW(w_),
5122 m_compareOp(QRhiSampler::Never)
5123{
5124}
5125
5126/*!
5127 \return the resource type.
5128 */
5129QRhiResource::Type QRhiSampler::resourceType() const
5130{
5131 return Sampler;
5132}
5133
5134/*!
5135 \fn QRhiSampler::Filter QRhiSampler::magFilter() const
5136 \return the magnification filter mode.
5137 */
5138
5139/*!
5140 \fn void QRhiSampler::setMagFilter(Filter f)
5141 Sets the magnification filter mode to \a f.
5142 */
5143
5144/*!
5145 \fn QRhiSampler::Filter QRhiSampler::minFilter() const
5146 \return the minification filter mode.
5147 */
5148
5149/*!
5150 \fn void QRhiSampler::setMinFilter(Filter f)
5151 Sets the minification filter mode to \a f.
5152 */
5153
5154/*!
5155 \fn QRhiSampler::Filter QRhiSampler::mipmapMode() const
5156 \return the mipmap filter mode.
5157 */
5158
5159/*!
5160 \fn void QRhiSampler::setMipmapMode(Filter f)
5161
5162 Sets the mipmap filter mode to \a f.
5163
5164 Leave this set to None when the texture has no mip levels, or when the mip
5165 levels are not to be taken into account.
5166 */
5167
5168/*!
5169 \fn QRhiSampler::AddressMode QRhiSampler::addressU() const
5170 \return the horizontal wrap mode.
5171 */
5172
5173/*!
5174 \fn void QRhiSampler::setAddressU(AddressMode mode)
5175 Sets the horizontal wrap \a mode.
5176 */
5177
5178/*!
5179 \fn QRhiSampler::AddressMode QRhiSampler::addressV() const
5180 \return the vertical wrap mode.
5181 */
5182
5183/*!
5184 \fn void QRhiSampler::setAddressV(AddressMode mode)
5185 Sets the vertical wrap \a mode.
5186 */
5187
5188/*!
5189 \fn QRhiSampler::AddressMode QRhiSampler::addressW() const
5190 \return the depth wrap mode.
5191 */
5192
5193/*!
5194 \fn void QRhiSampler::setAddressW(AddressMode mode)
5195 Sets the depth wrap \a mode.
5196 */
5197
5198/*!
5199 \fn QRhiSampler::CompareOp QRhiSampler::textureCompareOp() const
5200 \return the texture comparison function.
5201 */
5202
5203/*!
5204 \fn void QRhiSampler::setTextureCompareOp(CompareOp op)
5205 Sets the texture comparison function \a op.
5206 */
5207
5208/*!
5209 \class QRhiShadingRateMap
5210 \inmodule QtGuiPrivate
5211 \inheaderfile rhi/qrhi.h
5212 \since 6.9
5213 \brief An object that wraps a texture or another kind of native 3D API object.
5214
5215 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5216 for details.
5217
5218 For an introduction to Variable Rate Shading (VRS), see
5219 \l{https://learn.microsoft.com/en-us/windows/win32/direct3d12/vrs}. Qt
5220 supports a subset of the VRS features offered by Direct 3D 12 and Vulkan. In
5221 addition, Metal's somewhat different mechanism is supported by making it
5222 possible to set up a QRhiShadingRateMap with an existing
5223 MTLRasterizationRateMap object.
5224 */
5225
5226/*!
5227 \struct QRhiShadingRateMap::NativeShadingRateMap
5228 \inmodule QtGuiPrivate
5229 \inheaderfile rhi/qrhi.h
5230 \since 6.9
5231 \brief Wraps a native shading rate map.
5232
5233 An example is MTLRasterizationRateMap with Metal. Other 3D APIs that use
5234 textures for image-based VRS do not use this struct since those can function
5235 via the QRhiTexture-based overload of QRhiShadingRateMap::createFrom().
5236 */
5237
5238/*!
5239 \variable QRhiShadingRateMap::NativeShadingRateMap::object
5240 \brief 64-bit integer containing the native object handle.
5241
5242 Used with QRhiShadingRateMap::createFrom(). For example, with Metal,
5243 \c object is expected to be an id<MTLRasterizationRateMap>.
5244 */
5245
5246/*!
5247 \internal
5248 */
5249QRhiShadingRateMap::QRhiShadingRateMap(QRhiImplementation *rhi)
5250 : QRhiResource(rhi)
5251{
5252}
5253
5254/*!
5255 \return the resource type.
5256 */
5257QRhiResource::Type QRhiShadingRateMap::resourceType() const
5258{
5259 return ShadingRateMap;
5260}
5261
5262/*!
5263 Sets up the shading rate map to use a native 3D API shading rate object
5264 \a src.
5265
5266 \return \c true when successful, \c false when not supported.
5267
5268 \note This is functional only when the QRhi::VariableRateShadingMap feature
5269 is reported as supported, while QRhi::VariableRateShadingMapWithTexture
5270 feature is not. Currently this is true for Metal, assuming variable rate
5271 shading is supported by the GPU.
5272
5273 \note With Metal, the \c object field of \a src is expected to contain an
5274 id<MTLRasterizationRateMap>. Note that Qt does not perform anything else
5275 apart from passing the MTLRasterizationRateMap on to the
5276 MTLRenderPassDescriptor. If any special scaling is required, it is up to the
5277 application (or the XR compositor) to perform that.
5278 */
5279bool QRhiShadingRateMap::createFrom(NativeShadingRateMap src)
5280{
5281 Q_UNUSED(src);
5282 return false;
5283}
5284
5285/*!
5286 Sets up the shading rate map to use the texture \a src as the
5287 image containing the per-tile shading rates.
5288
5289 \return \c true when successful, \c false when not supported.
5290
5291 The QRhiShadingRateMap does not take ownership of \a src.
5292
5293 \note This is functional only when the
5294 QRhi::VariableRateShadingMapWithTexture feature is reported as supported. In
5295 practice may be supported on Vulkan and Direct 3D 12 when using modern
5296 graphics cards. It will never be supported on OpenGL or Metal, for example.
5297
5298 \note \a src must have a format of QRhiTexture::R8UI.
5299
5300 \note \a src must have a width of \c{ceil(render_target_pixel_width /
5301 (float)tile_width)} and a height of \c{ceil(render_target_pixel_height /
5302 (float)tile_height)}. It is up to the application to ensure the size of the
5303 texture is as expected, using the above formula, at all times. The tile size
5304 can be queried via \l QRhi::resourceLimit() and
5305 QRhi::ShadingRateImageTileSize.
5306
5307 Each byte (texel) in the texture corresponds to the shading rate value for
5308 one tile. 0 indicates 1x1, while a value of 10 indicates 4x4. See
5309 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shading_rate}{D3D12_SHADING_RATE}
5310 for other possible values.
5311 */
5312bool QRhiShadingRateMap::createFrom(QRhiTexture *src)
5313{
5314 Q_UNUSED(src);
5315 return false;
5316}
5317
5318/*!
5319 \class QRhiRenderPassDescriptor
5320 \inmodule QtGuiPrivate
5321 \inheaderfile rhi/qrhi.h
5322 \since 6.6
5323 \brief Render pass resource.
5324
5325 A render pass, if such a concept exists in the underlying graphics API, is
5326 a collection of attachments (color, depth, stencil) and describes how those
5327 attachments are used.
5328
5329 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5330 for details.
5331 */
5332
5333/*!
5334 \internal
5335 */
5336QRhiRenderPassDescriptor::QRhiRenderPassDescriptor(QRhiImplementation *rhi)
5337 : QRhiResource(rhi)
5338{
5339}
5340
5341/*!
5342 \return the resource type.
5343 */
5344QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
5345{
5346 return RenderPassDescriptor;
5347}
5348
5349/*!
5350 \fn virtual bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const = 0
5351
5352 \return true if the \a other QRhiRenderPassDescriptor is compatible with
5353 this one, meaning \c this and \a other can be used interchangeably in
5354 QRhiGraphicsPipeline::setRenderPassDescriptor().
5355
5356 The concept of the compatibility of renderpass descriptors is similar to
5357 the \l{QRhiShaderResourceBindings::isLayoutCompatible}{layout
5358 compatibility} of QRhiShaderResourceBindings instances. They allow better
5359 reuse of QRhiGraphicsPipeline instances: for example, a
5360 QRhiGraphicsPipeline instance cache is expected to use these functions to
5361 look for a matching pipeline, instead of just comparing pointers, thus
5362 allowing a different QRhiRenderPassDescriptor and
5363 QRhiShaderResourceBindings to be used in combination with the pipeline, as
5364 long as they are compatible.
5365
5366 The exact details of compatibility depend on the underlying graphics API.
5367 Two renderpass descriptors
5368 \l{QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()}{created}
5369 from the same QRhiTextureRenderTarget are always compatible.
5370
5371 Similarly to QRhiShaderResourceBindings, compatibility can also be tested
5372 without having two existing objects available. Extracting the opaque blob by
5373 calling serializedFormat() allows testing for compatibility by comparing the
5374 returned vector to another QRhiRenderPassDescriptor's
5375 serializedFormat(). This has benefits in certain situations, because it
5376 allows testing the compatibility of a QRhiRenderPassDescriptor with a
5377 QRhiGraphicsPipeline even when the QRhiRenderPassDescriptor the pipeline was
5378 originally built with is no longer available (but the data returned from its
5379 serializedFormat() still is).
5380
5381 \sa newCompatibleRenderPassDescriptor(), serializedFormat()
5382 */
5383
5384/*!
5385 \fn virtual QRhiRenderPassDescriptor *QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor() const = 0
5386
5387 \return a new QRhiRenderPassDescriptor that is
5388 \l{isCompatible()}{compatible} with this one.
5389
5390 This function allows cloning a QRhiRenderPassDescriptor. The returned
5391 object is ready to be used, and the ownership is transferred to the caller.
5392 Cloning a QRhiRenderPassDescriptor object can become useful in situations
5393 where the object is stored in data structures related to graphics pipelines
5394 (in order to allow creating new pipelines which in turn requires a
5395 renderpass descriptor object), and the lifetime of the renderpass
5396 descriptor created from a render target may be shorter than the pipelines.
5397 (for example, because the engine manages and destroys renderpasses together
5398 with the textures and render targets it was created from) In such a
5399 situation, it can be beneficial to store a cloned version in the data
5400 structures, and thus transferring ownership as well.
5401
5402 \sa isCompatible()
5403 */
5404
5405/*!
5406 \fn virtual QVector<quint32> QRhiRenderPassDescriptor::serializedFormat() const = 0
5407
5408 \return a vector of integers containing an opaque blob describing the data
5409 relevant for \l{isCompatible()}{compatibility}.
5410
5411 Given two QRhiRenderPassDescriptor objects \c rp1 and \c rp2, if the data
5412 returned from this function is identical, then \c{rp1->isCompatible(rp2)},
5413 and vice versa hold true as well.
5414
5415 \note The returned data is meant to be used for storing in memory and
5416 comparisons during the lifetime of the QRhi the object belongs to. It is not
5417 meant for storing on disk, reusing between processes, or using with multiple
5418 QRhi instances with potentially different backends.
5419
5420 \note Calling this function is expected to be a cheap operation since the
5421 backends are not supposed to calculate the data in this function, but rather
5422 return an already calculated series of data.
5423
5424 When creating reusable components as part of a library, where graphics
5425 pipelines are created and maintained while targeting a QRhiRenderTarget (be
5426 it a swapchain or a texture) managed by the client of the library, the
5427 components must be able to deal with a changing QRhiRenderPassDescriptor.
5428 For example, because the render target changes and so invalidates the
5429 previously QRhiRenderPassDescriptor (with regards to the new render target
5430 at least) due to having a potentially different color format and attachments
5431 now. Or because \l{QRhiShadingRateMap}{variable rate shading} is taken into
5432 use dynamically. A simple pattern that helps dealing with this is performing
5433 the following check on every frame, to recognize the case when the pipeline
5434 needs to be associated with a new QRhiRenderPassDescriptor, because
5435 something is different about the render target now, compared to earlier
5436 frames:
5437
5438 \code
5439 QRhiRenderPassDescriptor *rp = m_renderTarget->renderPassDescriptor();
5440 if (m_pipeline && rp->serializedFormat() != m_renderPassFormat) {
5441 m_pipeline->setRenderPassDescriptor(rp);
5442 m_renderPassFormat = rp->serializedFormat();
5443 m_pipeline->create();
5444 }
5445 // remember to store m_renderPassFormat also when creating m_pipeline the first time
5446 \endcode
5447
5448 \sa isCompatible()
5449 */
5450
5451/*!
5452 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
5453 QRhiVulkanRenderPassNativeHandles. The returned value is \nullptr when exposing
5454 the underlying native resources is not supported by the backend.
5455
5456 \sa QRhiVulkanRenderPassNativeHandles
5457 */
5458const QRhiNativeHandles *QRhiRenderPassDescriptor::nativeHandles()
5459{
5460 return nullptr;
5461}
5462
5463/*!
5464 \class QRhiRenderTarget
5465 \inmodule QtGuiPrivate
5466 \inheaderfile rhi/qrhi.h
5467 \since 6.6
5468 \brief Represents an onscreen (swapchain) or offscreen (texture) render target.
5469
5470 Applications do not create an instance of this class directly. Rather, it
5471 is the subclass QRhiTextureRenderTarget that is instantiable by clients of
5472 the API via \l{QRhi::newTextureRenderTarget()}{newTextureRenderTarget()}.
5473 The other subclass is QRhiSwapChainRenderTarget, which is the type
5474 QRhiSwapChain returns when calling
5475 \l{QRhiSwapChain::currentFrameRenderTarget()}{currentFrameRenderTarget()}.
5476
5477 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5478 for details.
5479
5480 \sa QRhiSwapChainRenderTarget, QRhiTextureRenderTarget
5481 */
5482
5483/*!
5484 \internal
5485 */
5486QRhiRenderTarget::QRhiRenderTarget(QRhiImplementation *rhi)
5487 : QRhiResource(rhi)
5488{
5489}
5490
5491/*!
5492 \fn virtual QSize QRhiRenderTarget::pixelSize() const = 0
5493
5494 \return the size in pixels.
5495
5496 Valid only after create() has been called successfully. Until then the
5497 result is a default-constructed QSize.
5498
5499 With QRhiTextureRenderTarget the returned size is the size of the
5500 associated attachments at the time of create(), in practice the size of the
5501 first color attachment, or the depth/stencil buffer if there are no color
5502 attachments. If the associated textures or renderbuffers are resized and
5503 rebuilt afterwards, then pixelSize() performs an implicit call to create()
5504 in order to rebuild the underlying data structures. This implicit check is
5505 similar to what QRhiCommandBuffer::beginPass() does, and ensures that the
5506 returned size is always up-to-date.
5507 */
5508
5509/*!
5510 \fn virtual float QRhiRenderTarget::devicePixelRatio() const = 0
5511
5512 \return the device pixel ratio. For QRhiTextureRenderTarget this is always
5513 1. For targets retrieved from a QRhiSwapChain the value reflects the
5514 \l{QWindow::devicePixelRatio()}{device pixel ratio} of the targeted
5515 QWindow.
5516 */
5517
5518/*!
5519 \fn virtual int QRhiRenderTarget::sampleCount() const = 0
5520
5521 \return the sample count or 1 if multisample antialiasing is not relevant for
5522 this render target.
5523 */
5524
5525/*!
5526 \fn QRhiRenderPassDescriptor *QRhiRenderTarget::renderPassDescriptor() const
5527
5528 \return the associated QRhiRenderPassDescriptor.
5529 */
5530
5531/*!
5532 \fn void QRhiRenderTarget::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
5533
5534 Sets the QRhiRenderPassDescriptor \a desc for use with this render target.
5535 */
5536
5537/*!
5538 \internal
5539 */
5540QRhiSwapChainRenderTarget::QRhiSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain_)
5541 : QRhiRenderTarget(rhi),
5542 m_swapchain(swapchain_)
5543{
5544}
5545
5546/*!
5547 \class QRhiSwapChainRenderTarget
5548 \inmodule QtGuiPrivate
5549 \inheaderfile rhi/qrhi.h
5550 \since 6.6
5551 \brief Swapchain render target resource.
5552
5553 When targeting the color buffers of a swapchain, active render target is a
5554 QRhiSwapChainRenderTarget. This is what
5555 QRhiSwapChain::currentFrameRenderTarget() returns.
5556
5557 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5558 for details.
5559
5560 \sa QRhiSwapChain
5561 */
5562
5563/*!
5564 \return the resource type.
5565 */
5566QRhiResource::Type QRhiSwapChainRenderTarget::resourceType() const
5567{
5568 return SwapChainRenderTarget;
5569}
5570
5571/*!
5572 \fn QRhiSwapChain *QRhiSwapChainRenderTarget::swapChain() const
5573
5574 \return the swapchain object.
5575 */
5576
5577/*!
5578 \class QRhiTextureRenderTarget
5579 \inmodule QtGuiPrivate
5580 \inheaderfile rhi/qrhi.h
5581 \since 6.6
5582 \brief Texture render target resource.
5583
5584 A texture render target allows rendering into one or more textures,
5585 optionally with a depth texture or depth/stencil renderbuffer.
5586
5587 For multisample rendering the common approach is to use a renderbuffer as
5588 the color attachment and set the non-multisample destination texture as the
5589 \c{resolve texture}. For more information, read the detailed description of
5590 the \l QRhiColorAttachment class.
5591
5592 \note Textures used in combination with QRhiTextureRenderTarget must be
5593 created with the QRhiTexture::RenderTarget flag.
5594
5595 The simplest example of creating a render target with a texture as its
5596 single color attachment:
5597
5598 \code
5599 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
5600 texture->create();
5601 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture });
5602 rp = rt->newCompatibleRenderPassDescriptor();
5603 rt->setRenderPassDescriptor(rp);
5604 rt->create();
5605 // rt can now be used with beginPass()
5606 \endcode
5607
5608 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5609 for details.
5610 */
5611
5612/*!
5613 \enum QRhiTextureRenderTarget::Flag
5614
5615 Flag values describing the load/store behavior for the render target. The
5616 load/store behavior may be baked into native resources under the hood,
5617 depending on the backend, and therefore it needs to be known upfront and
5618 cannot be changed without rebuilding (and so releasing and creating new
5619 native resources).
5620
5621 \value PreserveColorContents Indicates that the contents of the color
5622 attachments is to be loaded when starting a render pass, instead of
5623 clearing. This is potentially more expensive, especially on mobile (tiled)
5624 GPUs, but allows preserving the existing contents between passes. When doing
5625 multisample rendering with a resolve texture set, setting this flag also
5626 requests the multisample color data to be stored (written out) to the
5627 multisample texture or render buffer. (for non-multisample rendering the
5628 color data is always stored, but for MSAA storing the multisample data
5629 decreases efficiency for certain GPU architectures, hence defaulting to not
5630 writing it out) Note however that this is non-portable: in some cases there
5631 is no intermediate multisample texture on the graphics API level, e.g. when
5632 using OpenGL ES's \c{GL_EXT_multisampled_render_to_texture} as it is all
5633 implicit, handled by the OpenGL ES implementation. In that case,
5634 PreserveColorContents will likely have no effect. Therefore, avoid relying
5635 on this flag when using multisample rendering and the color attachment is
5636 using a multisample QRhiTexture (not QRhiRenderBuffer).
5637
5638 \value PreserveDepthStencilContents Indicates that the contents of the
5639 depth texture is to be loaded when starting a render pass, instead
5640 clearing. Only applicable when a texture is used as the depth buffer
5641 (QRhiTextureRenderTargetDescription::depthTexture() is set) because
5642 depth/stencil renderbuffers may not have any physical backing and data may
5643 not be written out in the first place.
5644
5645 \value DoNotStoreDepthStencilContents Indicates that the contents of the
5646 depth texture does not need to be written out. Relevant only when a
5647 QRhiTexture, not QRhiRenderBuffer, is used as the depth-stencil buffer,
5648 because for QRhiRenderBuffer this is implicit. When a depthResolveTexture is
5649 set, the flag is not relevant, because the behavior is then as if the flag
5650 was set. This enum value is introduced in Qt 6.8.
5651 */
5652
5653/*!
5654 \internal
5655 */
5656QRhiTextureRenderTarget::QRhiTextureRenderTarget(QRhiImplementation *rhi,
5657 const QRhiTextureRenderTargetDescription &desc_,
5658 Flags flags_)
5659 : QRhiRenderTarget(rhi),
5660 m_desc(desc_),
5661 m_flags(flags_)
5662{
5663}
5664
5665/*!
5666 \return the resource type.
5667 */
5668QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
5669{
5670 return TextureRenderTarget;
5671}
5672
5673/*!
5674 \fn virtual QRhiRenderPassDescriptor *QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() = 0
5675
5676 \return a new QRhiRenderPassDescriptor that is compatible with this render
5677 target.
5678
5679 The returned value is used in two ways: it can be passed to
5680 setRenderPassDescriptor() and
5681 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
5682 describes the attachments (color, depth/stencil) and the load/store
5683 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
5684 be used in combination with a render target that has a
5685 \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
5686 QRhiRenderPassDescriptor set.
5687
5688 Two QRhiTextureRenderTarget instances can share the same render pass
5689 descriptor as long as they have the same number and type of attachments.
5690 The associated QRhiTexture or QRhiRenderBuffer instances are not part of
5691 the render pass descriptor so those can differ in the two
5692 QRhiTextureRenderTarget instances.
5693
5694 \note resources, such as QRhiTexture instances, referenced in description()
5695 must already have create() called on them.
5696
5697 \sa create()
5698 */
5699
5700/*!
5701 \fn virtual bool QRhiTextureRenderTarget::create() = 0
5702
5703 Creates the corresponding native graphics resources. If there are already
5704 resources present due to an earlier create() with no corresponding
5705 destroy(), then destroy() is called implicitly first.
5706
5707 \note renderPassDescriptor() must be set before calling create(). To obtain
5708 a QRhiRenderPassDescriptor compatible with the render target, call
5709 newCompatibleRenderPassDescriptor() before create() but after setting all
5710 other parameters, such as description() and flags(). To save resources,
5711 reuse the same QRhiRenderPassDescriptor with multiple
5712 QRhiTextureRenderTarget instances, whenever possible. Sharing the same
5713 render pass descriptor is only possible when the render targets have the
5714 same number and type of attachments (the actual textures can differ) and
5715 the same flags.
5716
5717 \note resources, such as QRhiTexture instances, referenced in description()
5718 must already have create() called on them.
5719
5720 \return \c true when successful, \c false when a graphics operation failed.
5721 Regardless of the return value, calling destroy() is always safe.
5722 */
5723
5724/*!
5725 \fn QRhiTextureRenderTargetDescription QRhiTextureRenderTarget::description() const
5726 \return the render target description.
5727 */
5728
5729/*!
5730 \fn void QRhiTextureRenderTarget::setDescription(const QRhiTextureRenderTargetDescription &desc)
5731 Sets the render target description \a desc.
5732 */
5733
5734/*!
5735 \fn QRhiTextureRenderTarget::Flags QRhiTextureRenderTarget::flags() const
5736 \return the currently set flags.
5737 */
5738
5739/*!
5740 \fn void QRhiTextureRenderTarget::setFlags(Flags f)
5741 Sets the flags to \a f.
5742 */
5743
5744/*!
5745 \class QRhiShaderResourceBindings
5746 \inmodule QtGuiPrivate
5747 \inheaderfile rhi/qrhi.h
5748 \since 6.6
5749 \brief Encapsulates resources for making buffer, texture, sampler resources visible to shaders.
5750
5751 A QRhiShaderResourceBindings is a collection of QRhiShaderResourceBinding
5752 objects, each of which describe a single binding.
5753
5754 Take a fragment shader with the following interface:
5755
5756 \badcode
5757 layout(std140, binding = 0) uniform buf {
5758 mat4 mvp;
5759 int flip;
5760 } ubuf;
5761
5762 layout(binding = 1) uniform sampler2D tex;
5763 \endcode
5764
5765 To make resources visible to the shader, the following
5766 QRhiShaderResourceBindings could be created and then passed to
5767 QRhiGraphicsPipeline::setShaderResourceBindings():
5768
5769 \code
5770 QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings();
5771 srb->setBindings({
5772 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf),
5773 QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler)
5774 });
5775 srb->create();
5776 // ...
5777 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
5778 // ...
5779 ps->setShaderResourceBindings(srb);
5780 ps->create();
5781 // ...
5782 cb->setGraphicsPipeline(ps);
5783 cb->setShaderResources(); // binds srb
5784 \endcode
5785
5786 This assumes that \c ubuf is a QRhiBuffer, \c texture is a QRhiTexture,
5787 while \a sampler is a QRhiSampler. The example also assumes that the
5788 uniform block is present in the vertex shader as well so the same buffer is
5789 made visible to the vertex stage too.
5790
5791 \section3 Advanced usage
5792
5793 Building on the above example, let's assume that a pass now needs to use
5794 the exact same pipeline and shaders with a different texture. Creating a
5795 whole separate QRhiGraphicsPipeline just for this would be an overkill.
5796 This is why QRhiCommandBuffer::setShaderResources() allows specifying a \a
5797 srb argument. As long as the layouts (so the number of bindings and the
5798 binding points) match between two QRhiShaderResourceBindings, they can both
5799 be used with the same pipeline, assuming the pipeline was created with one of
5800 them in the first place. See isLayoutCompatible() for more details.
5801
5802 \code
5803 QRhiShaderResourceBindings *srb2 = rhi->newShaderResourceBindings();
5804 // ...
5805 cb->setGraphicsPipeline(ps);
5806 cb->setShaderResources(srb2); // binds srb2
5807 \endcode
5808
5809 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5810 for details.
5811 */
5812
5813/*!
5814 \typedef QRhiShaderResourceBindingSet
5815 \relates QRhi
5816 \since 6.7
5817
5818 Synonym for QRhiShaderResourceBindings.
5819*/
5820
5821/*!
5822 \internal
5823 */
5824QRhiShaderResourceBindings::QRhiShaderResourceBindings(QRhiImplementation *rhi)
5825 : QRhiResource(rhi)
5826{
5827 m_layoutDesc.reserve(BINDING_PREALLOC * QRhiShaderResourceBinding::LAYOUT_DESC_ENTRIES_PER_BINDING);
5828}
5829
5830/*!
5831 \return the resource type.
5832 */
5833QRhiResource::Type QRhiShaderResourceBindings::resourceType() const
5834{
5835 return ShaderResourceBindings;
5836}
5837
5838/*!
5839 \return \c true if the layout is compatible with \a other. The layout does
5840 not include the actual resource (such as, buffer or texture) and related
5841 parameters (such as, offset or size). It does include the binding point,
5842 pipeline stage, and resource type, however. The number and order of the
5843 bindings must also match in order to be compatible.
5844
5845 When there is a QRhiGraphicsPipeline created with this
5846 QRhiShaderResourceBindings, and the function returns \c true, \a other can
5847 then safely be passed to QRhiCommandBuffer::setShaderResources(), and so
5848 be used with the pipeline in place of this QRhiShaderResourceBindings.
5849
5850 \note This function must only be called after a successful create(), because
5851 it relies on data generated during the baking of the underlying data
5852 structures. This way the function can implement a comparison approach that
5853 is more efficient than iterating through two binding lists and calling
5854 QRhiShaderResourceBinding::isLayoutCompatible() on each pair. This becomes
5855 relevant especially when this function is called at a high frequency.
5856
5857 \sa serializedLayoutDescription()
5858 */
5859bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBindings *other) const
5860{
5861 if (other == this)
5862 return true;
5863
5864 if (!other)
5865 return false;
5866
5867 // This can become a hot code path. Therefore we do not iterate and call
5868 // isLayoutCompatible() on m_bindings, but rather check a pre-calculated
5869 // hash code and then, if the hash matched, do a uint array comparison
5870 // (that's still more cache friendly).
5871
5872 return m_layoutDescHash == other->m_layoutDescHash
5873 && m_layoutDesc == other->m_layoutDesc;
5874}
5875
5876/*!
5877 \fn QVector<quint32> QRhiShaderResourceBindings::serializedLayoutDescription() const
5878
5879 \return a vector of integers containing an opaque blob describing the layout
5880 of the binding list, i.e. the data relevant for
5881 \l{isLayoutCompatible()}{layout compatibility tests}.
5882
5883 Given two objects \c srb1 and \c srb2, if the data returned from this
5884 function is identical, then \c{srb1->isLayoutCompatible(srb2)}, and vice
5885 versa hold true as well.
5886
5887 \note The returned data is meant to be used for storing in memory and
5888 comparisons during the lifetime of the QRhi the object belongs to. It is not
5889 meant for storing on disk, reusing between processes, or using with multiple
5890 QRhi instances with potentially different backends.
5891
5892 \sa isLayoutCompatible()
5893 */
5894
5895void QRhiImplementation::updateLayoutDesc(QRhiShaderResourceBindings *srb)
5896{
5897 srb->m_layoutDescHash = 0;
5898 srb->m_layoutDesc.clear();
5899 auto layoutDescAppender = std::back_inserter(srb->m_layoutDesc);
5900 for (const QRhiShaderResourceBinding &b : std::as_const(srb->m_bindings)) {
5901 const QRhiShaderResourceBinding::Data *d = &b.d;
5902 srb->m_layoutDescHash ^= uint(d->binding) ^ uint(d->stage) ^ uint(d->type)
5903 ^ uint(d->arraySize());
5904 layoutDescAppender = d->serialize(layoutDescAppender);
5905 }
5906}
5907
5908/*!
5909 \fn virtual bool QRhiShaderResourceBindings::create() = 0
5910
5911 Creates the corresponding resource binding set. Depending on the underlying
5912 graphics API, this may involve creating native graphics resources, and
5913 therefore it should not be assumed that this is a cheap operation.
5914
5915 If create() has been called before with no corresponding destroy(), then
5916 destroy() is called implicitly first.
5917
5918 \return \c true when successful, \c false when failed.
5919 Regardless of the return value, calling destroy() is always safe.
5920 */
5921
5922/*!
5923 \fn void QRhiShaderResourceBindings::setBindings(std::initializer_list<QRhiShaderResourceBinding> list)
5924 Sets the \a list of bindings.
5925 */
5926
5927/*!
5928 \fn template<typename InputIterator> void QRhiShaderResourceBindings::setBindings(InputIterator first, InputIterator last)
5929 Sets the list of bindings from the iterators \a first and \a last.
5930 */
5931
5932/*!
5933 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cbeginBindings() const
5934 \return a const iterator pointing to the first item in the binding list.
5935 */
5936
5937/*!
5938 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cendBindings() const
5939 \return a const iterator pointing just after the last item in the binding list.
5940 */
5941
5942/*!
5943 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::bindingAt(qsizetype index) const
5944 \return the binding at the specified \a index.
5945 */
5946
5947/*!
5948 \fn qsizetype QRhiShaderResourceBindings::bindingCount() const
5949 \return the number of bindings.
5950 */
5951
5952/*!
5953 \class QRhiShaderResourceBinding
5954 \inmodule QtGuiPrivate
5955 \inheaderfile rhi/qrhi.h
5956 \since 6.6
5957 \brief Describes the shader resource for a single binding point.
5958
5959 A QRhiShaderResourceBinding cannot be constructed directly. Instead, use the
5960 static functions such as uniformBuffer() or sampledTexture() to get an
5961 instance.
5962
5963 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5964 for details.
5965 */
5966
5967/*!
5968 \enum QRhiShaderResourceBinding::Type
5969 Specifies type of the shader resource bound to a binding point
5970
5971 \value UniformBuffer Uniform buffer
5972
5973 \value SampledTexture Combined image sampler (a texture and sampler pair).
5974 Even when the shading language associated with the underlying 3D API has no
5975 support for this concept (e.g. D3D and HLSL), this is still supported
5976 because the shader translation layer takes care of the appropriate
5977 translation and remapping of binding points or shader registers.
5978
5979 \value Texture Texture (separate)
5980
5981 \value Sampler Sampler (separate)
5982
5983 \value ImageLoad Image load (with GLSL this maps to doing imageLoad() on a
5984 single level - and either one or all layers - of a texture exposed to the
5985 shader as an image object)
5986
5987 \value ImageStore Image store (with GLSL this maps to doing imageStore() or
5988 imageAtomic*() on a single level - and either one or all layers - of a
5989 texture exposed to the shader as an image object)
5990
5991 \value ImageLoadStore Image load and store
5992
5993 \value BufferLoad Storage buffer load (with GLSL this maps to reading from
5994 a shader storage buffer)
5995
5996 \value BufferStore Storage buffer store (with GLSL this maps to writing to
5997 a shader storage buffer)
5998
5999 \value BufferLoadStore Storage buffer load and store
6000 */
6001
6002/*!
6003 \enum QRhiShaderResourceBinding::StageFlag
6004 Flag values to indicate which stages the shader resource is visible in
6005
6006 \value VertexStage Vertex stage
6007 \value TessellationControlStage Tessellation control (hull shader) stage
6008 \value TessellationEvaluationStage Tessellation evaluation (domain shader) stage
6009 \value FragmentStage Fragment (pixel shader) stage
6010 \value ComputeStage Compute stage
6011 \value GeometryStage Geometry stage
6012 */
6013
6014/*!
6015 \return \c true if the layout is compatible with \a other. The layout does not
6016 include the actual resource (such as, buffer or texture) and related
6017 parameters (such as, offset or size).
6018
6019 For example, \c a and \c b below are not equal, but are compatible layout-wise:
6020
6021 \code
6022 auto a = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buffer);
6023 auto b = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, someOtherBuffer, 256);
6024 \endcode
6025 */
6026bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBinding &other) const
6027{
6028 // everything that goes into a VkDescriptorSetLayoutBinding must match
6029 return d.binding == other.d.binding
6030 && d.stage == other.d.stage
6031 && d.type == other.d.type
6032 && d.arraySize() == other.d.arraySize();
6033}
6034
6035/*!
6036 \return a shader resource binding for the given binding number, pipeline
6037 stages, and buffer specified by \a binding, \a stage, and \a buf.
6038
6039 \note When \a buf is not null, it must have been created with
6040 QRhiBuffer::UniformBuffer.
6041
6042 \note \a buf can be null. It is valid to create a
6043 QRhiShaderResourceBindings with unspecified resources, but such an object
6044 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6045 suitable for creating pipelines. Such a pipeline must then always be used
6046 together with another, layout compatible QRhiShaderResourceBindings with
6047 resources present passed to QRhiCommandBuffer::setShaderResources().
6048
6049 \note If the size of \a buf exceeds the limit reported for
6050 QRhi::MaxUniformBufferRange, unexpected errors may occur.
6051 */
6052QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
6053 int binding, StageFlags stage, QRhiBuffer *buf)
6054{
6055 QRhiShaderResourceBinding b;
6056 b.d.binding = binding;
6057 b.d.stage = stage;
6058 b.d.type = UniformBuffer;
6059 b.d.u.ubuf.buf = buf;
6060 b.d.u.ubuf.offset = 0;
6061 b.d.u.ubuf.maybeSize = 0; // entire buffer
6062 b.d.u.ubuf.hasDynamicOffset = false;
6063 return b;
6064}
6065
6066/*!
6067 \return a shader resource binding for the given binding number, pipeline
6068 stages, and buffer specified by \a binding, \a stage, and \a buf. This
6069 overload binds a region only, as specified by \a offset and \a size.
6070
6071 \note It is up to the user to ensure the offset is aligned to
6072 QRhi::ubufAlignment().
6073
6074 \note \a size must be greater than 0.
6075
6076 \note When \a buf is not null, it must have been created with
6077 QRhiBuffer::UniformBuffer.
6078
6079 \note \a buf can be null. It is valid to create a
6080 QRhiShaderResourceBindings with unspecified resources, but such an object
6081 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6082 suitable for creating pipelines. Such a pipeline must then always be used
6083 together with another, layout compatible QRhiShaderResourceBindings with
6084 resources present passed to QRhiCommandBuffer::setShaderResources().
6085
6086 \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
6087 unexpected errors may occur.
6088 */
6089QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
6090 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6091{
6092 Q_ASSERT(size > 0);
6093 QRhiShaderResourceBinding b;
6094 b.d.binding = binding;
6095 b.d.stage = stage;
6096 b.d.type = UniformBuffer;
6097 b.d.u.ubuf.buf = buf;
6098 b.d.u.ubuf.offset = offset;
6099 b.d.u.ubuf.maybeSize = size;
6100 b.d.u.ubuf.hasDynamicOffset = false;
6101 return b;
6102}
6103
6104/*!
6105 \return a shader resource binding for the given binding number, pipeline
6106 stages, and buffer specified by \a binding, \a stage, and \a buf. The
6107 uniform buffer is assumed to have dynamic offset. The dynamic offset can be
6108 specified in QRhiCommandBuffer::setShaderResources(), thus allowing using
6109 varying offset values without creating new bindings for the buffer. The
6110 size of the bound region is specified by \a size. Like with non-dynamic
6111 offsets, \c{offset + size} cannot exceed the size of \a buf.
6112
6113 \note When \a buf is not null, it must have been created with
6114 QRhiBuffer::UniformBuffer.
6115
6116 \note \a buf can be null. It is valid to create a
6117 QRhiShaderResourceBindings with unspecified resources, but such an object
6118 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6119 suitable for creating pipelines. Such a pipeline must then always be used
6120 together with another, layout compatible QRhiShaderResourceBindings with
6121 resources present passed to QRhiCommandBuffer::setShaderResources().
6122
6123 \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
6124 unexpected errors may occur.
6125 */
6126QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(
6127 int binding, StageFlags stage, QRhiBuffer *buf, quint32 size)
6128{
6129 Q_ASSERT(size > 0);
6130 QRhiShaderResourceBinding b;
6131 b.d.binding = binding;
6132 b.d.stage = stage;
6133 b.d.type = UniformBuffer;
6134 b.d.u.ubuf.buf = buf;
6135 b.d.u.ubuf.offset = 0;
6136 b.d.u.ubuf.maybeSize = size;
6137 b.d.u.ubuf.hasDynamicOffset = true;
6138 return b;
6139}
6140
6141/*!
6142 \return a shader resource binding for the given binding number, pipeline
6143 stages, texture, and sampler specified by \a binding, \a stage, \a tex,
6144 \a sampler.
6145
6146 \note This function is equivalent to calling sampledTextures() with a
6147 \c count of 1.
6148
6149 \note \a tex and \a sampler can be null. It is valid to create a
6150 QRhiShaderResourceBindings with unspecified resources, but such an object
6151 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6152 suitable for creating pipelines. Such a pipeline must then always be used
6153 together with another, layout compatible QRhiShaderResourceBindings with
6154 resources present passed to QRhiCommandBuffer::setShaderResources().
6155
6156 \note A shader may not be able to consume more than 16 textures/samplers,
6157 depending on the underlying graphics API. This hard limit must be kept in
6158 mind in renderer design. This does not apply to texture arrays which
6159 consume a single binding point (shader register) and can contain 256-2048
6160 textures, depending on the underlying graphics API. Arrays of textures (see
6161 sampledTextures()) are however no different in this regard than using the
6162 same number of individual textures.
6163
6164 \sa sampledTextures()
6165 */
6166QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
6167 int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
6168{
6169 QRhiShaderResourceBinding b;
6170 b.d.binding = binding;
6171 b.d.stage = stage;
6172 b.d.type = SampledTexture;
6173 b.d.u.stex.count = 1;
6174 b.d.u.stex.texSamplers[0] = { tex, sampler };
6175 return b;
6176}
6177
6178/*!
6179 \return a shader resource binding for the given binding number, pipeline
6180 stages, and the array of texture-sampler pairs specified by \a binding, \a
6181 stage, \a count, and \a texSamplers.
6182
6183 \note \a count must be at least 1, and not larger than 16.
6184
6185 \note When \a count is 1, this function is equivalent to sampledTexture().
6186
6187 This function is relevant when arrays of combined image samplers are
6188 involved. For example, in GLSL \c{layout(binding = 5) uniform sampler2D
6189 shadowMaps[8];} declares an array of combined image samplers. The
6190 application is then expected provide a QRhiShaderResourceBinding for
6191 binding point 5, set up by calling this function with \a count set to 8 and
6192 a valid texture and sampler for each element of the array.
6193
6194 \warning All elements of the array must be specified. With the above
6195 example, the only valid, portable approach is calling this function with a
6196 \a count of 8. Additionally, all QRhiTexture and QRhiSampler instances must
6197 be valid, meaning nullptr is not an accepted value. This is due to some of
6198 the underlying APIs, such as, Vulkan, that require a valid image and
6199 sampler object for each element in descriptor arrays. Applications are
6200 advised to provide "dummy" samplers and textures if some array elements are
6201 not relevant (due to not being accessed in the shader).
6202
6203 \note \a texSamplers can be null. It is valid to create a
6204 QRhiShaderResourceBindings with unspecified resources, but such an object
6205 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6206 suitable for creating pipelines. Such a pipeline must then always be used
6207 together with another, layout compatible QRhiShaderResourceBindings with
6208 resources present passed to QRhiCommandBuffer::setShaderResources().
6209
6210 \sa sampledTexture()
6211 */
6212QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTextures(
6213 int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers)
6214{
6215 Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
6216 QRhiShaderResourceBinding b;
6217 b.d.binding = binding;
6218 b.d.stage = stage;
6219 b.d.type = SampledTexture;
6220 b.d.u.stex.count = count;
6221 for (int i = 0; i < count; ++i) {
6222 if (texSamplers)
6223 b.d.u.stex.texSamplers[i] = texSamplers[i];
6224 else
6225 b.d.u.stex.texSamplers[i] = { nullptr, nullptr };
6226 }
6227 return b;
6228}
6229
6230/*!
6231 \return a shader resource binding for the given binding number, pipeline
6232 stages, and texture specified by \a binding, \a stage, \a tex.
6233
6234 \note This function is equivalent to calling textures() with a
6235 \c count of 1.
6236
6237 \note \a tex can be null. It is valid to create a
6238 QRhiShaderResourceBindings with unspecified resources, but such an object
6239 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6240 suitable for creating pipelines. Such a pipeline must then always be used
6241 together with another, layout compatible QRhiShaderResourceBindings with
6242 resources present passed to QRhiCommandBuffer::setShaderResources().
6243
6244 This creates a binding for a separate texture (image) object, whereas
6245 sampledTexture() is suitable for combined image samplers. In
6246 Vulkan-compatible GLSL code separate textures are declared as \c texture2D
6247 as opposed to \c sampler2D: \c{layout(binding = 1) uniform texture2D tex;}
6248
6249 \note A shader may not be able to consume more than 16 textures, depending
6250 on the underlying graphics API. This hard limit must be kept in mind in
6251 renderer design. This does not apply to texture arrays which consume a
6252 single binding point (shader register) and can contain 256-2048 textures,
6253 depending on the underlying graphics API. Arrays of textures (see
6254 sampledTextures()) are however no different in this regard than using the
6255 same number of individual textures.
6256
6257 \sa textures(), sampler()
6258 */
6259QRhiShaderResourceBinding QRhiShaderResourceBinding::texture(int binding, StageFlags stage, QRhiTexture *tex)
6260{
6261 QRhiShaderResourceBinding b;
6262 b.d.binding = binding;
6263 b.d.stage = stage;
6264 b.d.type = Texture;
6265 b.d.u.stex.count = 1;
6266 b.d.u.stex.texSamplers[0] = { tex, nullptr };
6267 return b;
6268}
6269
6270/*!
6271 \return a shader resource binding for the given binding number, pipeline
6272 stages, and the array of (separate) textures specified by \a binding, \a
6273 stage, \a count, and \a tex.
6274
6275 \note \a count must be at least 1, and not larger than 16.
6276
6277 \note When \a count is 1, this function is equivalent to texture().
6278
6279 \warning All elements of the array must be specified.
6280
6281 \note \a tex can be null. It is valid to create a
6282 QRhiShaderResourceBindings with unspecified resources, but such an object
6283 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6284 suitable for creating pipelines. Such a pipeline must then always be used
6285 together with another, layout compatible QRhiShaderResourceBindings with
6286 resources present passed to QRhiCommandBuffer::setShaderResources().
6287
6288 \sa texture(), sampler()
6289 */
6290QRhiShaderResourceBinding QRhiShaderResourceBinding::textures(int binding, StageFlags stage, int count, QRhiTexture **tex)
6291{
6292 Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
6293 QRhiShaderResourceBinding b;
6294 b.d.binding = binding;
6295 b.d.stage = stage;
6296 b.d.type = Texture;
6297 b.d.u.stex.count = count;
6298 for (int i = 0; i < count; ++i) {
6299 if (tex)
6300 b.d.u.stex.texSamplers[i] = { tex[i], nullptr };
6301 else
6302 b.d.u.stex.texSamplers[i] = { nullptr, nullptr };
6303 }
6304 return b;
6305}
6306
6307/*!
6308 \return a shader resource binding for the given binding number, pipeline
6309 stages, and sampler specified by \a binding, \a stage, \a sampler.
6310
6311 \note \a sampler can be null. It is valid to create a
6312 QRhiShaderResourceBindings with unspecified resources, but such an object
6313 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6314 suitable for creating pipelines. Such a pipeline must then always be used
6315 together with another, layout compatible QRhiShaderResourceBindings with
6316 resources present passed to QRhiCommandBuffer::setShaderResources().
6317
6318 Arrays of separate samplers are not supported.
6319
6320 This creates a binding for a separate sampler object, whereas
6321 sampledTexture() is suitable for combined image samplers. In
6322 Vulkan-compatible GLSL code separate samplers are declared as \c sampler
6323 as opposed to \c sampler2D: \c{layout(binding = 2) uniform sampler samp;}
6324
6325 With both a \c texture2D and \c sampler present, they can be used together
6326 to sample the texture: \c{fragColor = texture(sampler2D(tex, samp),
6327 texcoord);}.
6328
6329 \note A shader may not be able to consume more than 16 samplers, depending
6330 on the underlying graphics API. This hard limit must be kept in mind in
6331 renderer design.
6332
6333 \sa texture()
6334 */
6335QRhiShaderResourceBinding QRhiShaderResourceBinding::sampler(int binding, StageFlags stage, QRhiSampler *sampler)
6336{
6337 QRhiShaderResourceBinding b;
6338 b.d.binding = binding;
6339 b.d.stage = stage;
6340 b.d.type = Sampler;
6341 b.d.u.stex.count = 1;
6342 b.d.u.stex.texSamplers[0] = { nullptr, sampler };
6343 return b;
6344}
6345
6346/*!
6347 \return a shader resource binding for a read-only storage image with the
6348 given \a binding number and pipeline \a stage. The image load operations
6349 will have access to all layers of the specified \a level. (so if the texture
6350 is a cubemap, the shader must use imageCube instead of image2D)
6351
6352 \note When \a tex is not null, it must have been created with
6353 QRhiTexture::UsedWithLoadStore.
6354
6355 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6356 with unspecified resources, but such an object cannot be used with
6357 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6358 pipelines. Such a pipeline must then always be used together with another,
6359 layout compatible QRhiShaderResourceBindings with resources present passed
6360 to QRhiCommandBuffer::setShaderResources().
6361
6362 \note Image load/store is only available within the compute and fragment stages.
6363 */
6364QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoad(
6365 int binding, StageFlags stage, QRhiTexture *tex, int level)
6366{
6367 QRhiShaderResourceBinding b;
6368 b.d.binding = binding;
6369 b.d.stage = stage;
6370 b.d.type = ImageLoad;
6371 b.d.u.simage.tex = tex;
6372 b.d.u.simage.level = level;
6373 return b;
6374}
6375
6376/*!
6377 \return a shader resource binding for a write-only storage image with the
6378 given \a binding number and pipeline \a stage. The image store operations
6379 will have access to all layers of the specified \a level. (so if the texture
6380 is a cubemap, the shader must use imageCube instead of image2D)
6381
6382 \note When \a tex is not null, it must have been created with
6383 QRhiTexture::UsedWithLoadStore.
6384
6385 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6386 with unspecified resources, but such an object cannot be used with
6387 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6388 pipelines. Such a pipeline must then always be used together with another,
6389 layout compatible QRhiShaderResourceBindings with resources present passed
6390 to QRhiCommandBuffer::setShaderResources().
6391
6392 \note Image load/store is only available within the compute and fragment stages.
6393 */
6394QRhiShaderResourceBinding QRhiShaderResourceBinding::imageStore(
6395 int binding, StageFlags stage, QRhiTexture *tex, int level)
6396{
6397 QRhiShaderResourceBinding b;
6398 b.d.binding = binding;
6399 b.d.stage = stage;
6400 b.d.type = ImageStore;
6401 b.d.u.simage.tex = tex;
6402 b.d.u.simage.level = level;
6403 return b;
6404}
6405
6406/*!
6407 \return a shader resource binding for a read/write storage image with the
6408 given \a binding number and pipeline \a stage. The image load/store operations
6409 will have access to all layers of the specified \a level. (so if the texture
6410 is a cubemap, the shader must use imageCube instead of image2D)
6411
6412 \note When \a tex is not null, it must have been created with
6413 QRhiTexture::UsedWithLoadStore.
6414
6415 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6416 with unspecified resources, but such an object cannot be used with
6417 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6418 pipelines. Such a pipeline must then always be used together with another,
6419 layout compatible QRhiShaderResourceBindings with resources present passed
6420 to QRhiCommandBuffer::setShaderResources().
6421
6422 \note Image load/store is only available within the compute and fragment stages.
6423 */
6424QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoadStore(
6425 int binding, StageFlags stage, QRhiTexture *tex, int level)
6426{
6427 QRhiShaderResourceBinding b;
6428 b.d.binding = binding;
6429 b.d.stage = stage;
6430 b.d.type = ImageLoadStore;
6431 b.d.u.simage.tex = tex;
6432 b.d.u.simage.level = level;
6433 return b;
6434}
6435
6436/*!
6437 \return a shader resource binding for a read-only storage buffer with the
6438 given \a binding number and pipeline \a stage.
6439
6440 \note When \a buf is not null, must have been created with
6441 QRhiBuffer::StorageBuffer.
6442
6443 \note \a buf can be null. It is valid to create a
6444 QRhiShaderResourceBindings with unspecified resources, but such an object
6445 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6446 suitable for creating pipelines. Such a pipeline must then always be used
6447 together with another, layout compatible QRhiShaderResourceBindings with
6448 resources present passed to QRhiCommandBuffer::setShaderResources().
6449
6450 \note Buffer load/store is only guaranteed to be available within a compute
6451 pipeline. While some backends may support using these resources in a
6452 graphics pipeline as well, this is not universally supported, and even when
6453 it is, unexpected problems may arise when it comes to barriers and
6454 synchronization. Therefore, avoid using such resources with shaders other
6455 than compute.
6456 */
6457QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6458 int binding, StageFlags stage, QRhiBuffer *buf)
6459{
6460 QRhiShaderResourceBinding b;
6461 b.d.binding = binding;
6462 b.d.stage = stage;
6463 b.d.type = BufferLoad;
6464 b.d.u.sbuf.buf = buf;
6465 b.d.u.sbuf.offset = 0;
6466 b.d.u.sbuf.maybeSize = 0; // entire buffer
6467 return b;
6468}
6469
6470/*!
6471 \return a shader resource binding for a read-only storage buffer with the
6472 given \a binding number and pipeline \a stage. This overload binds a region
6473 only, as specified by \a offset and \a size.
6474
6475 \note When \a buf is not null, must have been created with
6476 QRhiBuffer::StorageBuffer.
6477
6478 \note \a buf can be null. It is valid to create a
6479 QRhiShaderResourceBindings with unspecified resources, but such an object
6480 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6481 suitable for creating pipelines. Such a pipeline must then always be used
6482 together with another, layout compatible QRhiShaderResourceBindings with
6483 resources present passed to QRhiCommandBuffer::setShaderResources().
6484
6485 \note Buffer load/store is only guaranteed to be available within a compute
6486 pipeline. While some backends may support using these resources in a
6487 graphics pipeline as well, this is not universally supported, and even when
6488 it is, unexpected problems may arise when it comes to barriers and
6489 synchronization. Therefore, avoid using such resources with shaders other
6490 than compute.
6491 */
6492QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6493 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6494{
6495 Q_ASSERT(size > 0);
6496 QRhiShaderResourceBinding b;
6497 b.d.binding = binding;
6498 b.d.stage = stage;
6499 b.d.type = BufferLoad;
6500 b.d.u.sbuf.buf = buf;
6501 b.d.u.sbuf.offset = offset;
6502 b.d.u.sbuf.maybeSize = size;
6503 return b;
6504}
6505
6506/*!
6507 \return a shader resource binding for a write-only storage buffer with the
6508 given \a binding number and pipeline \a stage.
6509
6510 \note When \a buf is not null, must have been created with
6511 QRhiBuffer::StorageBuffer.
6512
6513 \note \a buf can be null. It is valid to create a
6514 QRhiShaderResourceBindings with unspecified resources, but such an object
6515 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6516 suitable for creating pipelines. Such a pipeline must then always be used
6517 together with another, layout compatible QRhiShaderResourceBindings with
6518 resources present passed to QRhiCommandBuffer::setShaderResources().
6519
6520 \note Buffer load/store is only guaranteed to be available within a compute
6521 pipeline. While some backends may support using these resources in a
6522 graphics pipeline as well, this is not universally supported, and even when
6523 it is, unexpected problems may arise when it comes to barriers and
6524 synchronization. Therefore, avoid using such resources with shaders other
6525 than compute.
6526 */
6527QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6528 int binding, StageFlags stage, QRhiBuffer *buf)
6529{
6530 QRhiShaderResourceBinding b;
6531 b.d.binding = binding;
6532 b.d.stage = stage;
6533 b.d.type = BufferStore;
6534 b.d.u.sbuf.buf = buf;
6535 b.d.u.sbuf.offset = 0;
6536 b.d.u.sbuf.maybeSize = 0; // entire buffer
6537 return b;
6538}
6539
6540/*!
6541 \return a shader resource binding for a write-only storage buffer with the
6542 given \a binding number and pipeline \a stage. This overload binds a region
6543 only, as specified by \a offset and \a size.
6544
6545 \note When \a buf is not null, must have been created with
6546 QRhiBuffer::StorageBuffer.
6547
6548 \note \a buf can be null. It is valid to create a
6549 QRhiShaderResourceBindings with unspecified resources, but such an object
6550 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6551 suitable for creating pipelines. Such a pipeline must then always be used
6552 together with another, layout compatible QRhiShaderResourceBindings with
6553 resources present passed to QRhiCommandBuffer::setShaderResources().
6554
6555 \note Buffer load/store is only guaranteed to be available within a compute
6556 pipeline. While some backends may support using these resources in a
6557 graphics pipeline as well, this is not universally supported, and even when
6558 it is, unexpected problems may arise when it comes to barriers and
6559 synchronization. Therefore, avoid using such resources with shaders other
6560 than compute.
6561 */
6562QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6563 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6564{
6565 Q_ASSERT(size > 0);
6566 QRhiShaderResourceBinding b;
6567 b.d.binding = binding;
6568 b.d.stage = stage;
6569 b.d.type = BufferStore;
6570 b.d.u.sbuf.buf = buf;
6571 b.d.u.sbuf.offset = offset;
6572 b.d.u.sbuf.maybeSize = size;
6573 return b;
6574}
6575
6576/*!
6577 \return a shader resource binding for a read-write storage buffer with the
6578 given \a binding number and pipeline \a stage.
6579
6580 \note When \a buf is not null, must have been created with
6581 QRhiBuffer::StorageBuffer.
6582
6583 \note \a buf can be null. It is valid to create a
6584 QRhiShaderResourceBindings with unspecified resources, but such an object
6585 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6586 suitable for creating pipelines. Such a pipeline must then always be used
6587 together with another, layout compatible QRhiShaderResourceBindings with
6588 resources present passed to QRhiCommandBuffer::setShaderResources().
6589
6590 \note Buffer load/store is only guaranteed to be available within a compute
6591 pipeline. While some backends may support using these resources in a
6592 graphics pipeline as well, this is not universally supported, and even when
6593 it is, unexpected problems may arise when it comes to barriers and
6594 synchronization. Therefore, avoid using such resources with shaders other
6595 than compute.
6596 */
6597QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6598 int binding, StageFlags stage, QRhiBuffer *buf)
6599{
6600 QRhiShaderResourceBinding b;
6601 b.d.binding = binding;
6602 b.d.stage = stage;
6603 b.d.type = BufferLoadStore;
6604 b.d.u.sbuf.buf = buf;
6605 b.d.u.sbuf.offset = 0;
6606 b.d.u.sbuf.maybeSize = 0; // entire buffer
6607 return b;
6608}
6609
6610/*!
6611 \return a shader resource binding for a read-write storage buffer with the
6612 given \a binding number and pipeline \a stage. This overload binds a region
6613 only, as specified by \a offset and \a size.
6614
6615 \note When \a buf is not null, must have been created with
6616 QRhiBuffer::StorageBuffer.
6617
6618 \note \a buf can be null. It is valid to create a
6619 QRhiShaderResourceBindings with unspecified resources, but such an object
6620 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6621 suitable for creating pipelines. Such a pipeline must then always be used
6622 together with another, layout compatible QRhiShaderResourceBindings with
6623 resources present passed to QRhiCommandBuffer::setShaderResources().
6624
6625 \note Buffer load/store is only guaranteed to be available within a compute
6626 pipeline. While some backends may support using these resources in a
6627 graphics pipeline as well, this is not universally supported, and even when
6628 it is, unexpected problems may arise when it comes to barriers and
6629 synchronization. Therefore, avoid using such resources with shaders other
6630 than compute.
6631 */
6632QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6633 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6634{
6635 Q_ASSERT(size > 0);
6636 QRhiShaderResourceBinding b;
6637 b.d.binding = binding;
6638 b.d.stage = stage;
6639 b.d.type = BufferLoadStore;
6640 b.d.u.sbuf.buf = buf;
6641 b.d.u.sbuf.offset = offset;
6642 b.d.u.sbuf.maybeSize = size;
6643 return b;
6644}
6645
6646/*!
6647 \return \c true if the contents of the two QRhiShaderResourceBinding
6648 objects \a a and \a b are equal. This includes the resources (buffer,
6649 texture) and related parameters (offset, size) as well. To only compare
6650 layouts (binding point, pipeline stage, resource type), use
6651 \l{QRhiShaderResourceBinding::isLayoutCompatible()}{isLayoutCompatible()}
6652 instead.
6653
6654 \relates QRhiShaderResourceBinding
6655 */
6656bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6657{
6658 const QRhiShaderResourceBinding::Data *da = QRhiImplementation::shaderResourceBindingData(a);
6659 const QRhiShaderResourceBinding::Data *db = QRhiImplementation::shaderResourceBindingData(b);
6660
6661 if (da == db)
6662 return true;
6663
6664
6665 if (da->binding != db->binding
6666 || da->stage != db->stage
6667 || da->type != db->type)
6668 {
6669 return false;
6670 }
6671
6672 switch (da->type) {
6673 case QRhiShaderResourceBinding::UniformBuffer:
6674 if (da->u.ubuf.buf != db->u.ubuf.buf
6675 || da->u.ubuf.offset != db->u.ubuf.offset
6676 || da->u.ubuf.maybeSize != db->u.ubuf.maybeSize)
6677 {
6678 return false;
6679 }
6680 break;
6681 case QRhiShaderResourceBinding::SampledTexture:
6682 if (da->u.stex.count != db->u.stex.count)
6683 return false;
6684 for (int i = 0; i < da->u.stex.count; ++i) {
6685 if (da->u.stex.texSamplers[i].tex != db->u.stex.texSamplers[i].tex
6686 || da->u.stex.texSamplers[i].sampler != db->u.stex.texSamplers[i].sampler)
6687 {
6688 return false;
6689 }
6690 }
6691 break;
6692 case QRhiShaderResourceBinding::Texture:
6693 if (da->u.stex.count != db->u.stex.count)
6694 return false;
6695 for (int i = 0; i < da->u.stex.count; ++i) {
6696 if (da->u.stex.texSamplers[i].tex != db->u.stex.texSamplers[i].tex)
6697 return false;
6698 }
6699 break;
6700 case QRhiShaderResourceBinding::Sampler:
6701 if (da->u.stex.texSamplers[0].sampler != db->u.stex.texSamplers[0].sampler)
6702 return false;
6703 break;
6704 case QRhiShaderResourceBinding::ImageLoad:
6705 case QRhiShaderResourceBinding::ImageStore:
6706 case QRhiShaderResourceBinding::ImageLoadStore:
6707 if (da->u.simage.tex != db->u.simage.tex
6708 || da->u.simage.level != db->u.simage.level)
6709 {
6710 return false;
6711 }
6712 break;
6713 case QRhiShaderResourceBinding::BufferLoad:
6714 case QRhiShaderResourceBinding::BufferStore:
6715 case QRhiShaderResourceBinding::BufferLoadStore:
6716 if (da->u.sbuf.buf != db->u.sbuf.buf
6717 || da->u.sbuf.offset != db->u.sbuf.offset
6718 || da->u.sbuf.maybeSize != db->u.sbuf.maybeSize)
6719 {
6720 return false;
6721 }
6722 break;
6723 default:
6724 Q_UNREACHABLE_RETURN(false);
6725 }
6726
6727 return true;
6728}
6729
6730/*!
6731 \return \c false if all the bindings in the two QRhiShaderResourceBinding
6732 objects \a a and \a b are equal; otherwise returns \c true.
6733
6734 \relates QRhiShaderResourceBinding
6735 */
6736bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6737{
6738 return !(a == b);
6739}
6740
6741/*!
6742 \fn size_t qHash(const QRhiShaderResourceBinding &key, size_t seed)
6743 \qhashold{QRhiShaderResourceBinding}
6744 */
6745size_t qHash(const QRhiShaderResourceBinding &b, size_t seed) noexcept
6746{
6747 const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6748 QtPrivate::QHashCombineWithSeed hash(seed);
6749 seed = hash(seed, d->binding);
6750 seed = hash(seed, d->stage);
6751 seed = hash(seed, d->type);
6752 switch (d->type) {
6753 case QRhiShaderResourceBinding::UniformBuffer:
6754 seed = hash(seed, reinterpret_cast<quintptr>(d->u.ubuf.buf));
6755 break;
6756 case QRhiShaderResourceBinding::SampledTexture:
6757 seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].tex));
6758 seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].sampler));
6759 break;
6760 case QRhiShaderResourceBinding::Texture:
6761 seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].tex));
6762 break;
6763 case QRhiShaderResourceBinding::Sampler:
6764 seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].sampler));
6765 break;
6766 case QRhiShaderResourceBinding::ImageLoad:
6767 case QRhiShaderResourceBinding::ImageStore:
6768 case QRhiShaderResourceBinding::ImageLoadStore:
6769 seed = hash(seed, reinterpret_cast<quintptr>(d->u.simage.tex));
6770 break;
6771 case QRhiShaderResourceBinding::BufferLoad:
6772 case QRhiShaderResourceBinding::BufferStore:
6773 case QRhiShaderResourceBinding::BufferLoadStore:
6774 seed = hash(seed, reinterpret_cast<quintptr>(d->u.sbuf.buf));
6775 break;
6776 }
6777 return seed;
6778}
6779
6780#ifndef QT_NO_DEBUG_STREAM
6781QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
6782{
6783 QDebugStateSaver saver(dbg);
6784 const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6785 dbg.nospace() << "QRhiShaderResourceBinding("
6786 << "binding=" << d->binding
6787 << " stage=" << d->stage
6788 << " type=" << d->type;
6789 switch (d->type) {
6790 case QRhiShaderResourceBinding::UniformBuffer:
6791 dbg.nospace() << " UniformBuffer("
6792 << "buffer=" << d->u.ubuf.buf
6793 << " offset=" << d->u.ubuf.offset
6794 << " maybeSize=" << d->u.ubuf.maybeSize
6795 << ')';
6796 break;
6797 case QRhiShaderResourceBinding::SampledTexture:
6798 dbg.nospace() << " SampledTextures("
6799 << "count=" << d->u.stex.count;
6800 for (int i = 0; i < d->u.stex.count; ++i) {
6801 dbg.nospace() << " texture=" << d->u.stex.texSamplers[i].tex
6802 << " sampler=" << d->u.stex.texSamplers[i].sampler;
6803 }
6804 dbg.nospace() << ')';
6805 break;
6806 case QRhiShaderResourceBinding::Texture:
6807 dbg.nospace() << " Textures("
6808 << "count=" << d->u.stex.count;
6809 for (int i = 0; i < d->u.stex.count; ++i)
6810 dbg.nospace() << " texture=" << d->u.stex.texSamplers[i].tex;
6811 dbg.nospace() << ')';
6812 break;
6813 case QRhiShaderResourceBinding::Sampler:
6814 dbg.nospace() << " Sampler("
6815 << " sampler=" << d->u.stex.texSamplers[0].sampler
6816 << ')';
6817 break;
6818 case QRhiShaderResourceBinding::ImageLoad:
6819 dbg.nospace() << " ImageLoad("
6820 << "texture=" << d->u.simage.tex
6821 << " level=" << d->u.simage.level
6822 << ')';
6823 break;
6824 case QRhiShaderResourceBinding::ImageStore:
6825 dbg.nospace() << " ImageStore("
6826 << "texture=" << d->u.simage.tex
6827 << " level=" << d->u.simage.level
6828 << ')';
6829 break;
6830 case QRhiShaderResourceBinding::ImageLoadStore:
6831 dbg.nospace() << " ImageLoadStore("
6832 << "texture=" << d->u.simage.tex
6833 << " level=" << d->u.simage.level
6834 << ')';
6835 break;
6836 case QRhiShaderResourceBinding::BufferLoad:
6837 dbg.nospace() << " BufferLoad("
6838 << "buffer=" << d->u.sbuf.buf
6839 << " offset=" << d->u.sbuf.offset
6840 << " maybeSize=" << d->u.sbuf.maybeSize
6841 << ')';
6842 break;
6843 case QRhiShaderResourceBinding::BufferStore:
6844 dbg.nospace() << " BufferStore("
6845 << "buffer=" << d->u.sbuf.buf
6846 << " offset=" << d->u.sbuf.offset
6847 << " maybeSize=" << d->u.sbuf.maybeSize
6848 << ')';
6849 break;
6850 case QRhiShaderResourceBinding::BufferLoadStore:
6851 dbg.nospace() << " BufferLoadStore("
6852 << "buffer=" << d->u.sbuf.buf
6853 << " offset=" << d->u.sbuf.offset
6854 << " maybeSize=" << d->u.sbuf.maybeSize
6855 << ')';
6856 break;
6857 default:
6858 dbg.nospace() << " UNKNOWN()";
6859 break;
6860 }
6861 dbg.nospace() << ')';
6862 return dbg;
6863}
6864#endif
6865
6866#ifndef QT_NO_DEBUG_STREAM
6867QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
6868{
6869 QDebugStateSaver saver(dbg);
6870 dbg.nospace() << "QRhiShaderResourceBindings("
6871 << srb.m_bindings
6872 << ')';
6873 return dbg;
6874}
6875#endif
6876
6877/*!
6878 \class QRhiGraphicsPipeline
6879 \inmodule QtGuiPrivate
6880 \inheaderfile rhi/qrhi.h
6881 \since 6.6
6882 \brief Graphics pipeline state resource.
6883
6884 Represents a graphics pipeline. What exactly this map to in the underlying
6885 native graphics API, varies. Where there is a concept of pipeline objects,
6886 for example with Vulkan, the QRhi backend will create such an object upon
6887 calling create(). Elsewhere, for example with OpenGL, the
6888 QRhiGraphicsPipeline may merely collect the various state, and create()'s
6889 main task is to set up the corresponding shader program, but deferring
6890 looking at any of the requested state to a later point.
6891
6892 As with all QRhiResource subclasses, the two-phased initialization pattern
6893 applies: setting any values via the setters, for example setDepthTest(), is
6894 only effective after calling create(). Avoid changing any values once the
6895 QRhiGraphicsPipeline has been initialized via create(). To change some
6896 state, set the new value and call create() again. However, that will
6897 effectively release all underlying native resources and create new ones. As
6898 a result, it may be a heavy, expensive operation. Rather, prefer creating
6899 multiple pipelines with the different states, and
6900 \l{QRhiCommandBuffer::setGraphicsPipeline()}{switch between them} when
6901 recording the render pass.
6902
6903 \note Setting the shader stages is mandatory. There must be at least one
6904 stage, and there must be a vertex stage.
6905
6906 \note Setting the shader resource bindings is mandatory. The referenced
6907 QRhiShaderResourceBindings must already have create() called on it by the
6908 time create() is called. Associating with a QRhiShaderResourceBindings that
6909 has no bindings is also valid, as long as no shader in any stage expects any
6910 resources. Using a QRhiShaderResourceBindings object that does not specify
6911 any actual resources (i.e., the buffers, textures, etc. for the binding
6912 points are set to \nullptr) is valid as well, as long as a
6913 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
6914 QRhiShaderResourceBindings, that specifies resources for all the bindings,
6915 is going to be set via
6916 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} when
6917 recording the render pass.
6918
6919 \note Setting the render pass descriptor is mandatory. To obtain a
6920 QRhiRenderPassDescriptor that can be passed to setRenderPassDescriptor(),
6921 use either QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() or
6922 QRhiSwapChain::newCompatibleRenderPassDescriptor().
6923
6924 \note Setting the vertex input layout is mandatory.
6925
6926 \note sampleCount() defaults to 1 and must match the sample count of the
6927 render target's color and depth stencil attachments.
6928
6929 \note The depth test, depth write, and stencil test are disabled by
6930 default. The face culling mode defaults to no culling.
6931
6932 \note stencilReadMask() and stencilWriteMask() apply to both faces. They
6933 both default to 0xFF.
6934
6935 \section2 Example usage
6936
6937 All settings of a graphics pipeline have defaults which might be suitable
6938 to many applications. Therefore a minimal example of creating a graphics
6939 pipeline could be the following. This assumes that the vertex shader takes
6940 a single \c{vec3 position} input at the input location 0. With the
6941 QRhiShaderResourceBindings and QRhiRenderPassDescriptor objects, plus the
6942 QShader collections for the vertex and fragment stages, a pipeline could be
6943 created like this:
6944
6945 \code
6946 QRhiShaderResourceBindings *srb;
6947 QRhiRenderPassDescriptor *rpDesc;
6948 QShader vs, fs;
6949 // ...
6950
6951 QRhiVertexInputLayout inputLayout;
6952 inputLayout.setBindings({ { 3 * sizeof(float) } });
6953 inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float3, 0 } });
6954
6955 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
6956 ps->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
6957 ps->setVertexInputLayout(inputLayout);
6958 ps->setShaderResourceBindings(srb);
6959 ps->setRenderPassDescriptor(rpDesc);
6960 if (!ps->create()) { error(); }
6961 \endcode
6962
6963 The above code creates a pipeline object that uses the defaults for many
6964 settings and states. For example, it will use a \l Triangles topology, no
6965 backface culling, blending is disabled but color write is enabled for all
6966 four channels, depth test/write are disabled, stencil operations are
6967 disabled.
6968
6969 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
6970 for details.
6971
6972 \sa QRhiCommandBuffer, QRhi
6973 */
6974
6975/*!
6976 \enum QRhiGraphicsPipeline::Flag
6977
6978 Flag values for describing the dynamic state of the pipeline, and other
6979 options. The viewport is always dynamic.
6980
6981 \value UsesBlendConstants Indicates that a blend color constant will be set
6982 via QRhiCommandBuffer::setBlendConstants()
6983
6984 \value UsesStencilRef Indicates that a stencil reference value will be set
6985 via QRhiCommandBuffer::setStencilRef()
6986
6987 \value UsesScissor Indicates that a scissor rectangle will be set via
6988 QRhiCommandBuffer::setScissor()
6989
6990 \value CompileShadersWithDebugInfo Requests compiling shaders with debug
6991 information enabled. This is relevant only when runtime shader compilation
6992 from source code is involved, and only when the underlying infrastructure
6993 supports this. With concrete examples, this is not relevant with Vulkan and
6994 SPIR-V, because the GLSL-to-SPIR-V compilation does not happen at run
6995 time. On the other hand, consider Direct3D and HLSL, where there are
6996 multiple options: when the QShader packages ship with pre-compiled bytecode
6997 (\c DXBC), debug information is to be requested through the tool that
6998 generates the \c{.qsb} file, similarly to the case of Vulkan and
6999 SPIR-V. However, when having HLSL source code in the pre- or
7000 runtime-generated QShader packages, the first phase of compilation (HLSL
7001 source to intermediate format) happens at run time too, with this flag taken
7002 into account. Debug information is relevant in particular with tools like
7003 RenderDoc since it allows seeing the original source code when investigating
7004 the pipeline and when performing vertex or fragment shader debugging.
7005
7006 \value UsesShadingRate Indicates that a per-draw (per-pipeline) shading rate
7007 value will be set via QRhiCommandBuffer::setShadingRate(). Not specifying
7008 this flag and still calling setShadingRate() may lead to varying, unexpected
7009 results depending on the underlying graphics API.
7010
7011 \value [since 6.12] UsesIndirectDraws Indicates that this pipeline will be used with
7012 indirect draw calls (QRhiCommandBuffer::drawIndirect() or
7013 QRhiCommandBuffer::drawIndexedIndirect()). Setting this flag allows the
7014 Metal backend to use Indirect Command Buffers (ICB) for GPU-driven
7015 rendering, which significantly reduces CPU overhead for large draw counts.
7016 Not setting this flag when using indirect draws is still functional but may
7017 result in less optimal performance on Metal: QRhi::DrawIndirectMulti reports
7018 what the device can do, without knowing about individual pipelines, so a
7019 pipeline without this flag falls back to CPU-side looping even when that
7020 feature is reported as supported. The exception is
7021 QRhiCommandBuffer::drawIndirectCount() and
7022 QRhiCommandBuffer::drawIndexedIndirectCount(), for which the flag is
7023 mandatory on Metal because there is no non-ICB implementation of those. This
7024 flag has no effect on other backends.
7025 */
7026
7027/*!
7028 \enum QRhiGraphicsPipeline::Topology
7029 Specifies the primitive topology
7030
7031 \value Triangles (default)
7032 \value TriangleStrip
7033 \value TriangleFan (only available if QRhi::TriangleFanTopology is supported)
7034 \value Lines
7035 \value LineStrip
7036 \value Points
7037
7038 \value Patches (only available if QRhi::Tessellation is supported, and
7039 requires the tessellation stages to be present in the pipeline)
7040 */
7041
7042/*!
7043 \enum QRhiGraphicsPipeline::CullMode
7044 Specifies the culling mode
7045
7046 \value None No culling (default)
7047 \value Front Cull front faces
7048 \value Back Cull back faces
7049 */
7050
7051/*!
7052 \enum QRhiGraphicsPipeline::FrontFace
7053 Specifies the front face winding order
7054
7055 \value CCW Counter clockwise (default)
7056 \value CW Clockwise
7057 */
7058
7059/*!
7060 \enum QRhiGraphicsPipeline::ColorMaskComponent
7061 Flag values for specifying the color write mask
7062
7063 \value R
7064 \value G
7065 \value B
7066 \value A
7067 */
7068
7069/*!
7070 \enum QRhiGraphicsPipeline::BlendFactor
7071 Specifies the blend factor
7072
7073 \value Zero
7074 \value One
7075 \value SrcColor
7076 \value OneMinusSrcColor
7077 \value DstColor
7078 \value OneMinusDstColor
7079 \value SrcAlpha
7080 \value OneMinusSrcAlpha
7081 \value DstAlpha
7082 \value OneMinusDstAlpha
7083 \value ConstantColor
7084 \value OneMinusConstantColor
7085 \value ConstantAlpha
7086 \value OneMinusConstantAlpha
7087 \value SrcAlphaSaturate
7088 \value Src1Color
7089 \value OneMinusSrc1Color
7090 \value Src1Alpha
7091 \value OneMinusSrc1Alpha
7092 */
7093
7094/*!
7095 \enum QRhiGraphicsPipeline::BlendOp
7096 Specifies the blend operation
7097
7098 \value Add
7099 \value Subtract
7100 \value ReverseSubtract
7101 \value Min
7102 \value Max
7103 */
7104
7105/*!
7106 \enum QRhiGraphicsPipeline::CompareOp
7107 Specifies the depth or stencil comparison function
7108
7109 \value Never
7110 \value Less (default for depth)
7111 \value Equal
7112 \value LessOrEqual
7113 \value Greater
7114 \value NotEqual
7115 \value GreaterOrEqual
7116 \value Always (default for stencil)
7117 */
7118
7119/*!
7120 \enum QRhiGraphicsPipeline::StencilOp
7121 Specifies the stencil operation
7122
7123 \value StencilZero
7124 \value Keep (default)
7125 \value Replace
7126 \value IncrementAndClamp
7127 \value DecrementAndClamp
7128 \value Invert
7129 \value IncrementAndWrap
7130 \value DecrementAndWrap
7131 */
7132
7133/*!
7134 \enum QRhiGraphicsPipeline::PolygonMode
7135 \brief Specifies the polygon rasterization mode
7136
7137 Polygon Mode (Triangle Fill Mode in Metal, Fill Mode in D3D) specifies
7138 the fill mode used when rasterizing polygons. Polygons may be drawn as
7139 solids (Fill), or as a wire mesh (Line).
7140
7141 Support for non-fill polygon modes is optional and is indicated by the
7142 QRhi::NonFillPolygonMode feature. With OpenGL ES and some Vulkan
7143 implementations the feature will likely be reported as unsupported, which
7144 then means values other than Fill cannot be used.
7145
7146 \value Fill The interior of the polygon is filled (default)
7147 \value Line Boundary edges of the polygon are drawn as line segments.
7148 */
7149
7150/*!
7151 \struct QRhiGraphicsPipeline::TargetBlend
7152 \inmodule QtGuiPrivate
7153 \inheaderfile rhi/qrhi.h
7154 \since 6.6
7155 \brief Describes the blend state for one color attachment.
7156
7157 Defaults to color write enabled, blending disabled. The blend values are
7158 set up for pre-multiplied alpha (One, OneMinusSrcAlpha, One,
7159 OneMinusSrcAlpha) by default. This means that to get the alpha blending
7160 mode Qt Quick uses, it is enough to set the \c enable flag to true while
7161 leaving other values at their defaults.
7162
7163 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7164 for details.
7165 */
7166
7167/*!
7168 \variable QRhiGraphicsPipeline::TargetBlend::colorWrite
7169 */
7170
7171/*!
7172 \variable QRhiGraphicsPipeline::TargetBlend::enable
7173 */
7174
7175/*!
7176 \variable QRhiGraphicsPipeline::TargetBlend::srcColor
7177 */
7178
7179/*!
7180 \variable QRhiGraphicsPipeline::TargetBlend::dstColor
7181 */
7182
7183/*!
7184 \variable QRhiGraphicsPipeline::TargetBlend::opColor
7185 */
7186
7187/*!
7188 \variable QRhiGraphicsPipeline::TargetBlend::srcAlpha
7189 */
7190
7191/*!
7192 \variable QRhiGraphicsPipeline::TargetBlend::dstAlpha
7193 */
7194
7195/*!
7196 \variable QRhiGraphicsPipeline::TargetBlend::opAlpha
7197 */
7198
7199/*!
7200 \struct QRhiGraphicsPipeline::StencilOpState
7201 \inmodule QtGuiPrivate
7202 \inheaderfile rhi/qrhi.h
7203 \since 6.6
7204 \brief Describes the stencil operation state.
7205
7206 The default-constructed StencilOpState has the following set:
7207 \list
7208 \li failOp - \l Keep
7209 \li depthFailOp - \l Keep
7210 \li passOp - \l Keep
7211 \li compareOp \l Always
7212 \endlist
7213
7214 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7215 for details.
7216 */
7217
7218/*!
7219 \variable QRhiGraphicsPipeline::StencilOpState::failOp
7220 */
7221
7222/*!
7223 \variable QRhiGraphicsPipeline::StencilOpState::depthFailOp
7224 */
7225
7226/*!
7227 \variable QRhiGraphicsPipeline::StencilOpState::passOp
7228 */
7229
7230/*!
7231 \variable QRhiGraphicsPipeline::StencilOpState::compareOp
7232 */
7233
7234/*!
7235 \internal
7236 */
7237QRhiGraphicsPipeline::QRhiGraphicsPipeline(QRhiImplementation *rhi)
7238 : QRhiResource(rhi)
7239{
7240}
7241
7242/*!
7243 \return the resource type.
7244 */
7245QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
7246{
7247 return GraphicsPipeline;
7248}
7249
7250/*!
7251 \fn virtual bool QRhiGraphicsPipeline::create() = 0
7252
7253 Creates the corresponding native graphics resources. If there are already
7254 resources present due to an earlier create() with no corresponding
7255 destroy(), then destroy() is called implicitly first.
7256
7257 \return \c true when successful, \c false when a graphics operation failed.
7258 Regardless of the return value, calling destroy() is always safe.
7259
7260 \note This may be, depending on the underlying graphics API, an expensive
7261 operation, especially when shaders get compiled/optimized from source or
7262 from an intermediate bytecode format to the GPU's own instruction set.
7263 Where applicable, the QRhi backend automatically sets up the relevant
7264 non-persistent facilities to accelerate this, for example the Vulkan
7265 backend automatically creates a \c VkPipelineCache to improve data reuse
7266 during the lifetime of the application.
7267
7268 \note Drivers may also employ various persistent (disk-based) caching
7269 strategies for shader and pipeline data, which is hidden to and is outside
7270 of Qt's control. In some cases, depending on the graphics API and the QRhi
7271 backend, there are facilities within QRhi for manually managing such a
7272 cache, allowing the retrieval of a serializable blob that can then be
7273 reloaded in the future runs of the application to ensure faster pipeline
7274 creation times. See QRhi::pipelineCacheData() and
7275 QRhi::setPipelineCacheData() for details. Note also that when working with
7276 a QRhi instance managed by a higher level Qt framework, such as Qt Quick,
7277 it is possible that such disk-based caching is taken care of automatically,
7278 for example QQuickWindow uses a disk-based pipeline cache by default (which
7279 comes in addition to any driver-level caching).
7280 */
7281
7282/*!
7283 \fn QRhiGraphicsPipeline::Flags QRhiGraphicsPipeline::flags() const
7284 \return the currently set flags.
7285 */
7286
7287/*!
7288 \fn void QRhiGraphicsPipeline::setFlags(Flags f)
7289 Sets the flags \a f.
7290 */
7291
7292/*!
7293 \fn QRhiGraphicsPipeline::Topology QRhiGraphicsPipeline::topology() const
7294 \return the currently set primitive topology.
7295 */
7296
7297/*!
7298 \fn void QRhiGraphicsPipeline::setTopology(Topology t)
7299 Sets the primitive topology \a t.
7300 */
7301
7302/*!
7303 \fn QRhiGraphicsPipeline::CullMode QRhiGraphicsPipeline::cullMode() const
7304 \return the currently set face culling mode.
7305 */
7306
7307/*!
7308 \fn void QRhiGraphicsPipeline::setCullMode(CullMode mode)
7309 Sets the specified face culling \a mode.
7310 */
7311
7312/*!
7313 \fn QRhiGraphicsPipeline::FrontFace QRhiGraphicsPipeline::frontFace() const
7314 \return the currently set front face mode.
7315 */
7316
7317/*!
7318 \fn void QRhiGraphicsPipeline::setFrontFace(FrontFace f)
7319 Sets the front face mode \a f.
7320 */
7321
7322/*!
7323 \fn void QRhiGraphicsPipeline::setTargetBlends(std::initializer_list<TargetBlend> list)
7324
7325 Sets the \a list of render target blend settings. This is a list because
7326 when multiple render targets are used (i.e., a QRhiTextureRenderTarget with
7327 more than one QRhiColorAttachment), there needs to be a TargetBlend
7328 structure per render target (color attachment).
7329
7330 By default there is one default-constructed TargetBlend set.
7331
7332 \sa QRhi::MaxColorAttachments
7333 */
7334
7335/*!
7336 \fn template<typename InputIterator> void QRhiGraphicsPipeline::setTargetBlends(InputIterator first, InputIterator last)
7337 Sets the list of render target blend settings from the iterators \a first and \a last.
7338 */
7339
7340/*!
7341 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cbeginTargetBlends() const
7342 \return a const iterator pointing to the first item in the render target blend setting list.
7343 */
7344
7345/*!
7346 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cendTargetBlends() const
7347 \return a const iterator pointing just after the last item in the render target blend setting list.
7348 */
7349
7350/*!
7351 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::targetBlendAt(qsizetype index) const
7352 \return the render target blend setting at the specified \a index.
7353 */
7354
7355/*!
7356 \fn qsizetype QRhiGraphicsPipeline::targetBlendCount() const
7357 \return the number of render target blend settings.
7358 */
7359
7360/*!
7361 \fn bool QRhiGraphicsPipeline::hasDepthTest() const
7362 \return true if depth testing is enabled.
7363 */
7364
7365/*!
7366 \fn void QRhiGraphicsPipeline::setDepthTest(bool enable)
7367
7368 Enables or disables depth testing based on \a enable. Both depth test and
7369 the writing out of depth data are disabled by default.
7370
7371 \sa setDepthWrite()
7372 */
7373
7374/*!
7375 \fn bool QRhiGraphicsPipeline::hasDepthWrite() const
7376 \return true if depth write is enabled.
7377 */
7378
7379/*!
7380 \fn void QRhiGraphicsPipeline::setDepthWrite(bool enable)
7381
7382 Controls the writing out of depth data into the depth buffer based on
7383 \a enable. By default this is disabled. Depth write is typically enabled
7384 together with the depth test.
7385
7386 \note Enabling depth write without having depth testing enabled may not
7387 lead to the desired result, and should be avoided.
7388
7389 \sa setDepthTest()
7390 */
7391
7392/*!
7393 \fn bool QRhiGraphicsPipeline::hasDepthClamp() const
7394 \return true if depth clamp is enabled.
7395
7396 \since 6.11
7397 */
7398
7399/*!
7400 \fn void QRhiGraphicsPipeline::setDepthClamp(bool enable)
7401
7402 Enables depth clamping when \a enable is true. When depth clamping is
7403 enabled, primitives that would otherwise be clipped by the near or far
7404 clip plane are rasterized and their depth values are clamped to the
7405 depth range. When disabled (the default), such primitives are clipped.
7406
7407 \note This setting is ignored when the QRhi::DepthClamp feature is
7408 reported as unsupported.
7409
7410 \since 6.11
7411 */
7412
7413/*!
7414 \fn QRhiGraphicsPipeline::CompareOp QRhiGraphicsPipeline::depthOp() const
7415 \return the depth comparison function.
7416 */
7417
7418/*!
7419 \fn void QRhiGraphicsPipeline::setDepthOp(CompareOp op)
7420 Sets the depth comparison function \a op.
7421 */
7422
7423/*!
7424 \fn bool QRhiGraphicsPipeline::hasStencilTest() const
7425 \return true if stencil testing is enabled.
7426 */
7427
7428/*!
7429 \fn void QRhiGraphicsPipeline::setStencilTest(bool enable)
7430 Enables or disables stencil tests based on \a enable.
7431 By default this is disabled.
7432 */
7433
7434/*!
7435 \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilFront() const
7436 \return the current stencil test state for front faces.
7437 */
7438
7439/*!
7440 \fn void QRhiGraphicsPipeline::setStencilFront(const StencilOpState &state)
7441 Sets the stencil test \a state for front faces.
7442 */
7443
7444/*!
7445 \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilBack() const
7446 \return the current stencil test state for back faces.
7447 */
7448
7449/*!
7450 \fn void QRhiGraphicsPipeline::setStencilBack(const StencilOpState &state)
7451 Sets the stencil test \a state for back faces.
7452 */
7453
7454/*!
7455 \fn quint32 QRhiGraphicsPipeline::stencilReadMask() const
7456 \return the currrent stencil read mask.
7457 */
7458
7459/*!
7460 \fn void QRhiGraphicsPipeline::setStencilReadMask(quint32 mask)
7461 Sets the stencil read \a mask. The default value is 0xFF.
7462 */
7463
7464/*!
7465 \fn quint32 QRhiGraphicsPipeline::stencilWriteMask() const
7466 \return the current stencil write mask.
7467 */
7468
7469/*!
7470 \fn void QRhiGraphicsPipeline::setStencilWriteMask(quint32 mask)
7471 Sets the stencil write \a mask. The default value is 0xFF.
7472 */
7473
7474/*!
7475 \fn int QRhiGraphicsPipeline::sampleCount() const
7476 \return the currently set sample count. 1 means no multisample antialiasing.
7477 */
7478
7479/*!
7480 \fn void QRhiGraphicsPipeline::setSampleCount(int s)
7481
7482 Sets the sample count. Typical values for \a s are 1, 4, or 8. The pipeline
7483 must always be compatible with the render target, i.e. the sample counts
7484 must match.
7485
7486 \sa QRhi::supportedSampleCounts()
7487 */
7488
7489/*!
7490 \fn float QRhiGraphicsPipeline::lineWidth() const
7491 \return the currently set line width. The default is 1.0f.
7492 */
7493
7494/*!
7495 \fn void QRhiGraphicsPipeline::setLineWidth(float width)
7496
7497 Sets the line \a width. If the QRhi::WideLines feature is reported as
7498 unsupported at runtime, values other than 1.0f are ignored.
7499 */
7500
7501/*!
7502 \fn int QRhiGraphicsPipeline::depthBias() const
7503 \return the currently set depth bias.
7504 */
7505
7506/*!
7507 \fn void QRhiGraphicsPipeline::setDepthBias(int bias)
7508 Sets the depth \a bias. The default value is 0.
7509 */
7510
7511/*!
7512 \fn float QRhiGraphicsPipeline::slopeScaledDepthBias() const
7513 \return the currently set slope scaled depth bias.
7514 */
7515
7516/*!
7517 \fn void QRhiGraphicsPipeline::setSlopeScaledDepthBias(float bias)
7518 Sets the slope scaled depth \a bias. The default value is 0.
7519 */
7520
7521/*!
7522 \fn void QRhiGraphicsPipeline::setShaderStages(std::initializer_list<QRhiShaderStage> list)
7523 Sets the \a list of shader stages.
7524 */
7525
7526/*!
7527 \fn template<typename InputIterator> void QRhiGraphicsPipeline::setShaderStages(InputIterator first, InputIterator last)
7528 Sets the list of shader stages from the iterators \a first and \a last.
7529 */
7530
7531/*!
7532 \fn const QRhiShaderStage *QRhiGraphicsPipeline::cbeginShaderStages() const
7533 \return a const iterator pointing to the first item in the shader stage list.
7534 */
7535
7536/*!
7537 \fn const QRhiShaderStage *QRhiGraphicsPipeline::cendShaderStages() const
7538 \return a const iterator pointing just after the last item in the shader stage list.
7539 */
7540
7541/*!
7542 \fn const QRhiShaderStage *QRhiGraphicsPipeline::shaderStageAt(qsizetype index) const
7543 \return the shader stage at the specified \a index.
7544 */
7545
7546/*!
7547 \fn qsizetype QRhiGraphicsPipeline::shaderStageCount() const
7548 \return the number of shader stages in this pipeline.
7549 */
7550
7551/*!
7552 \fn QRhiVertexInputLayout QRhiGraphicsPipeline::vertexInputLayout() const
7553 \return the currently set vertex input layout specification.
7554 */
7555
7556/*!
7557 \fn void QRhiGraphicsPipeline::setVertexInputLayout(const QRhiVertexInputLayout &layout)
7558 Specifies the vertex input \a layout.
7559 */
7560
7561/*!
7562 \fn QRhiShaderResourceBindings *QRhiGraphicsPipeline::shaderResourceBindings() const
7563 \return the currently associated QRhiShaderResourceBindings object.
7564 */
7565
7566/*!
7567 \fn void QRhiGraphicsPipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
7568
7569 Associates with \a srb describing the resource binding layout and the
7570 resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional,
7571 because only the layout matters during pipeline creation. Therefore, the \a
7572 srb passed in here can leave the actual buffer or texture objects
7573 unspecified (\nullptr) as long as there is another,
7574 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
7575 QRhiShaderResourceBindings bound via
7576 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
7577 recording the draw calls.
7578 */
7579
7580/*!
7581 \fn QRhiRenderPassDescriptor *QRhiGraphicsPipeline::renderPassDescriptor() const
7582 \return the currently set QRhiRenderPassDescriptor.
7583 */
7584
7585/*!
7586 \fn void QRhiGraphicsPipeline::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
7587 Associates with the specified QRhiRenderPassDescriptor \a desc.
7588 */
7589
7590/*!
7591 \fn int QRhiGraphicsPipeline::patchControlPointCount() const
7592 \return the currently set patch control point count.
7593 */
7594
7595/*!
7596 \fn void QRhiGraphicsPipeline::setPatchControlPointCount(int count)
7597
7598 Sets the number of patch control points to \a count. The default value is
7599 3. This is used only when the topology is set to \l Patches.
7600 */
7601
7602/*!
7603 \fn QRhiGraphicsPipeline::PolygonMode QRhiGraphicsPipeline::polygonMode() const
7604 \return the polygon mode.
7605 */
7606
7607/*!
7608 \fn void QRhiGraphicsPipeline::setPolygonMode(PolygonMode mode)
7609 Sets the polygon \a mode. The default is Fill.
7610
7611 \sa QRhi::NonFillPolygonMode
7612 */
7613
7614/*!
7615 \fn int QRhiGraphicsPipeline::multiViewCount() const
7616 \return the view count. The default is 0, indicating no multiview rendering.
7617 \since 6.7
7618 */
7619
7620/*!
7621 \fn void QRhiGraphicsPipeline::setMultiViewCount(int count)
7622 Sets the view \a count for multiview rendering. The default is 0,
7623 indicating no multiview rendering.
7624 \a count must be 2 or larger to trigger multiview rendering.
7625
7626 Multiview is only available when the \l{QRhi::MultiView}{MultiView feature}
7627 is reported as supported. The render target must be a 2D texture array, and
7628 the color attachment for the render target must have the same \a count set.
7629
7630 See QRhiColorAttachment::setMultiViewCount() for further details on
7631 multiview rendering.
7632
7633 \since 6.7
7634 \sa QRhi::MultiView, QRhiColorAttachment::setMultiViewCount()
7635 */
7636
7637/*!
7638 \class QRhiSwapChain
7639 \inmodule QtGuiPrivate
7640 \inheaderfile rhi/qrhi.h
7641 \since 6.6
7642 \brief Swapchain resource.
7643
7644 A swapchain enables presenting rendering results to a surface. A swapchain
7645 is typically backed by a set of color buffers. Of these, one is displayed
7646 at a time.
7647
7648 Below is a typical pattern for creating and managing a swapchain and some
7649 associated resources in order to render onto a QWindow:
7650
7651 \code
7652 void init()
7653 {
7654 sc = rhi->newSwapChain();
7655 ds = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
7656 QSize(), // no need to set the size here due to UsedWithSwapChainOnly
7657 1,
7658 QRhiRenderBuffer::UsedWithSwapChainOnly);
7659 sc->setWindow(window);
7660 sc->setDepthStencil(ds);
7661 rp = sc->newCompatibleRenderPassDescriptor();
7662 sc->setRenderPassDescriptor(rp);
7663 resizeSwapChain();
7664 }
7665
7666 void resizeSwapChain()
7667 {
7668 hasSwapChain = sc->createOrResize();
7669 }
7670
7671 void render()
7672 {
7673 if (!hasSwapChain || notExposed)
7674 return;
7675
7676 if (sc->currentPixelSize() != sc->surfacePixelSize() || newlyExposed) {
7677 resizeSwapChain();
7678 if (!hasSwapChain)
7679 return;
7680 newlyExposed = false;
7681 }
7682
7683 rhi->beginFrame(sc);
7684 // ...
7685 rhi->endFrame(sc);
7686 }
7687 \endcode
7688
7689 Avoid relying on QWindow resize events to resize swapchains, especially
7690 considering that surface sizes may not always fully match the QWindow
7691 reported dimensions. The safe, cross-platform approach is to do the check
7692 via surfacePixelSize() whenever starting a new frame.
7693
7694 Releasing the swapchain must happen while the QWindow and the underlying
7695 native window is fully up and running. Building on the previous example:
7696
7697 \code
7698 void releaseSwapChain()
7699 {
7700 if (hasSwapChain) {
7701 sc->destroy();
7702 hasSwapChain = false;
7703 }
7704 }
7705
7706 // assuming Window is our QWindow subclass
7707 bool Window::event(QEvent *e)
7708 {
7709 switch (e->type()) {
7710 case QEvent::UpdateRequest: // for QWindow::requestUpdate()
7711 render();
7712 break;
7713 case QEvent::PlatformSurface:
7714 if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
7715 releaseSwapChain();
7716 break;
7717 default:
7718 break;
7719 }
7720 return QWindow::event(e);
7721 }
7722 \endcode
7723
7724 Initializing the swapchain and starting to render the first frame cannot
7725 start at any time. The safe, cross-platform approach is to rely on expose
7726 events. QExposeEvent is a loosely specified event that is sent whenever a
7727 window gets mapped, obscured, and resized, depending on the platform.
7728
7729 \code
7730 void Window::exposeEvent(QExposeEvent *)
7731 {
7732 // initialize and start rendering when the window becomes usable for graphics purposes
7733 if (isExposed() && !running) {
7734 running = true;
7735 init();
7736 }
7737
7738 // stop pushing frames when not exposed or size becomes 0
7739 if ((!isExposed() || (hasSwapChain && sc->surfacePixelSize().isEmpty())) && running)
7740 notExposed = true;
7741
7742 // continue when exposed again and the surface has a valid size
7743 if (isExposed() && running && notExposed && !sc->surfacePixelSize().isEmpty()) {
7744 notExposed = false;
7745 newlyExposed = true;
7746 }
7747
7748 if (isExposed() && !sc->surfacePixelSize().isEmpty())
7749 render();
7750 }
7751 \endcode
7752
7753 Once the rendering has started, a simple way to request a new frame is
7754 QWindow::requestUpdate(). While on some platforms this is merely a small
7755 timer, on others it has a specific implementation: for instance on macOS or
7756 iOS it may be backed by
7757 \l{https://developer.apple.com/documentation/corevideo/cvdisplaylink?language=objc}{CVDisplayLink}.
7758 The example above is already prepared for update requests by handling
7759 QEvent::UpdateRequest.
7760
7761 While acting as a QRhiRenderTarget, QRhiSwapChain also manages a
7762 QRhiCommandBuffer. Calling QRhi::endFrame() submits the recorded commands
7763 and also enqueues a \c present request. The default behavior is to do this
7764 with a swap interval of 1, meaning synchronizing to the display's vertical
7765 refresh is enabled. Thus the rendering thread calling beginFrame() and
7766 endFrame() will get throttled to vsync. On some backends this can be
7767 disabled by passing QRhiSwapChain:NoVSync in flags().
7768
7769 Multisampling (MSAA) is handled transparently to the applications when
7770 requested via setSampleCount(). Where applicable, QRhiSwapChain will take
7771 care of creating additional color buffers and issuing a multisample resolve
7772 command at the end of a frame. For OpenGL, it is necessary to request the
7773 appropriate sample count also via QSurfaceFormat, by calling
7774 QSurfaceFormat::setDefaultFormat() before initializing the QRhi.
7775
7776 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7777 for details.
7778 */
7779
7780/*!
7781 \enum QRhiSwapChain::Flag
7782 Flag values to describe swapchain properties
7783
7784 \value SurfaceHasPreMulAlpha Indicates that the target surface has
7785 transparency with premultiplied alpha. For example, this is what Qt Quick
7786 uses when the alpha channel is enabled on the target QWindow, because the
7787 scenegraph rendrerer always outputs fragments with alpha multiplied into
7788 the red, green, and blue values. To ensure identical behavior across
7789 platforms, always set QSurfaceFormat::alphaBufferSize() to a non-zero value
7790 on the target QWindow whenever this flag is set on the swapchain.
7791
7792 \value SurfaceHasNonPreMulAlpha Indicates the target surface has
7793 transparency with non-premultiplied alpha. Be aware that this may not be
7794 supported on some systems, if the system compositor always expects content
7795 with premultiplied alpha. In that case the behavior with this flag set is
7796 expected to be equivalent to SurfaceHasPreMulAlpha.
7797
7798 \value sRGB Requests to pick an sRGB format for the swapchain's color
7799 buffers and/or render target views, where applicable. Note that this
7800 implies that sRGB framebuffer update and blending will get enabled for all
7801 content targeting this swapchain, and opting out is not possible. For
7802 OpenGL, set \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the
7803 QSurfaceFormat of the QWindow in addition. Applicable only when the
7804 swapchain format is set to QRhiSwapChain::SDR.
7805
7806 \value UsedAsTransferSource Indicates the swapchain will be used as the
7807 source of a readback in QRhiResourceUpdateBatch::readBackTexture().
7808
7809 \value NoVSync Requests disabling waiting for vertical sync, also avoiding
7810 throttling the rendering thread. The behavior is backend specific and
7811 applicable only where it is possible to control this. Some may ignore the
7812 request altogether. For OpenGL, try instead setting the swap interval to 0
7813 on the QWindow via QSurfaceFormat::setSwapInterval().
7814
7815 \value MinimalBufferCount Requests creating the swapchain with the minimum
7816 number of buffers, which is in practice 2, unless the graphics
7817 implementation has a higher minimum number than that. Only applicable with
7818 backends where such control is available via the graphics API, for example,
7819 Vulkan. By default it is up to the backend to decide what number of buffers
7820 it requests (in practice this is almost always either 2 or 3), and it is
7821 not the applications' concern. However, on Vulkan for instance the backend
7822 will likely prefer the higher number (3), for example to avoid odd
7823 performance issues with some Vulkan implementations on mobile devices. It
7824 could be that on some platforms it can prove to be beneficial to force the
7825 lower buffer count (2), so this flag allows forcing that. Note that all
7826 this has no effect on the number of frames kept in flight, so the CPU
7827 (QRhi) will still prepare frames at most \c{N - 1} frames ahead of the GPU,
7828 even when the swapchain image buffer count larger than \c N. (\c{N} =
7829 QRhi::FramesInFlight and typically 2).
7830 */
7831
7832/*!
7833 \enum QRhiSwapChain::Format
7834 Describes the swapchain format. The default format is SDR.
7835
7836 This enum is used with
7837 \l{QRhiSwapChain::isFormatSupported()}{isFormatSupported()} to check
7838 upfront if creating the swapchain with the given format is supported by the
7839 platform and the window's associated screen, and with
7840 \l{QRhiSwapChain::setFormat()}{setFormat()}
7841 to set the requested format in the swapchain before calling
7842 \l{QRhiSwapChain::createOrResize()}{createOrResize()} for the first time.
7843
7844 \value SDR 8-bit RGBA or BGRA, depending on the backend and platform. With
7845 OpenGL ES in particular, it could happen that the platform provides less
7846 than 8 bits (e.g. due to EGL and the QSurfaceFormat choosing a 565 or 444
7847 format - this is outside the control of QRhi). Standard dynamic range. May
7848 be combined with setting the QRhiSwapChain::sRGB flag.
7849
7850 \value HDRExtendedSrgbLinear 16-bit float RGBA, high dynamic range,
7851 extended linear sRGB (scRGB) color space. This involves Rec. 709 primaries
7852 (same as SDR/sRGB) and linear colors. Conversion to the display's native
7853 color space (such as, HDR10) is performed by the windowing system. On
7854 Windows this is the canonical color space of the system compositor, and is
7855 the recommended format for HDR swapchains in general on desktop platforms.
7856
7857 \value HDR10 10-bit unsigned int RGB or BGR with 2 bit alpha, high dynamic
7858 range, HDR10 (Rec. 2020) color space with an ST2084 PQ transfer function.
7859
7860 \value HDRExtendedDisplayP3Linear 16-bit float RGBA, high dynamic range,
7861 extended linear Display P3 color space. The primary choice for HDR on
7862 platforms such as iOS and VisionOS.
7863 */
7864
7865/*!
7866 \internal
7867 */
7868QRhiSwapChain::QRhiSwapChain(QRhiImplementation *rhi)
7869 : QRhiResource(rhi)
7870{
7871}
7872
7873/*!
7874 \return the resource type.
7875 */
7876QRhiResource::Type QRhiSwapChain::resourceType() const
7877{
7878 return SwapChain;
7879}
7880
7881/*!
7882 \fn QSize QRhiSwapChain::currentPixelSize() const
7883
7884 \return the size with which the swapchain was last successfully built. Use
7885 this to decide if createOrResize() needs to be called again: if
7886 \c{currentPixelSize() != surfacePixelSize()} then the swapchain needs to be
7887 resized.
7888
7889 \note Typical rendering logic will call this function to get the output
7890 size when starting to prepare a new frame, and base dependent calculations
7891 (such as, the viewport) on the size returned from this function.
7892
7893 While in many cases the value is the same as \c{QWindow::size() *
7894 QWindow::devicePixelRatio()}, relying on the QWindow-reported size is not
7895 guaranteed to be correct on all platforms and graphics API implementations.
7896 Using this function is therefore strongly recommended whenever there is a
7897 need to identify the dimensions, in pixels, of the output layer or surface.
7898
7899 This also has the added benefit of avoiding potential data races when QRhi
7900 is used on a dedicated rendering thread, because the need to call QWindow
7901 functions, that may then access data updated on the main thread, is
7902 avoided.
7903
7904 \sa surfacePixelSize()
7905 */
7906
7907/*!
7908 \fn virtual QSize QRhiSwapChain::surfacePixelSize() = 0
7909
7910 \return The size of the window's associated surface or layer.
7911
7912 \warning Do not assume this is the same as \c{QWindow::size() *
7913 QWindow::devicePixelRatio()}. With some graphics APIs and windowing system
7914 interfaces (for example, Vulkan) there is a theoretical possibility for a
7915 surface to assume a size different from the associated window. To support
7916 these cases, \b{rendering logic must always base size-derived calculations
7917 (such as, viewports) on the size reported from QRhiSwapChain, and never on
7918 the size queried from QWindow}.
7919
7920 \note \b{Can also be called before createOrResize(), if at least window() is
7921 already set. This in combination with currentPixelSize() allows to detect
7922 when a swapchain needs to be resized.} However, watch out for the fact that
7923 the size of the underlying native object (surface, layer, or similar) is
7924 "live", so whenever this function is called, it returns the latest value
7925 reported by the underlying implementation, without any atomicity guarantee.
7926 Therefore, using this function to determine pixel sizes for graphics
7927 resources that are used in a frame is strongly discouraged. Rely on
7928 currentPixelSize() instead which returns a size that is atomic and will not
7929 change between createOrResize() invocations.
7930
7931 \note For depth-stencil buffers used in combination with the swapchain's
7932 color buffers, it is strongly recommended to rely on the automatic sizing
7933 and rebuilding behavior provided by the
7934 QRhiRenderBuffer:UsedWithSwapChainOnly flag. Avoid querying the surface
7935 size via this function just to get a size that can be passed to
7936 QRhiRenderBuffer::setPixelSize() as that would suffer from the lack of
7937 atomicity as described above.
7938
7939 \sa currentPixelSize()
7940 */
7941
7942/*!
7943 \fn virtual bool QRhiSwapChain::isFormatSupported(Format f) = 0
7944
7945 \return true if the given swapchain format \a f is supported. SDR is always
7946 supported.
7947
7948 \note Can be called independently of createOrResize(), but window() must
7949 already be set. Calling without the window set may lead to unexpected
7950 results depending on the backend and platform (most likely false for any
7951 HDR format), because HDR format support is usually tied to the output
7952 (screen) to which the swapchain's associated window belongs at any given
7953 time. If the result is true for a HDR format, then creating the swapchain
7954 with that format is expected to succeed as long as the window is not moved
7955 to another screen in the meantime.
7956
7957 The main use of this function is to call it before the first
7958 createOrResize() after the window is already set. This allow the QRhi
7959 backends to perform platform or windowing system specific queries to
7960 determine if the window (and the screen it is on) is capable of true HDR
7961 output with the specified format.
7962
7963 When the format is reported as supported, call setFormat() to set the
7964 requested format and call createOrResize(). Be aware of the consequences
7965 however: successfully requesting a HDR format will involve having to deal
7966 with a different color space, possibly doing white level correction for
7967 non-HDR-aware content, adjusting tonemapping methods, adjusting offscreen
7968 render target settings, etc.
7969
7970 \sa setFormat()
7971 */
7972
7973/*!
7974 \fn virtual QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer() = 0
7975
7976 \return a command buffer on which rendering commands and resource updates
7977 can be recorded within a \l{QRhi::beginFrame()}{beginFrame} -
7978 \l{QRhi::endFrame()}{endFrame} block, assuming beginFrame() was called with
7979 this swapchain.
7980
7981 \note The returned object is valid also after endFrame(), up until the next
7982 beginFrame(), but the returned command buffer should not be used to record
7983 any commands then. Rather, it can be used to query data collected during
7984 the frame (or previous frames), for example by calling
7985 \l{QRhiCommandBuffer::lastCompletedGpuTime()}{lastCompletedGpuTime()}.
7986
7987 \note The value must not be cached and reused between frames. The caller
7988 should not hold on to the returned object once
7989 \l{QRhi::beginFrame()}{beginFrame()} is called again. Instead, the command
7990 buffer object should be queried again by calling this function.
7991*/
7992
7993/*!
7994 \fn virtual QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget() = 0
7995
7996 \return a render target that can used with beginPass() in order to render
7997 the swapchain's current backbuffer. Only valid within a
7998 QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called
7999 with this swapchain.
8000
8001 \note the value must not be cached and reused between frames
8002 */
8003
8004/*!
8005 \enum QRhiSwapChain::StereoTargetBuffer
8006 Selects the backbuffer to use with a stereoscopic swapchain.
8007
8008 \value LeftBuffer
8009 \value RightBuffer
8010 */
8011
8012/*!
8013 \return a render target that can be used with beginPass() in order to
8014 render to the swapchain's left or right backbuffer. This overload should be
8015 used only with stereoscopic rendering, that is, when the associated QWindow
8016 is backed by two color buffers, one for each eye, instead of just one.
8017
8018 When stereoscopic rendering is not supported, the return value will be
8019 the default target. It is supported by all hardware backends except for Metal, in
8020 combination with \l QSurfaceFormat::StereoBuffers, assuming it is supported
8021 by the graphics and display driver stack at run time. Metal and Null backends
8022 are going to return the default render target from this overload.
8023
8024 \note the value must not be cached and reused between frames
8025 */
8026QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
8027{
8028 Q_UNUSED(targetBuffer);
8029 return currentFrameRenderTarget();
8030}
8031
8032/*!
8033 \fn virtual bool QRhiSwapChain::createOrResize() = 0
8034
8035 Creates the swapchain if not already done and resizes the swapchain buffers
8036 to match the current size of the targeted surface. Call this whenever the
8037 size of the target surface is different than before.
8038
8039 \note call destroy() only when the swapchain needs to be released
8040 completely, typically upon
8041 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed. To perform resizing, just
8042 call createOrResize().
8043
8044 \return \c true when successful, \c false when a graphics operation failed.
8045 Regardless of the return value, calling destroy() is always safe.
8046 */
8047
8048/*!
8049 \fn QWindow *QRhiSwapChain::window() const
8050 \return the currently set window.
8051 */
8052
8053/*!
8054 \fn void QRhiSwapChain::setWindow(QWindow *window)
8055 Sets the \a window.
8056 */
8057
8058/*!
8059 \fn QRhiSwapChainProxyData QRhiSwapChain::proxyData() const
8060 \return the currently set proxy data.
8061 */
8062
8063/*!
8064 \fn void QRhiSwapChain::setProxyData(const QRhiSwapChainProxyData &d)
8065 Sets the proxy data \a d.
8066
8067 \sa QRhi::updateSwapChainProxyData()
8068 */
8069
8070/*!
8071 \fn QRhiSwapChain::Flags QRhiSwapChain::flags() const
8072 \return the currently set flags.
8073 */
8074
8075/*!
8076 \fn void QRhiSwapChain::setFlags(Flags f)
8077 Sets the flags \a f.
8078 */
8079
8080/*!
8081 \fn QRhiSwapChain::Format QRhiSwapChain::format() const
8082 \return the currently set format.
8083 */
8084
8085/*!
8086 \fn void QRhiSwapChain::setFormat(Format f)
8087 Sets the format \a f.
8088
8089 Avoid setting formats that are reported as unsupported from
8090 isFormatSupported(). Note that support for a given format may depend on the
8091 screen the swapchain's associated window is opened on. On some platforms,
8092 such as Windows and macOS, for HDR output to work it is necessary to have
8093 HDR output enabled in the display settings.
8094
8095 See isFormatSupported(), \l QRhiSwapChainHdrInfo, and \l Format for more
8096 information on high dynamic range output.
8097 */
8098
8099/*!
8100 \fn QRhiRenderBuffer *QRhiSwapChain::depthStencil() const
8101 \return the currently associated renderbuffer for depth-stencil.
8102 */
8103
8104/*!
8105 \fn void QRhiSwapChain::setDepthStencil(QRhiRenderBuffer *ds)
8106 Sets the renderbuffer \a ds for use as a depth-stencil buffer.
8107 */
8108
8109/*!
8110 \fn int QRhiSwapChain::sampleCount() const
8111 \return the currently set sample count. 1 means no multisample antialiasing.
8112 */
8113
8114/*!
8115 \fn void QRhiSwapChain::setSampleCount(int samples)
8116
8117 Sets the sample count. Common values for \a samples are 1 (no MSAA), 4 (4x
8118 MSAA), or 8 (8x MSAA).
8119
8120 \sa QRhi::supportedSampleCounts()
8121 */
8122
8123/*!
8124 \fn QRhiRenderPassDescriptor *QRhiSwapChain::renderPassDescriptor() const
8125 \return the currently associated QRhiRenderPassDescriptor object.
8126 */
8127
8128/*!
8129 \fn void QRhiSwapChain::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
8130 Associates with the QRhiRenderPassDescriptor \a desc.
8131 */
8132
8133/*!
8134 \fn virtual QRhiRenderPassDescriptor *QRhiSwapChain::newCompatibleRenderPassDescriptor() = 0;
8135
8136 \return a new QRhiRenderPassDescriptor that is compatible with this swapchain.
8137
8138 The returned value is used in two ways: it can be passed to
8139 setRenderPassDescriptor() and
8140 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
8141 describes the attachments (color, depth/stencil) and the load/store
8142 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
8143 be used in combination with a swapchain that has a
8144 \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
8145 QRhiRenderPassDescriptor set.
8146
8147 \sa createOrResize()
8148 */
8149
8150/*!
8151 \fn QRhiShadingRateMap *QRhiSwapChain::shadingRateMap() const
8152 \return the currently set QRhiShadingRateMap. By default this is \nullptr.
8153 \since 6.9
8154 */
8155
8156/*!
8157 \fn void QRhiSwapChain::setShadingRateMap(QRhiShadingRateMap *map)
8158
8159 Associates with the specified QRhiShadingRateMap \a map. This is functional
8160 only when the \l QRhi::VariableRateShadingMap feature is reported as
8161 supported.
8162
8163 When QRhiCommandBuffer::setShadingRate() is also called, the higher of the
8164 two shading rates is used for each tile. There is currently no control
8165 offered over the combiner behavior.
8166
8167 \note Setting a shading rate map implies that a different, new
8168 QRhiRenderPassDescriptor is needed and some of the native swapchain objects
8169 must be rebuilt. Therefore, if the swapchain is already set up, call
8170 newCompatibleRenderPassDescriptor() and setRenderPassDescriptor() right
8171 after setShadingRateMap(). Then, createOrResize() must also be called again.
8172 This has rolling consequences, for example for graphics pipelines: those
8173 also need to be associated with the new QRhiRenderPassDescriptor and then
8174 rebuilt. See \l QRhiRenderPassDescriptor::serializedFormat() for some
8175 suggestions on how to deal with this. Remember to set the
8176 QRhiGraphicsPipeline::UsesShadingRate flag for them as well.
8177
8178 \since 6.9
8179 */
8180
8181/*!
8182 \struct QRhiSwapChainHdrInfo
8183 \inmodule QtGuiPrivate
8184 \inheaderfile rhi/qrhi.h
8185 \since 6.6
8186
8187 \brief Describes the high dynamic range related information of the
8188 swapchain's associated output.
8189
8190 To perform HDR-compatible tonemapping, where the target range is not [0,1],
8191 one often needs to know the maximum luminance of the display the
8192 swapchain's window is associated with. While this is often made
8193 user-configurable (think brightness, gamma and similar settings in games),
8194 it can be highly useful to set defaults based on the values reported by the
8195 display itself, thus providing a decent starting point.
8196
8197 There are some problems however: the information is exposed in different
8198 forms on different platforms, whereas with cross-platform graphics APIs
8199 there is often no associated solution at all, because managing such
8200 information is not in the scope of the API (and may rather be retrievable
8201 via other platform-specific means, if any).
8202
8203 With Metal on macOS/iOS, there is no luminance values exposed in the
8204 platform APIs. Instead, the maximum color component value, that would be
8205 1.0 in a non-HDR setup, is provided. The \c limitsType field indicates what
8206 kind of information is available. It is then up to the clients of QRhi to
8207 access the correct data from the \c limits union and use it as they see
8208 fit.
8209
8210 With an API like Vulkan, where there is no way to get such information, the
8211 values are always the built-in defaults.
8212
8213 Therefore, the struct returned from QRhiSwapChain::hdrInfo() contains
8214 either some hard-coded defaults or real values received from an API such as
8215 DXGI (IDXGIOutput6) or Cocoa (NSScreen). When no platform queries are
8216 available (or needs using platform facilities out of scope for QRhi), the
8217 hard-coded defaults are a maximum luminance of 1000 nits and an SDR white
8218 level of 200.
8219
8220 The struct also exposes the presumed luminance behavior of the platform and
8221 its compositor, to indicate what a color component value of 1.0 is treated
8222 as in a HDR color buffer. In some cases it will be necessary to perform
8223 color correction of non-HDR content composited with HDR content. To enable
8224 this, the SDR white level is queried from the system on some platforms
8225 (Windows) and exposed here.
8226
8227 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8228 for details.
8229
8230 \sa QRhiSwapChain::hdrInfo()
8231 */
8232
8233/*!
8234 \enum QRhiSwapChainHdrInfo::LimitsType
8235
8236 \value LuminanceInNits Indicates that the \l limits union has its
8237 \c luminanceInNits struct set
8238
8239 \value ColorComponentValue Indicates that the \l limits union has its
8240 \c colorComponentValue struct set
8241*/
8242
8243/*!
8244 \enum QRhiSwapChainHdrInfo::LuminanceBehavior
8245
8246 \value SceneReferred Indicates that the color value of 1.0 is interpreted
8247 as 80 nits. This is the behavior of HDR-enabled windows with the Windows
8248 compositor. See
8249 \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range}{this
8250 page} for more information on HDR on Windows.
8251
8252 \value DisplayReferred Indicates that the color value of 1.0 is interpreted
8253 as the value of the SDR white. (which can be e.g. 200 nits, but will vary
8254 depending on screen brightness) This is the behavior of HDR-enabled windows
8255 on Apple platforms. See
8256 \l{https://developer.apple.com/documentation/metal/hdr_content/displaying_hdr_content_in_a_metal_layer}{this
8257 page} for more information on Apple's EDR system.
8258*/
8259
8260/*!
8261 \variable QRhiSwapChainHdrInfo::limitsType
8262
8263 With Metal on macOS/iOS, there is no luminance values exposed in the
8264 platform APIs. Instead, the maximum color component value, that would be
8265 1.0 in a non-HDR setup, is provided. This value indicates what kind of
8266 information is available in \l limits.
8267
8268 \sa QRhiSwapChain::hdrInfo()
8269*/
8270
8271/*!
8272 \variable QRhiSwapChainHdrInfo::limits
8273
8274 Contains the actual values queried from the graphics API or the platform.
8275 The type of data is indicated by \l limitsType. This is therefore a union.
8276 There are currently two options:
8277
8278 Luminance values in nits:
8279
8280 \code
8281 struct {
8282 float minLuminance;
8283 float maxLuminance;
8284 } luminanceInNits;
8285 \endcode
8286
8287 On Windows the minimum and maximum luminance depends on the screen
8288 brightness. While not relevant for desktops, on laptops the screen
8289 brightness may change at any time. Increasing brightness implies decreased
8290 maximum luminance. In addition, the results may also be dependent on the
8291 HDR Content Brightness set in Windows Settings' System/Display/HDR view,
8292 if there is such a setting.
8293
8294 Note however that the changes made to the laptop screen's brightness or in
8295 the system settings while the application is running are not necessarily
8296 reflected in the returned values, meaning calling hdrInfo() again may still
8297 return the same luminance range as before for the rest of the process'
8298 lifetime. The exact behavior is up to DXGI and Qt has no control over it.
8299
8300 \note The Windows compositor works in scene-referred mode for HDR content.
8301 A color component value of 1.0 corresponds to a luminance of 80 nits. When
8302 rendering non-HDR content (e.g. 2D UI elements), the correction of the
8303 white level is often necessary. (e.g., outputting the fragment color (1, 1,
8304 1) will likely lead to showing a shade of white that is too dim on-screen)
8305 See \l sdrWhiteLevel.
8306
8307 For macOS/iOS, the current maximum and potential maximum color
8308 component values are provided:
8309
8310 \code
8311 struct {
8312 float maxColorComponentValue;
8313 float maxPotentialColorComponentValue;
8314 } colorComponentValue;
8315 \endcode
8316
8317 The value may depend on the screen brightness, which on laptops means that
8318 the result may change in the next call to hdrInfo() if the brightness was
8319 changed in the meantime. The maximum screen brightness implies a maximum
8320 color value of 1.0.
8321
8322 \note Apple's EDR is display-referred. 1.0 corresponds to a luminance level
8323 of SDR white (e.g. 200 nits), the value of which varies based on the screen
8324 brightness and possibly other settings. The exact luminance value for that,
8325 or the maximum luminance of the display, are not exposed to the
8326 applications.
8327
8328 \note It has been observed that the color component values are not set to
8329 the correct larger-than-1 value right away on startup on some macOS
8330 systems, but the values tend to change during or after the first frame.
8331
8332 \sa QRhiSwapChain::hdrInfo()
8333*/
8334
8335/*!
8336 \variable QRhiSwapChainHdrInfo::luminanceBehavior
8337
8338 Describes the platform's presumed behavior with regards to color values.
8339
8340 \sa sdrWhiteLevel
8341 */
8342
8343/*!
8344 \variable QRhiSwapChainHdrInfo::sdrWhiteLevel
8345
8346 On Windows this is the dynamic SDR white level in nits. The value is
8347 dependent on the screen brightness (on laptops), and the SDR or HDR Content
8348 Brightness settings in the Windows settings' System/Display/HDR view.
8349
8350 To perform white level correction for non-HDR (SDR) content, such as 2D UI
8351 elemenents, multiply the final color with sdrWhiteLevel / 80.0 whenever
8352 \l luminanceBehavior is SceneReferred. (assuming Windows and a linear
8353 extended sRGB (scRGB) color space)
8354
8355 On other platforms the value is always a pre-defined value, 200. This may
8356 not match the system's actual SDR white level, but the value of this
8357 variable is not relevant in practice when the \l luminanceBehavior is
8358 DisplayReferred, because then the color component value of 1.0 refers to
8359 the SDR white by default.
8360
8361 \sa luminanceBehavior
8362*/
8363
8364/*!
8365 \return the HDR information for the associated display.
8366
8367 Do not assume that this is a cheap operation. Depending on the platform,
8368 this function makes various platform queries which may have a performance
8369 impact.
8370
8371 \note Can be called before createOrResize() as long as the window is
8372 \l{setWindow()}{set}.
8373
8374 \note What happens when moving a window with an initialized swapchain
8375 between displays (HDR to HDR with different characteristics, HDR to SDR,
8376 etc.) is not currently well-defined and depends heavily on the windowing
8377 system and compositor, with potentially varying behavior between platforms.
8378 Currently QRhi only guarantees that hdrInfo() returns valid data, if
8379 available, for the display to which the swapchain's associated window
8380 belonged at the time of createOrResize().
8381
8382 \sa QRhiSwapChainHdrInfo
8383 */
8384QRhiSwapChainHdrInfo QRhiSwapChain::hdrInfo()
8385{
8386 QRhiSwapChainHdrInfo info;
8387 info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
8388 info.limits.luminanceInNits.minLuminance = 0.0f;
8389 info.limits.luminanceInNits.maxLuminance = 1000.0f;
8390 info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
8391 info.sdrWhiteLevel = 200.0f;
8392 return info;
8393}
8394
8395#ifndef QT_NO_DEBUG_STREAM
8396QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
8397{
8398 QDebugStateSaver saver(dbg);
8399 dbg.nospace() << "QRhiSwapChainHdrInfo(";
8400 switch (info.limitsType) {
8402 dbg.nospace() << " minLuminance=" << info.limits.luminanceInNits.minLuminance
8403 << " maxLuminance=" << info.limits.luminanceInNits.maxLuminance;
8404 break;
8406 dbg.nospace() << " maxColorComponentValue=" << info.limits.colorComponentValue.maxColorComponentValue;
8407 dbg.nospace() << " maxPotentialColorComponentValue=" << info.limits.colorComponentValue.maxPotentialColorComponentValue;
8408 break;
8409 }
8410 switch (info.luminanceBehavior) {
8412 dbg.nospace() << " scene-referred, SDR white level=" << info.sdrWhiteLevel;
8413 break;
8415 dbg.nospace() << " display-referred";
8416 break;
8417 }
8418 dbg.nospace() << ')';
8419 return dbg;
8420}
8421#endif
8422
8423/*!
8424 \class QRhiComputePipeline
8425 \inmodule QtGuiPrivate
8426 \inheaderfile rhi/qrhi.h
8427 \since 6.6
8428 \brief Compute pipeline state resource.
8429
8430 \note Setting the shader resource bindings is mandatory. The referenced
8431 QRhiShaderResourceBindings must already have created() called on it by the
8432 time create() is called.
8433
8434 \note Setting the shader is mandatory.
8435
8436 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8437 for details.
8438 */
8439
8440/*!
8441 \enum QRhiComputePipeline::Flag
8442
8443 Flag values for describing pipeline options.
8444
8445 \value CompileShadersWithDebugInfo Requests compiling shaders with debug
8446 information enabled, when applicable. See
8447 QRhiGraphicsPipeline::CompileShadersWithDebugInfo for more information.
8448 */
8449
8450/*!
8451 \return the resource type.
8452 */
8453QRhiResource::Type QRhiComputePipeline::resourceType() const
8454{
8455 return ComputePipeline;
8456}
8457
8458/*!
8459 \internal
8460 */
8461QRhiComputePipeline::QRhiComputePipeline(QRhiImplementation *rhi)
8462 : QRhiResource(rhi)
8463{
8464}
8465
8466/*!
8467 \fn QRhiComputePipeline::Flags QRhiComputePipeline::flags() const
8468 \return the currently set flags.
8469 */
8470
8471/*!
8472 \fn void QRhiComputePipeline::setFlags(Flags f)
8473 Sets the flags \a f.
8474 */
8475
8476/*!
8477 \fn QRhiShaderStage QRhiComputePipeline::shaderStage() const
8478 \return the currently set shader.
8479 */
8480
8481/*!
8482 \fn void QRhiComputePipeline::setShaderStage(const QRhiShaderStage &stage)
8483
8484 Sets the shader to use. \a stage can only refer to the
8485 \l{QRhiShaderStage::Compute}{compute stage}.
8486 */
8487
8488/*!
8489 \fn QRhiShaderResourceBindings *QRhiComputePipeline::shaderResourceBindings() const
8490 \return the currently associated QRhiShaderResourceBindings object.
8491 */
8492
8493/*!
8494 \fn void QRhiComputePipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
8495
8496 Associates with \a srb describing the resource binding layout and the
8497 resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional. As
8498 with graphics pipelines, the \a srb passed in here can leave the actual
8499 buffer or texture objects unspecified (\nullptr) as long as there is
8500 another,
8501 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
8502 QRhiShaderResourceBindings bound via
8503 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
8504 recording the dispatch call.
8505 */
8506
8507/*!
8508 \struct QRhiIndirectDrawCommand
8509 \inmodule QtGuiPrivate
8510 \inheaderfile rhi/qrhi.h
8511 \since 6.12
8512 \brief Draw command.
8513
8514 A draw command that can be uploaded to a QRhiBuffer of usage
8515 QRhiBuffer::UsageFlag::IndirectBuffer.
8516
8517 \sa QRhiCommandBuffer::drawIndirect()
8518
8519 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8520 for details.
8521 */
8522
8523/*!
8524 \variable QRhiIndirectDrawCommand::vertexCount
8525*/
8526
8527/*!
8528 \variable QRhiIndirectDrawCommand::instanceCount
8529*/
8530
8531/*!
8532 \variable QRhiIndirectDrawCommand::firstVertex
8533*/
8534
8535/*!
8536 \variable QRhiIndirectDrawCommand::firstInstance
8537*/
8538
8539/*!
8540 \struct QRhiIndexedIndirectDrawCommand
8541 \inmodule QtGuiPrivate
8542 \inheaderfile rhi/qrhi.h
8543 \since 6.12
8544 \brief Indexed draw command.
8545
8546 An indexed draw command that can be uploaded to a QRhiBuffer of usage
8547 QRhiBuffer::UsageFlag::IndirectBuffer.
8548
8549 \sa QRhiCommandBuffer::drawIndexedIndirect()
8550
8551 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8552 for details.
8553 */
8554
8555/*!
8556 \variable QRhiIndexedIndirectDrawCommand::indexCount
8557*/
8558
8559/*!
8560 \variable QRhiIndexedIndirectDrawCommand::instanceCount
8561*/
8562
8563/*!
8564 \variable QRhiIndexedIndirectDrawCommand::firstIndex
8565*/
8566
8567/*!
8568 \variable QRhiIndexedIndirectDrawCommand::vertexOffset
8569*/
8570
8571/*!
8572 \variable QRhiIndexedIndirectDrawCommand::firstInstance
8573*/
8574
8575/*!
8576 \struct QRhiDispatchIndirectCommand
8577 \inmodule QtGuiPrivate
8578 \inheaderfile rhi/qrhi.h
8579 \since 6.13
8580 \brief Compute dispatch command.
8581
8582 A compute dispatch command that can be uploaded to a QRhiBuffer of usage
8583 QRhiBuffer::UsageFlag::IndirectBuffer. The fields specify the number of
8584 local work groups along each dimension and have the same meaning as the
8585 \c x, \c y, \c z parameters of QRhiCommandBuffer::dispatch().
8586
8587 \c y and \c z default to 1, so a one dimensional dispatch only needs \c x
8588 to be set. Note that a count of 0 in any dimension is valid and results in
8589 no work groups being launched at all.
8590
8591 \sa QRhiCommandBuffer::dispatchIndirect()
8592
8593 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8594 for details.
8595 */
8596
8597/*!
8598 \variable QRhiDispatchIndirectCommand::x
8599*/
8600
8601/*!
8602 \variable QRhiDispatchIndirectCommand::y
8603*/
8604
8605/*!
8606 \variable QRhiDispatchIndirectCommand::z
8607*/
8608
8609/*!
8610 \class QRhiIndirectCommandBuffer
8611 \inmodule QtGuiPrivate
8612 \inheaderfile rhi/qrhi.h
8613 \since 6.13
8614 \brief A prerecorded batch of indirect draw commands.
8615
8616 A QRhiIndirectCommandBuffer holds a number of draw commands that are
8617 recorded once and can then be replayed any number of times with a single
8618 QRhiCommandBuffer::executeIndirect() call. It is an alternative to the
8619 buffer-based QRhiCommandBuffer::drawIndirect() family of functions. Under
8620 the hood, it may do exactly the same as does (typical with Vulkan, Direct
8621 3D, and OpenGL), or may be implemented differently (Metal).
8622
8623 Create one with QRhi::newIndirectCommandBuffer(), passing in the type and
8624 the maximum number of commands, and call create(). The (maximum) command
8625 count is mandatory, whichever way the commands are going to be provided: it
8626 is the capacity of the object, and create() fails when it is 0.
8627
8628 \badcode
8629 icb = rhi->newIndirectCommandBuffer(QRhiIndirectCommandBuffer::IndexedDraws, 1024);
8630 if (!icb->create()) { error(); }
8631 \endcode
8632
8633 Record commands with draw() or drawIndexed(), then hand the object to a
8634 resource update batch so that the recorded contents reach the GPU.
8635 commitIndirectCommandBuffer() has to be called after recording and before
8636 the pass that executes the commands. It is a no-op when nothing changed
8637 since the last time, so calling it every frame is cheap.
8638
8639 Executing happens inside a render pass:
8640
8641 \badcode
8642 icb->clear();
8643 for (const Item &item : items)
8644 icb->drawIndexed(item.indexCount, 1, item.firstIndex, item.vertexOffset);
8645
8646 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
8647 u->commitIndirectCommandBuffer(icb);
8648
8649 cb->beginPass(rt, Qt::black, { 1.0f, 0 }, u);
8650 cb->setGraphicsPipeline(ps);
8651 cb->setVertexInput(0, 1, &vbufBinding, ibuf, 0, QRhiCommandBuffer::IndexUInt16);
8652 cb->setShaderResources();
8653 cb->executeIndirect(icb);
8654 cb->endPass();
8655 \endcode
8656
8657 The commands can also be generated on the GPU instead of being recorded on
8658 the CPU. In that case fill a buffer with QRhiIndirectDrawCommand or
8659 QRhiIndexedIndirectDrawCommand entries from a compute shader, and call
8660 QRhiCommandBuffer::buildIndirect() with that buffer. That call must happen
8661 outside of any pass. The CPU-side recording functions of
8662 QRhiIndirectCommandBuffer are not used in this case.
8663
8664 \badcode
8665 cb->beginComputePass();
8666 ... // a cb->dispatch() to invoke a compute shader that writes to indirectBuf
8667 cb->endComputePass();
8668
8669 QRhiIndirectCommandBufferBuildInfo buildInfo;
8670 buildInfo.topology = ps->topology();
8671 buildInfo.sourceBuffer = indirectBuf;
8672 buildInfo.commandCount = itemCount; // as many as the compute shader wrote
8673 buildInfo.indexBuffer = indexBuffer;
8674 buildInfo.indexFormat = QRhiCommandBuffer::IndexUInt16;
8675 cb->buildIndirect(icb, buildInfo);
8676
8677 cb->beginPass(rt, Qt::black, { 1.0f, 0 });
8678 cb->setGraphicsPipeline(ps);
8679 cb->setVertexInput(0, 1, &vbufBinding, ibuf, 0, QRhiCommandBuffer::IndexUInt16);
8680 cb->setShaderResources();
8681 cb->executeIndirect(icb);
8682 cb->endPass();
8683 \endcode
8684
8685 When the number of commands is itself decided on the device, set
8686 QRhiIndirectCommandBufferBuildInfo::countBuffer instead of working out
8687 \c itemCount on the CPU. See \l{Command counts} below.
8688
8689 \section2 Command counts
8690
8691 Three counts are involved, and they are not the same thing:
8692
8693 \list
8694
8695 \li maxCommandCount() is the capacity. It is fixed at create() time and
8696 sizes whatever native object the backend needs. Neither of the two ways of
8697 providing commands can exceed it; attempting to does not grow the object.
8698
8699 \li recordedCommandCount() is how many draw() or drawIndexed() calls were
8700 made since the last clear(). It only concerns the CPU-recorded case.
8701
8702 \li commandCount() is how many commands QRhiCommandBuffer::executeIndirect()
8703 issues by default. For a CPU-recorded indirect command buffer that is
8704 recordedCommandCount(). Once QRhiCommandBuffer::buildIndirect() has been
8705 called, isGpuBuilt() returns true and commandCount() is the count resolved
8706 from QRhiIndirectCommandBufferBuildInfo::commandCount instead (but note that
8707 that value is the actual command count only when no
8708 \l{QRhiIndirectCommandBufferBuildInfo::}countBuffer is set, is just a
8709 maximum with a counter buffer present).
8710
8711 \endlist
8712
8713 The size of QRhiIndirectCommandBufferBuildInfo::sourceBuffer plays no part
8714 in any of this: no count is ever derived from it. The buffer is written by
8715 the GPU and is free to be larger than the number of commands actually in
8716 it, so leaving QRhiIndirectCommandBufferBuildInfo::commandCount at 0 does
8717 not mean "as many as fit", it means maxCommandCount().
8718
8719 A device-side count, via QRhiIndirectCommandBufferBuildInfo::countBuffer,
8720 narrows the count further when the commands are executed, and can only
8721 reduce it: the value in the count buffer is clamped to what
8722 commandCount() returns.
8723
8724 Either way, the indirect command buffer is fully prepared before the render
8725 pass begins. That is what separates it from the buffer-based
8726 QRhiCommandBuffer::drawIndirect() family, where some backends (Metal above a
8727 certain draw count, and always for the count variants) have to interrupt and
8728 restart the render pass in order to encode the commands. Such an
8729 interruption costs a QRhiRenderBuffer depth-stencil buffer its contents
8730 unless QRhiRenderBuffer::NoTransientBacking was set, and may also be degrading
8731 performance due to having to reload the color buffer values. With
8732 executeIndirect() the question does not arise.
8733
8734 For Metal, the buffer-based API implies (ahove a certain draw count, or
8735 whhen using the count variants) having to run a compute kernel to create an
8736 MTLIndirectCommandBuffer from the Vulkan/Direct 3D/OpenGL style indirect
8737 buffer. With QRhiIndirectCommandBuffer this is not always necessary, because
8738 now, at least when the commands are generated on the CPU side, an
8739 MTLIndirectCommandBuffer can be created and set up normally, by calling
8740 MTLIndirectCommandBuffer's Objective-C API, instead of having to inject a
8741 compute pass. When generating the commands on the GPU, the extra compute
8742 pass is still necessary, but at least it will not interrupt the render pass,
8743 by design, unlike with the direct buffer-based API. Note however that using
8744 MTLIndirectCommandBuffer natively from C++/Objective-C to perform repeated
8745 CPU-side draw call generation can prove to be quite expensive (when
8746 frequently re-recording a larger set of draw commands), compared to the
8747 GPU-side draw command generation, even though that involves an extra encoding
8748 compute pass to "convert" the Vulkan/Direct 3D/OpenGL style indirect buffer
8749 to what Metal prefers. See the next section.
8750
8751 \section2 Recording on the CPU or building on the GPU
8752
8753 The two ways of populating an indirect command buffer are not equivalent in
8754 cost, and the difference grows with the number of commands.
8755
8756 Recording with draw() or drawIndexed() is work proportional to the number of
8757 commands, and it is repeated whenever the contents change. Where that work
8758 lands depends on the backend: those that keep the commands in a buffer
8759 upload it from QRhiResourceUpdateBatch::commitIndirectCommandBuffer(),
8760 whereas Metal encodes each command individually into a native
8761 \c MTLIndirectCommandBuffer, one native call per command, and does so from
8762 QRhiCommandBuffer::executeIndirect().
8763
8764 Either way the result is cached and keyed on the recorded contents, so an
8765 indirect command buffer that is recorded once and then executed unchanged
8766 frame after frame costs nothing beyond the first few frames. That is the
8767 case CPU recording is meant for: a command set that is stable, or changes
8768 rarely, relative to how often it is executed.
8769
8770 The opposite case - many commands, cleared and re-recorded every frame - is
8771 the one to avoid. Regenerating tens of thousands of commands per frame that
8772 way can be an order of magnitude more expensive on Apple platforms than
8773 filling a QRhiBuffer and calling QRhiCommandBuffer::drawIndexedIndirect() on
8774 it, because of the per-command native encoding. When the command set is both
8775 large and regenerated every frame, generate it on the GPU and use
8776 QRhiCommandBuffer::buildIndirect(); the alternative is to stay with the
8777 buffer-based drawIndirect() family and accept the render pass interruption
8778 it may cause (which is still not recommended, even if it would perform
8779 better).
8780
8781 A given QRhiIndirectCommandBuffer holds one kind of command: either
8782 non-indexed draws (\c Draws) or indexed draws (\c IndexedDraws), never a
8783 mix of the two. This mirrors what the underlying APIs can express: a single
8784 indirect draw call always has one command type and one stride.
8785
8786 The requirements are the same as for the indirect draws this stands in for:
8787 QRhi::DrawIndirect has to be supported, the graphics pipeline should be
8788 created with \l{QRhiGraphicsPipeline::UsesIndirectDraws}{UsesIndirectDraws},
8789 and a count buffer additionally needs QRhi::DrawIndirectCount to be
8790 supported.
8791
8792 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8793 for details.
8794
8795 \sa QRhiCommandBuffer::executeIndirect(), QRhiCommandBuffer::drawIndirect()
8796 */
8797
8798/*!
8799 \enum QRhiIndirectCommandBuffer::Type
8800 Specifies the kind of commands an indirect command buffer holds.
8801
8802 \value Draws Non-indexed draw commands, recorded with draw().
8803 \value IndexedDraws Indexed draw commands, recorded with drawIndexed().
8804 */
8805
8806/*!
8807 \fn QRhiIndirectCommandBuffer::Type QRhiIndirectCommandBuffer::type() const
8808 \return the type of commands this indirect command buffer holds.
8809 */
8810
8811/*!
8812 \fn void QRhiIndirectCommandBuffer::setType(Type t)
8813
8814 Sets the command type \a t. The type is normally specified in
8815 QRhi::newIndirectCommandBuffer(), so this function is only used when it has
8816 to be changed. As with other setters, it only takes effect when calling
8817 create().
8818 */
8819
8820/*!
8821 \fn quint32 QRhiIndirectCommandBuffer::maxCommandCount() const
8822 \return the capacity, i.e. the maximum number of commands.
8823 */
8824
8825/*!
8826 \fn void QRhiIndirectCommandBuffer::setMaxCommandCount(quint32 count)
8827
8828 Sets the capacity, the maximum number of commands, to \a count. The
8829 capacity is normally specified in QRhi::newIndirectCommandBuffer(), so this
8830 function is only used when it has to be changed. As with other setters, it
8831 only takes effect when calling create(), which fails when \a count is 0.
8832
8833 The capacity applies regardless of how the commands are going to be
8834 provided: recording them with draw() and drawIndexed() and building them
8835 with QRhiCommandBuffer::buildIndirect() are both bounded by it.
8836
8837 draw() and drawIndexed() ignore, with a warning, any command past the first
8838 \a count ones. QRhiCommandBuffer::buildIndirect() clamps, also with a
8839 warning, when QRhiIndirectCommandBufferBuildInfo::commandCount is larger.
8840
8841 \sa commandCount(), recordedCommandCount()
8842 */
8843
8844/*!
8845 \fn quint32 QRhiIndirectCommandBuffer::recordedCommandCount() const
8846
8847 \return the number of commands recorded with draw() or drawIndexed() since
8848 the last clear().
8849
8850 This is unaffected by QRhiCommandBuffer::buildIndirect(): once the commands
8851 come from the GPU, whatever was recorded on the CPU is ignored. Use
8852 commandCount() to get the number of commands that will actually be
8853 executed.
8854 */
8855
8856/*!
8857 \fn bool QRhiIndirectCommandBuffer::isGpuBuilt() const
8858
8859 \return \c true when QRhiCommandBuffer::buildIndirect() has been called on
8860 this indirect command buffer, meaning its contents come from a QRhiBuffer
8861 instead of from draw() and drawIndexed().
8862
8863 Once true, this stays true until the next create().
8864 */
8865
8866/*!
8867 \fn quint32 QRhiIndirectCommandBuffer::commandCount() const
8868
8869 \return the number of commands QRhiCommandBuffer::executeIndirect() issues
8870 by default.
8871
8872 This is recordedCommandCount() for a CPU-recorded indirect command buffer,
8873 and the count resolved from
8874 QRhiIndirectCommandBufferBuildInfo::commandCount once
8875 QRhiCommandBuffer::buildIndirect() has been called.
8876
8877 A count buffer, if there is one, can reduce the number of draws further at
8878 execution time. This function does not, and cannot, account for that.
8879 */
8880
8881/*!
8882 \fn virtual bool QRhiIndirectCommandBuffer::create() = 0
8883
8884 Creates the corresponding native objects.
8885
8886 Fails when maxCommandCount() is 0.
8887
8888 A given QRhiIndirectCommandBuffer takes its commands either from draw() and
8889 drawIndexed() followed by
8890 QRhiResourceUpdateBatch::commitIndirectCommandBuffer(), or from
8891 QRhiCommandBuffer::buildIndirect(), but not from both. Moving to the latter
8892 is one-way: clear() does not undo it, and neither does a subsequent
8893 commitIndirectCommandBuffer(); isGpuBuilt() stays true and the commands keep
8894 coming from the buffer. Call create() again to get an indirect command
8895 buffer that is populated from the CPU once more.
8896
8897 \note Like with every other QRhi resource, destroy() gives up the contents,
8898 and so create() starts from an empty indirect command buffer:
8899 recordedCommandCount() is 0 afterwards. Setting a different type() or
8900 maxCommandCount() and calling create() again therefore needs the commands
8901 to be recorded again as well.
8902
8903 \return \c true when successful, \c false when a graphics operation failed.
8904 */
8905
8906/*!
8907 \internal
8908 */
8909QRhiIndirectCommandBuffer::QRhiIndirectCommandBuffer(QRhiImplementation *rhi, Type type_,
8910 quint32 maxCommandCount_)
8911 : QRhiResource(rhi),
8912 m_type(type_), m_maxCommandCount(maxCommandCount_)
8913{
8914}
8915
8916/*!
8917 \return the resource type.
8918 */
8919QRhiResource::Type QRhiIndirectCommandBuffer::resourceType() const
8920{
8921 return IndirectCommandBuffer;
8922}
8923
8924/*!
8925 Discards all commands recorded so far.
8926
8927 Can be called at any time, also before create(). The recorded contents only
8928 become visible to the GPU once the object is passed to
8929 QRhiResourceUpdateBatch::commitIndirectCommandBuffer().
8930
8931 This resets recordedCommandCount() to 0. It does not undo a
8932 QRhiCommandBuffer::buildIndirect(): an indirect command buffer that gets
8933 its commands from the GPU keeps doing so, and commandCount() is unchanged.
8934
8935 \note Clearing and re-recording invalidates whatever the backend cached for
8936 the previous contents, so the per-command cost of recording is paid again.
8937 Call this only when the commands actually have to change. See
8938 \l{Recording on the CPU or building on the GPU} for why that matters at high
8939 command counts.
8940 */
8941void QRhiIndirectCommandBuffer::clear()
8942{
8943 m_data.clear();
8944 m_commandCount = 0;
8945 m_generation += 1;
8946}
8947
8948/*!
8949 Records a non-indexed draw command with \a vertexCount, \a instanceCount,
8950 \a firstVertex, and \a firstInstance.
8951
8952 The semantics are the same as QRhiCommandBuffer::draw().
8953
8954 \note Only valid on an indirect command buffer of type Draws.
8955 */
8956void QRhiIndirectCommandBuffer::draw(quint32 vertexCount, quint32 instanceCount,
8957 quint32 firstVertex, quint32 firstInstance)
8958{
8959 if (m_type != Draws) {
8960 qWarning("QRhiIndirectCommandBuffer: draw() on an IndexedDraws indirect command buffer; ignored");
8961 return;
8962 }
8963 if (m_commandCount == m_maxCommandCount) {
8964 qWarning("QRhiIndirectCommandBuffer: maxCommandCount (%u) reached; command ignored",
8965 m_maxCommandCount);
8966 return;
8967 }
8968 const QRhiIndirectDrawCommand cmd = { vertexCount, instanceCount, firstVertex, firstInstance };
8969 m_data.append(reinterpret_cast<const char *>(&cmd), sizeof(cmd));
8970 m_commandCount += 1;
8971 m_generation += 1;
8972}
8973
8974/*!
8975 Records an indexed draw command with \a indexCount, \a instanceCount, \a
8976 firstIndex, \a vertexOffset, and \a firstInstance.
8977
8978 The semantics are the same as QRhiCommandBuffer::drawIndexed().
8979
8980 \note Only valid on an indirect command buffer of type IndexedDraws.
8981 */
8982void QRhiIndirectCommandBuffer::drawIndexed(quint32 indexCount, quint32 instanceCount,
8983 quint32 firstIndex, qint32 vertexOffset,
8984 quint32 firstInstance)
8985{
8986 if (m_type != IndexedDraws) {
8987 qWarning("QRhiIndirectCommandBuffer: drawIndexed() on a Draws indirect command buffer; ignored");
8988 return;
8989 }
8990 if (m_commandCount == m_maxCommandCount) {
8991 qWarning("QRhiIndirectCommandBuffer: maxCommandCount (%u) reached; command ignored",
8992 m_maxCommandCount);
8993 return;
8994 }
8995 const QRhiIndexedIndirectDrawCommand cmd = { indexCount, instanceCount, firstIndex,
8996 vertexOffset, firstInstance };
8997 m_data.append(reinterpret_cast<const char *>(&cmd), sizeof(cmd));
8998 m_commandCount += 1;
8999 m_generation += 1;
9000}
9001
9002/*!
9003 \struct QRhiIndirectCommandBufferBuildInfo
9004 \inmodule QtGuiPrivate
9005 \inheaderfile rhi/qrhi.h
9006 \since 6.13
9007 \brief Describes how to build an indirect command buffer from a QRhiBuffer.
9008
9009 \sa QRhiCommandBuffer::buildIndirect()
9010
9011 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9012 for details.
9013 */
9014
9015/*!
9016 \variable QRhiIndirectCommandBufferBuildInfo::topology
9017
9018 The topology the commands will be drawn with. Must match the topology of the
9019 graphics pipeline that is set when QRhiCommandBuffer::executeIndirect() is
9020 called. Some backends need it in order to build their native indirect
9021 command buffer, and it is not available to them outside of a render pass.
9022*/
9023
9024/*!
9025 \variable QRhiIndirectCommandBufferBuildInfo::sourceBuffer
9026
9027 The buffer holding the QRhiIndirectDrawCommand or
9028 QRhiIndexedIndirectDrawCommand entries. Must have IndirectBuffer usage.
9029
9030 Its size is not used to work out how many commands there are, see
9031 commandCount.
9032*/
9033
9034/*!
9035 \variable QRhiIndirectCommandBufferBuildInfo::sourceBufferOffset
9036*/
9037
9038/*!
9039 \variable QRhiIndirectCommandBufferBuildInfo::commandCount
9040
9041 The number of commands to take from sourceBuffer. This is what
9042 QRhiIndirectCommandBuffer::commandCount() reports afterwards, and so how
9043 many draws QRhiCommandBuffer::executeIndirect() issues by default.
9044
9045 0 means QRhiIndirectCommandBuffer::maxCommandCount(). It does not mean "as
9046 many as fit in sourceBuffer": a buffer written by the GPU can be larger
9047 than the number of commands in it, so no count is ever derived from its
9048 size. A value above QRhiIndirectCommandBuffer::maxCommandCount() is clamped
9049 to it, with a warning.
9050
9051 \note Specifying countBuffer changes what this value means: it stops being
9052 the number of commands and becomes the \e maximum number of commands, with
9053 the device-side count in countBuffer deciding the actual number. Without a
9054 countBuffer, exactly this many commands are executed.
9055*/
9056
9057/*!
9058 \variable QRhiIndirectCommandBufferBuildInfo::stride
9059
9060 The byte distance between two commands in sourceBuffer. 0 means the size of
9061 the corresponding command struct.
9062*/
9063
9064/*!
9065 \variable QRhiIndirectCommandBufferBuildInfo::countBuffer
9066
9067 An optional buffer whose first quint32 holds the number of commands to
9068 execute. Requires QRhi::DrawIndirectCount.
9069
9070 \note Setting this turns commandCount into an upper bound. The device-side
9071 value is clamped to it, so a count buffer can only ever reduce the number
9072 of draws, never raise it.
9073*/
9074
9075/*!
9076 \variable QRhiIndirectCommandBufferBuildInfo::countBufferOffset
9077*/
9078
9079/*!
9080 \variable QRhiIndirectCommandBufferBuildInfo::indexBuffer
9081
9082 The index buffer the commands index into. Required for IndexedDraws.
9083*/
9084
9085/*!
9086 \variable QRhiIndirectCommandBufferBuildInfo::indexBufferOffset
9087*/
9088
9089/*!
9090 \variable QRhiIndirectCommandBufferBuildInfo::indexFormat
9091*/
9092
9094 Type type,
9095 quint32 maxCommandCount)
9097{
9098}
9099
9104
9106{
9107 // Unconditionally, also when there is nothing else to do: like with every
9108 // other resource, destroy() gives up the contents. Carrying a recording
9109 // over into the next create() would not survive a changed maxCommandCount
9110 // or type.
9111 clear();
9112
9113 if (!valid)
9114 return;
9115
9116 delete buffer;
9117 buffer = nullptr;
9118 uploadedGeneration = 0;
9119 buildInfo = {};
9120 m_gpuBuilt = false;
9121 m_gpuBuiltCommandCount = 0;
9122 valid = false;
9123
9124 if (m_rhi)
9125 m_rhi->unregisterResource(this);
9126}
9127
9129{
9130 // Either way the recorded commands go: they may not fit maxCommandCount()
9131 // or match type() anymore.
9132 if (valid)
9133 destroy();
9134 else
9135 clear();
9136
9137 if (!m_maxCommandCount) {
9138 qWarning("QRhiIndirectCommandBuffer: maxCommandCount is 0");
9139 return false;
9140 }
9141
9142 valid = true;
9143 m_rhi->registerResource(this);
9144 return true;
9145}
9146
9148{
9149 // m_gpuBuilt: the commands come from the source buffer from now on, so
9150 // there is nothing to upload, as documented for commitIndirectCommandBuffer().
9151 if (!valid || m_gpuBuilt || m_data.isEmpty() || uploadedGeneration == m_generation)
9152 return;
9153
9154 if (!buffer) {
9155 const quint32 commandSize = m_type == IndexedDraws ? sizeof(QRhiIndexedIndirectDrawCommand)
9156 : sizeof(QRhiIndirectDrawCommand);
9157 buffer = m_rhi->createBuffer(QRhiBuffer::Static, QRhiBuffer::IndirectBuffer,
9158 m_maxCommandCount * commandSize);
9159 if (!buffer || !buffer->create()) {
9160 delete buffer;
9161 buffer = nullptr;
9162 return;
9163 }
9164 }
9165
9166 u->uploadStaticBuffer(buffer, 0, quint32(m_data.size()), m_data.constData());
9167 uploadedGeneration = m_generation;
9168}
9169
9170void QRhiBufferBackedIndirectCommandBuffer::build(const QRhiIndirectCommandBufferBuildInfo &info)
9171{
9172 buildInfo = info;
9173 quint32 count = info.commandCount ? info.commandCount : m_maxCommandCount;
9174 if (count > m_maxCommandCount) {
9175 qWarning("QRhiIndirectCommandBuffer: buildIndirect() with commandCount %u exceeds "
9176 "maxCommandCount %u; clamping", count, m_maxCommandCount);
9177 count = m_maxCommandCount;
9178 }
9179 m_gpuBuilt = true;
9180 m_gpuBuiltCommandCount = count;
9181}
9182
9184 quint32 firstCommand,
9185 quint32 commandCount)
9186{
9187 const bool indexed = m_type == IndexedDraws;
9188 const quint32 canonicalStride = m_type == IndexedDraws ? sizeof(QRhiIndexedIndirectDrawCommand)
9189 : sizeof(QRhiIndirectDrawCommand);
9190
9191 if (m_gpuBuilt) {
9192 const quint32 stride = buildInfo.stride ? buildInfo.stride : canonicalStride;
9193 const quint32 available = m_gpuBuiltCommandCount > firstCommand
9194 ? m_gpuBuiltCommandCount - firstCommand : 0;
9195 const quint32 count = qMin(commandCount, available);
9196 if (!count)
9197 return;
9198 const quint32 offset = buildInfo.sourceBufferOffset + firstCommand * stride;
9199 if (buildInfo.countBuffer) {
9200 // Note that a non-zero firstCommand shifts the window, but the
9201 // device-side count is still relative to the start of that window.
9202 if (indexed) {
9203 cb->drawIndexedIndirectCount(buildInfo.sourceBuffer, offset,
9204 buildInfo.countBuffer, buildInfo.countBufferOffset,
9205 count, stride);
9206 } else {
9207 cb->drawIndirectCount(buildInfo.sourceBuffer, offset,
9208 buildInfo.countBuffer, buildInfo.countBufferOffset,
9209 count, stride);
9210 }
9211 } else {
9212 if (indexed)
9213 cb->drawIndexedIndirect(buildInfo.sourceBuffer, offset, count, stride);
9214 else
9215 cb->drawIndirect(buildInfo.sourceBuffer, offset, count, stride);
9216 }
9217 return;
9218 }
9219
9220 if (!buffer) {
9221 // Metal encodes on the spot in executeIndirect() and so needs no
9222 // commit. Everywhere else a missing one means drawing nothing.
9223 if (m_commandCount) {
9224 qWarning("QRhiIndirectCommandBuffer: %u command(s) recorded but never flushed with "
9225 "QRhiResourceUpdateBatch::commitIndirectCommandBuffer(); nothing to draw",
9226 m_commandCount);
9227 }
9228 return;
9229 }
9230 if (!m_commandCount)
9231 return;
9232
9233 const quint32 available = m_commandCount > firstCommand ? m_commandCount - firstCommand : 0;
9234 const quint32 count = qMin(commandCount, available);
9235 if (!count)
9236 return;
9237
9238 const quint32 offset = firstCommand * canonicalStride;
9239 if (indexed)
9240 cb->drawIndexedIndirect(buffer, offset, count, canonicalStride);
9241 else
9242 cb->drawIndirect(buffer, offset, count, canonicalStride);
9243}
9244
9245QRhiIndirectCommandBuffer *QRhiImplementation::createIndirectCommandBuffer(QRhiIndirectCommandBuffer::Type type,
9246 quint32 maxCommandCount)
9247{
9248 return new QRhiBufferBackedIndirectCommandBuffer(this, type, maxCommandCount);
9249}
9250
9251void QRhiImplementation::buildIndirect(QRhiCommandBuffer *cb, QRhiIndirectCommandBuffer *icb,
9252 const QRhiIndirectCommandBufferBuildInfo &info)
9253{
9254 Q_UNUSED(cb);
9255 static_cast<QRhiBufferBackedIndirectCommandBuffer *>(icb)->build(info);
9256}
9257
9258void QRhiImplementation::executeIndirect(QRhiCommandBuffer *cb, QRhiIndirectCommandBuffer *icb,
9259 quint32 firstCommand, quint32 commandCount)
9260{
9261 static_cast<QRhiBufferBackedIndirectCommandBuffer *>(icb)->execute(cb, firstCommand, commandCount);
9262}
9263
9264void QRhiImplementation::commitIndirectCommandBuffer(QRhiResourceUpdateBatch *u,
9265 QRhiIndirectCommandBuffer *icb)
9266{
9267 static_cast<QRhiBufferBackedIndirectCommandBuffer *>(icb)->enqueueUpload(u);
9268}
9269
9270/*!
9271 \class QRhiCommandBuffer
9272 \inmodule QtGuiPrivate
9273 \inheaderfile rhi/qrhi.h
9274 \since 6.6
9275 \brief Command buffer resource.
9276
9277 Not creatable by applications at the moment. The only ways to obtain a
9278 valid QRhiCommandBuffer are to get it from the targeted swapchain via
9279 QRhiSwapChain::currentFrameCommandBuffer(), or, in case of rendering
9280 completely offscreen, initializing one via QRhi::beginOffscreenFrame().
9281
9282 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9283 for details.
9284 */
9285
9286/*!
9287 \enum QRhiCommandBuffer::IndexFormat
9288 Specifies the index data type
9289
9290 \value IndexUInt16 Unsigned 16-bit (quint16)
9291 \value IndexUInt32 Unsigned 32-bit (quint32)
9292 */
9293
9294/*!
9295 \enum QRhiCommandBuffer::BeginPassFlag
9296 Flag values for QRhi::beginPass()
9297
9298 \value ExternalContent Specifies that there will be a call to
9299 QRhiCommandBuffer::beginExternal() in this pass. Some backends, Vulkan in
9300 particular, will fail if this flag is not set and beginExternal() is still
9301 called.
9302
9303 \value DoNotTrackResourcesForCompute Specifies that there is no need to
9304 track resources used in this pass if the only purpose of such tracking is
9305 to generate barriers for compute. Implies that there are no compute passes
9306 in the frame. This is an optimization hint that may be taken into account
9307 by certain backends, OpenGL in particular, allowing them to skip certain
9308 operations. When this flag is set for a render pass in a frame, calling
9309 \l{QRhiCommandBuffer::beginComputePass()}{beginComputePass()} in that frame
9310 may lead to unexpected behavior, depending on the resource dependencies
9311 between the render and compute passes.
9312 */
9313
9314/*!
9315 \typedef QRhiCommandBuffer::DynamicOffset
9316
9317 Synonym for std::pair<int, quint32>. The first entry is the binding, the second
9318 is the offset in the buffer.
9319*/
9320
9321/*!
9322 \typedef QRhiCommandBuffer::VertexInput
9323
9324 Synonym for std::pair<QRhiBuffer *, quint32>. The second entry is an offset in
9325 the buffer specified by the first.
9326*/
9327
9328/*!
9329 \internal
9330 */
9331QRhiCommandBuffer::QRhiCommandBuffer(QRhiImplementation *rhi)
9332 : QRhiResource(rhi)
9333{
9334}
9335
9336/*!
9337 \return the resource type.
9338 */
9339QRhiResource::Type QRhiCommandBuffer::resourceType() const
9340{
9341 return CommandBuffer;
9342}
9343
9344static const char *resourceTypeStr(const QRhiResource *res)
9345{
9346 switch (res->resourceType()) {
9347 case QRhiResource::Buffer:
9348 return "Buffer";
9349 case QRhiResource::Texture:
9350 return "Texture";
9351 case QRhiResource::Sampler:
9352 return "Sampler";
9353 case QRhiResource::RenderBuffer:
9354 return "RenderBuffer";
9355 case QRhiResource::RenderPassDescriptor:
9356 return "RenderPassDescriptor";
9357 case QRhiResource::SwapChainRenderTarget:
9358 return "SwapChainRenderTarget";
9359 case QRhiResource::TextureRenderTarget:
9360 return "TextureRenderTarget";
9361 case QRhiResource::ShaderResourceBindings:
9362 return "ShaderResourceBindings";
9363 case QRhiResource::GraphicsPipeline:
9364 return "GraphicsPipeline";
9365 case QRhiResource::SwapChain:
9366 return "SwapChain";
9367 case QRhiResource::ComputePipeline:
9368 return "ComputePipeline";
9369 case QRhiResource::CommandBuffer:
9370 return "CommandBuffer";
9371 case QRhiResource::ShadingRateMap:
9372 return "ShadingRateMap";
9373 case QRhiResource::IndirectCommandBuffer:
9374 return "IndirectCommandBuffer";
9375 }
9376
9377 Q_UNREACHABLE_RETURN("");
9378}
9379
9380QRhiImplementation::~QRhiImplementation()
9381{
9382 qDeleteAll(resUpdPool);
9383
9384 // Be nice and show something about leaked stuff. Though we may not get
9385 // this far with some backends where the allocator or the api may check
9386 // and freak out for unfreed graphics objects in the derived dtor already.
9387#ifndef QT_NO_DEBUG
9388 // debug builds: just do it always
9389 static bool leakCheck = true;
9390#else
9391 // release builds: opt-in
9392 static bool leakCheck = qEnvironmentVariableIntValue("QT_RHI_LEAK_CHECK");
9393#endif
9394 if (!resources.isEmpty()) {
9395 if (leakCheck) {
9396 qWarning("QRhi %p going down with %d unreleased resources that own native graphics objects. This is not nice.",
9397 q, int(resources.size()));
9398 }
9399 for (auto it = resources.cbegin(), end = resources.cend(); it != end; ++it) {
9400 QRhiResource *res = it.key();
9401 const bool ownsNativeResources = it.value();
9402 if (leakCheck && ownsNativeResources)
9403 qWarning(" %s resource %p (%s)", resourceTypeStr(res), res, res->m_objectName.constData());
9404
9405 // Null out the resource's rhi pointer. This is why it makes sense to do null
9406 // checks in the destroy() implementations of the various resource types. It
9407 // allows to survive in bad applications that somehow manage to destroy a
9408 // resource of a QRhi after the QRhi itself.
9409 res->m_rhi = nullptr;
9410 }
9411 }
9412}
9413
9414bool QRhiImplementation::isCompressedFormat(QRhiTexture::Format format) const
9415{
9416 return (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
9417 || (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
9418 || (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12);
9419}
9420
9421bool QRhiImplementation::compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
9422 quint32 *bpl, quint32 *byteSize,
9423 QSize *blockDim) const
9424{
9425 int xdim = 4;
9426 int ydim = 4;
9427 quint32 blockSize = 0;
9428
9429 switch (format) {
9430 case QRhiTexture::BC1:
9431 blockSize = 8;
9432 break;
9433 case QRhiTexture::BC2:
9434 blockSize = 16;
9435 break;
9436 case QRhiTexture::BC3:
9437 blockSize = 16;
9438 break;
9439 case QRhiTexture::BC4:
9440 blockSize = 8;
9441 break;
9442 case QRhiTexture::BC5:
9443 blockSize = 16;
9444 break;
9445 case QRhiTexture::BC6H:
9446 blockSize = 16;
9447 break;
9448 case QRhiTexture::BC7:
9449 blockSize = 16;
9450 break;
9451
9452 case QRhiTexture::ETC2_RGB8:
9453 blockSize = 8;
9454 break;
9455 case QRhiTexture::ETC2_RGB8A1:
9456 blockSize = 8;
9457 break;
9458 case QRhiTexture::ETC2_RGBA8:
9459 blockSize = 16;
9460 break;
9461
9462 case QRhiTexture::ASTC_4x4:
9463 blockSize = 16;
9464 break;
9465 case QRhiTexture::ASTC_5x4:
9466 blockSize = 16;
9467 xdim = 5;
9468 break;
9469 case QRhiTexture::ASTC_5x5:
9470 blockSize = 16;
9471 xdim = ydim = 5;
9472 break;
9473 case QRhiTexture::ASTC_6x5:
9474 blockSize = 16;
9475 xdim = 6;
9476 ydim = 5;
9477 break;
9478 case QRhiTexture::ASTC_6x6:
9479 blockSize = 16;
9480 xdim = ydim = 6;
9481 break;
9482 case QRhiTexture::ASTC_8x5:
9483 blockSize = 16;
9484 xdim = 8;
9485 ydim = 5;
9486 break;
9487 case QRhiTexture::ASTC_8x6:
9488 blockSize = 16;
9489 xdim = 8;
9490 ydim = 6;
9491 break;
9492 case QRhiTexture::ASTC_8x8:
9493 blockSize = 16;
9494 xdim = ydim = 8;
9495 break;
9496 case QRhiTexture::ASTC_10x5:
9497 blockSize = 16;
9498 xdim = 10;
9499 ydim = 5;
9500 break;
9501 case QRhiTexture::ASTC_10x6:
9502 blockSize = 16;
9503 xdim = 10;
9504 ydim = 6;
9505 break;
9506 case QRhiTexture::ASTC_10x8:
9507 blockSize = 16;
9508 xdim = 10;
9509 ydim = 8;
9510 break;
9511 case QRhiTexture::ASTC_10x10:
9512 blockSize = 16;
9513 xdim = ydim = 10;
9514 break;
9515 case QRhiTexture::ASTC_12x10:
9516 blockSize = 16;
9517 xdim = 12;
9518 ydim = 10;
9519 break;
9520 case QRhiTexture::ASTC_12x12:
9521 blockSize = 16;
9522 xdim = ydim = 12;
9523 break;
9524
9525 default:
9526 Q_UNREACHABLE();
9527 break;
9528 }
9529
9530 const quint32 wblocks = quint32((qint64(qMax(0, size.width())) + xdim - 1) / xdim);
9531 const quint32 hblocks = quint32((qint64(qMax(0, size.height())) + ydim - 1) / ydim);
9532
9533 if (blockDim)
9534 *blockDim = QSize(xdim, ydim);
9535
9536 // Compute in 64-bit, as safety for extreme geometry that would not fit.
9537 // wblocks and hblocks are at most 2^29 and blockSize at most 16.
9538 const quint64 bytesPerLine = quint64(wblocks) * quint64(blockSize);
9539 const quint64 totalSize = quint64(wblocks) * quint64(hblocks) * quint64(blockSize);
9540 if (bytesPerLine > std::numeric_limits<quint32>::max()
9541 || totalSize > std::numeric_limits<quint32>::max())
9542 {
9543 qWarning("Compressed texture of size %dx%d with format %d has a byte size of %llu "
9544 "which is too large to be handled",
9545 size.width(), size.height(), int(format), totalSize);
9546 if (bpl)
9547 *bpl = 0;
9548 if (byteSize)
9549 *byteSize = 0;
9550 return false;
9551 }
9552
9553 if (bpl)
9554 *bpl = quint32(bytesPerLine);
9555 if (byteSize)
9556 *byteSize = quint32(totalSize);
9557
9558 return true;
9559}
9560
9561bool QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSize &size,
9562 quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const
9563{
9564 if (isCompressedFormat(format))
9565 return compressedFormatInfo(format, size, bpl, byteSize, nullptr);
9566
9567 quint32 bpc = 0;
9568 switch (format) {
9569 case QRhiTexture::RGBA8:
9570 bpc = 4;
9571 break;
9572 case QRhiTexture::BGRA8:
9573 bpc = 4;
9574 break;
9575 case QRhiTexture::R8:
9576 bpc = 1;
9577 break;
9578 case QRhiTexture::RG8:
9579 bpc = 2;
9580 break;
9581 case QRhiTexture::R16:
9582 bpc = 2;
9583 break;
9584 case QRhiTexture::RG16:
9585 bpc = 4;
9586 break;
9587 case QRhiTexture::RED_OR_ALPHA8:
9588 bpc = 1;
9589 break;
9590
9591 case QRhiTexture::RGBA16F:
9592 bpc = 8;
9593 break;
9594 case QRhiTexture::RGBA32F:
9595 bpc = 16;
9596 break;
9597 case QRhiTexture::R16F:
9598 bpc = 2;
9599 break;
9600 case QRhiTexture::R32F:
9601 bpc = 4;
9602 break;
9603
9604 case QRhiTexture::RGB10A2:
9605 bpc = 4;
9606 break;
9607
9608 case QRhiTexture::D16:
9609 bpc = 2;
9610 break;
9611 case QRhiTexture::D24:
9612 case QRhiTexture::D24S8:
9613 case QRhiTexture::D32F:
9614 bpc = 4;
9615 break;
9616
9617 case QRhiTexture::D32FS8:
9618 bpc = 8;
9619 break;
9620
9621 case QRhiTexture::R8SI:
9622 case QRhiTexture::R8UI:
9623 bpc = 1;
9624 break;
9625 case QRhiTexture::R32SI:
9626 case QRhiTexture::R32UI:
9627 bpc = 4;
9628 break;
9629 case QRhiTexture::RG32SI:
9630 case QRhiTexture::RG32UI:
9631 bpc = 8;
9632 break;
9633 case QRhiTexture::RGBA32SI:
9634 case QRhiTexture::RGBA32UI:
9635 bpc = 16;
9636 break;
9637
9638 default:
9639 Q_UNREACHABLE();
9640 break;
9641 }
9642
9643 const quint32 width = uint(qMax(0, size.width()));
9644 const quint32 height = uint(qMax(0, size.height()));
9645
9646 if (bytesPerPixel)
9647 *bytesPerPixel = bpc;
9648
9649 // Compute in 64-bit, as safety for extreme geometry that would not fit.
9650 const quint64 bytesPerLine = quint64(width) * quint64(bpc);
9651 const quint64 pixelCount = quint64(width) * quint64(height);
9652 if (bytesPerLine > std::numeric_limits<quint32>::max()
9653 || pixelCount > std::numeric_limits<quint32>::max() / bpc)
9654 {
9655 qWarning("Texture of size %dx%d with format %d has a byte size "
9656 "which is too large to be handled",
9657 size.width(), size.height(), int(format));
9658 if (bpl)
9659 *bpl = 0;
9660 if (byteSize)
9661 *byteSize = 0;
9662 return false;
9663 }
9664
9665 if (bpl)
9666 *bpl = quint32(bytesPerLine);
9667 if (byteSize)
9668 *byteSize = quint32(pixelCount * quint64(bpc));
9669
9670 return true;
9671}
9672
9673bool QRhiImplementation::isStencilSupportingFormat(QRhiTexture::Format format) const
9674{
9675 switch (format) {
9676 case QRhiTexture::D24S8:
9677 case QRhiTexture::D32FS8:
9678 return true;
9679 default:
9680 break;
9681 }
9682 return false;
9683}
9684
9685bool QRhiImplementation::sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps)
9686{
9687 if (ps->cbeginShaderStages() == ps->cendShaderStages()) {
9688 qWarning("Cannot build a graphics pipeline without any stages");
9689 return false;
9690 }
9691
9692 bool hasVertexStage = false;
9693 for (auto it = ps->cbeginShaderStages(), itEnd = ps->cendShaderStages(); it != itEnd; ++it) {
9694 if (!it->shader().isValid()) {
9695 qWarning("Empty shader passed to graphics pipeline");
9696 return false;
9697 }
9698 if (it->type() == QRhiShaderStage::Vertex)
9699 hasVertexStage = true;
9700 }
9701 if (!hasVertexStage) {
9702 qWarning("Cannot build a graphics pipeline without a vertex stage");
9703 return false;
9704 }
9705
9706 if (!ps->renderPassDescriptor()) {
9707 qWarning("Cannot build a graphics pipeline without a QRhiRenderPassDescriptor");
9708 return false;
9709 }
9710
9711 if (!ps->shaderResourceBindings()) {
9712 qWarning("Cannot build a graphics pipeline without QRhiShaderResourceBindings");
9713 return false;
9714 }
9715
9716 return true;
9717}
9718
9719bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb)
9720{
9721#ifndef QT_NO_DEBUG
9722 bool bindingsOk = true;
9723 const int CHECKED_BINDINGS_COUNT = 64;
9724 bool bindingSeen[CHECKED_BINDINGS_COUNT] = {};
9725 for (auto it = srb->cbeginBindings(), end = srb->cendBindings(); it != end; ++it) {
9726 const int binding = shaderResourceBindingData(*it)->binding;
9727 if (binding >= CHECKED_BINDINGS_COUNT)
9728 continue;
9729 if (binding < 0) {
9730 qWarning("Invalid binding number %d", binding);
9731 bindingsOk = false;
9732 continue;
9733 }
9734 switch (shaderResourceBindingData(*it)->type) {
9735 case QRhiShaderResourceBinding::UniformBuffer:
9736 if (!bindingSeen[binding]) {
9737 bindingSeen[binding] = true;
9738 } else {
9739 qWarning("Uniform buffer duplicates an existing binding number %d", binding);
9740 bindingsOk = false;
9741 }
9742 break;
9743 case QRhiShaderResourceBinding::SampledTexture:
9744 if (!bindingSeen[binding]) {
9745 bindingSeen[binding] = true;
9746 } else {
9747 qWarning("Combined image sampler duplicates an existing binding number %d", binding);
9748 bindingsOk = false;
9749 }
9750 break;
9751 case QRhiShaderResourceBinding::Texture:
9752 if (!bindingSeen[binding]) {
9753 bindingSeen[binding] = true;
9754 } else {
9755 qWarning("Texture duplicates an existing binding number %d", binding);
9756 bindingsOk = false;
9757 }
9758 break;
9759 case QRhiShaderResourceBinding::Sampler:
9760 if (!bindingSeen[binding]) {
9761 bindingSeen[binding] = true;
9762 } else {
9763 qWarning("Sampler duplicates an existing binding number %d", binding);
9764 bindingsOk = false;
9765 }
9766 break;
9767 case QRhiShaderResourceBinding::ImageLoad:
9768 case QRhiShaderResourceBinding::ImageStore:
9769 case QRhiShaderResourceBinding::ImageLoadStore:
9770 if (!bindingSeen[binding]) {
9771 bindingSeen[binding] = true;
9772 } else {
9773 qWarning("Image duplicates an existing binding number %d", binding);
9774 bindingsOk = false;
9775 }
9776 break;
9777 case QRhiShaderResourceBinding::BufferLoad:
9778 case QRhiShaderResourceBinding::BufferStore:
9779 case QRhiShaderResourceBinding::BufferLoadStore:
9780 if (!bindingSeen[binding]) {
9781 bindingSeen[binding] = true;
9782 } else {
9783 qWarning("Buffer duplicates an existing binding number %d", binding);
9784 bindingsOk = false;
9785 }
9786 break;
9787 default:
9788 qWarning("Unknown binding type %d", int(shaderResourceBindingData(*it)->type));
9789 bindingsOk = false;
9790 break;
9791 }
9792 }
9793
9794 if (!bindingsOk) {
9795 qWarning() << *srb;
9796 return false;
9797 }
9798#else
9799 Q_UNUSED(srb);
9800#endif
9801 return true;
9802}
9803
9804bool QRhiImplementation::sanityCheckResourceOwnership(QRhiResource *maybeResource)
9805{
9806 if (maybeResource == nullptr || maybeResource->m_rhi == nullptr)
9807 return true;
9808
9809 if (maybeResource->m_rhi->q != q) {
9810 qWarning("%s %p (%s) belongs to QRhi %p, but client code attempted to use it with QRhi %p. This is wrong.",
9811 resourceTypeStr(maybeResource),
9812 maybeResource,
9813 maybeResource->m_objectName.constData(),
9814 maybeResource->m_rhi->q,
9815 q);
9816 return false;
9817 }
9818
9819 return true;
9820}
9821
9822int QRhiImplementation::effectiveSampleCount(int sampleCount) const
9823{
9824 // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
9825 const int s = qBound(1, sampleCount, 64);
9826 const QList<int> supported = supportedSampleCounts();
9827 int result = 1;
9828
9829 // Stay compatible with Qt 5 in that requesting an unsupported sample count
9830 // is not an error (although we still do a categorized debug print about
9831 // this), and rather a supported value, preferably a close one, not just 1,
9832 // is used instead. This is actually deviating from Qt 5 as that performs a
9833 // clamping only and does not handle cases such as when sample count 2 is
9834 // not supported but 4 is. (OpenGL handles things like that gracefully,
9835 // other APIs may not, so improve this by picking the next largest, or in
9836 // absence of that, the largest value; this with the goal to not reduce
9837 // quality by rather picking a larger-than-requested value than a smaller one)
9838
9839 for (int i = 0, ie = supported.count(); i != ie; ++i) {
9840 // assumes the 'supported' list is sorted
9841 if (supported[i] >= s) {
9842 result = supported[i];
9843 break;
9844 }
9845 }
9846
9847 if (result != s) {
9848 if (result == 1 && !supported.isEmpty())
9849 result = supported.last();
9850 qCDebug(QRHI_LOG_INFO, "Attempted to set unsupported sample count %d, using %d instead",
9851 sampleCount, result);
9852 }
9853
9854 return result;
9855}
9856
9857/*!
9858 \internal
9859 */
9860QRhi::QRhi()
9861{
9862}
9863
9864/*!
9865 Destructor. Destroys the backend and releases resources.
9866 */
9867QRhi::~QRhi()
9868{
9869 if (!d)
9870 return;
9871
9872 d->runCleanup();
9873
9874 qDeleteAll(d->pendingDeleteResources);
9875 d->pendingDeleteResources.clear();
9876
9877 d->destroy();
9878 delete d;
9879}
9880
9881QRhiImplementation *QRhiImplementation::newInstance(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *importDevice)
9882{
9883 QRhiImplementation *d = nullptr;
9884
9885 switch (impl) {
9886 case QRhi::Null:
9887 d = new QRhiNull(static_cast<QRhiNullInitParams *>(params));
9888 break;
9889 case QRhi::Vulkan:
9890#if QT_CONFIG(vulkan)
9891 d = new QRhiVulkan(static_cast<QRhiVulkanInitParams *>(params),
9892 static_cast<QRhiVulkanNativeHandles *>(importDevice));
9893 break;
9894#else
9895 Q_UNUSED(importDevice);
9896 qWarning("This build of Qt has no Vulkan support");
9897 break;
9898#endif
9899 case QRhi::OpenGLES2:
9900#ifndef QT_NO_OPENGL
9901 d = new QRhiGles2(static_cast<QRhiGles2InitParams *>(params),
9902 static_cast<QRhiGles2NativeHandles *>(importDevice));
9903 break;
9904#else
9905 qWarning("This build of Qt has no OpenGL support");
9906 break;
9907#endif
9908 case QRhi::D3D11:
9909#ifdef Q_OS_WIN
9910 d = new QRhiD3D11(static_cast<QRhiD3D11InitParams *>(params),
9911 static_cast<QRhiD3D11NativeHandles *>(importDevice));
9912 break;
9913#else
9914 qWarning("This platform has no Direct3D 11 support");
9915 break;
9916#endif
9917 case QRhi::Metal:
9918#if QT_CONFIG(metal)
9919 d = new QRhiMetal(static_cast<QRhiMetalInitParams *>(params),
9920 static_cast<QRhiMetalNativeHandles *>(importDevice));
9921 break;
9922#else
9923 qWarning("This platform has no Metal support");
9924 break;
9925#endif
9926 case QRhi::D3D12:
9927#ifdef Q_OS_WIN
9928#ifdef QRHI_D3D12_AVAILABLE
9929 d = new QRhiD3D12(static_cast<QRhiD3D12InitParams *>(params),
9930 static_cast<QRhiD3D12NativeHandles *>(importDevice));
9931 break;
9932#else
9933 qWarning("Qt was built without Direct3D 12 support. "
9934 "This is likely due to having ancient SDK headers (such as d3d12.h) in the Qt build environment. "
9935 "Rebuild Qt with an SDK supporting D3D12 features introduced in Windows 10 version 1703, "
9936 "or use an MSVC build as those typically are built with more up-to-date SDKs.");
9937 break;
9938#endif
9939#else
9940 qWarning("This platform has no Direct3D 12 support");
9941 break;
9942#endif
9943 }
9944
9945 return d;
9946}
9947
9948void QRhiImplementation::prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags, QRhiAdapter *adapter)
9949{
9950 q = rhi;
9951
9952 debugMarkers = flags.testFlag(QRhi::EnableDebugMarkers);
9953
9954 implType = impl;
9955 implThread = QThread::currentThread();
9956
9957 requestedRhiAdapter = adapter;
9958}
9959
9960QRhi::AdapterList QRhiImplementation::enumerateAdaptersBeforeCreate(QRhiNativeHandles *) const
9961{
9962 return {};
9963}
9964
9965/*!
9966 \overload
9967
9968 Equivalent to create(\a impl, \a params, \a flags, \a importDevice, \c nullptr).
9969 */
9970QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice)
9971{
9972 return create(impl, params, flags, importDevice, nullptr);
9973}
9974
9975/*!
9976 \return a new QRhi instance with a backend for the graphics API specified
9977 by \a impl with the specified \a flags. \return \c nullptr if the
9978 function fails.
9979
9980 \a params must point to an instance of one of the backend-specific
9981 subclasses of QRhiInitParams, such as, QRhiVulkanInitParams,
9982 QRhiMetalInitParams, QRhiD3D11InitParams, QRhiD3D12InitParams,
9983 QRhiGles2InitParams. See these classes for examples on creating a QRhi.
9984
9985 QRhi by design does not implement any fallback logic: if the specified API
9986 cannot be initialized, create() will fail, with warnings printed on the
9987 debug output by the backends. The clients of QRhi, for example Qt Quick,
9988 may however provide additional logic that allow falling back to an API
9989 different than what was requested, depending on the platform. If the
9990 intention is just to test if initialization would succeed when calling
9991 create() at later point, it is preferable to use probe() instead of
9992 create(), because with some backends probing can be implemented in a more
9993 lightweight manner as opposed to create(), which performs full
9994 initialization of the infrastructure and is wasteful if that QRhi instance
9995 is then thrown immediately away.
9996
9997 \a importDevice allows using an already existing graphics device, without
9998 QRhi creating its own. When not null, this parameter must point to an
9999 instance of one of the subclasses of QRhiNativeHandles:
10000 QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles,
10001 QRhiMetalNativeHandles, QRhiGles2NativeHandles. The exact details and
10002 semantics depend on the backand and the underlying graphics API.
10003
10004 Specifying a QRhiAdapter in \a adapter offers a transparent, cross-API
10005 alternative to passing in a \c VkPhysicalDevice via QRhiVulkanNativeHandles,
10006 or an adapter LUID via QRhiD3D12NativeHandles. The ownership of \a adapter
10007 is not taken. See enumerateAdapters() for more information on this approach.
10008
10009 \note \a importDevice and \a adapter cannot be both specified.
10010
10011 \sa probe()
10012 */
10013QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice, QRhiAdapter *adapter)
10014{
10015 if (adapter && importDevice)
10016 qWarning("adapter and importDevice should not both be non-null in QRhi::create()");
10017
10018 std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, importDevice));
10019 if (!rd)
10020 return nullptr;
10021
10022 std::unique_ptr<QRhi> r(new QRhi);
10023 r->d = rd.release();
10024 r->d->prepareForCreate(r.get(), impl, flags, adapter);
10025 if (!r->d->create(flags))
10026 return nullptr;
10027
10028 return r.release();
10029}
10030
10031/*!
10032 \return true if create() can be expected to succeed when called the given
10033 \a impl and \a params.
10034
10035 For some backends this is equivalent to calling create(), checking its
10036 return value, and then destroying the resulting QRhi.
10037
10038 For others, in particular with Metal, there may be a specific probing
10039 implementation, which allows testing in a more lightweight manner without
10040 polluting the debug output with warnings upon failures.
10041
10042 \sa create()
10043 */
10044bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)
10045{
10046 bool ok = false;
10047
10048 // The only place currently where this makes sense is Metal, where the API
10049 // is simple enough so that a special probing function - doing nothing but
10050 // a MTLCreateSystemDefaultDevice - is reasonable. Elsewhere, just call
10051 // create() and then drop the result.
10052
10053 if (impl == Metal) {
10054#if QT_CONFIG(metal)
10055 ok = QRhiMetal::probe(static_cast<QRhiMetalInitParams *>(params));
10056#endif
10057 } else {
10058 QRhi *rhi = create(impl, params);
10059 ok = rhi != nullptr;
10060 delete rhi;
10061 }
10062 return ok;
10063}
10064
10065/*!
10066 \typedef QRhi::AdapterList
10067 \relates QRhi
10068 \since 6.10
10069
10070 Synonym for QVector<QRhiAdapter *>.
10071*/
10072
10073/*!
10074 \return the list of adapters (physical devices) present, or an empty list
10075 when such control is not available with a given graphics API.
10076
10077 Backends where such level of control is not available, the returned list is
10078 always empty. Thus an empty list does not indicate there are no graphics
10079 devices in the system, but that fine-grained control over selecting which
10080 one to use is not available.
10081
10082 Backends for Direct 3D 11, Direct 3D 12, and Vulkan can be expected to fully
10083 support enumerating adapters. Others may not. The backend is specified by \a
10084 impl. A QRhiAdapter returned from this function must only be used in a
10085 create() call with the same \a impl. Some underlying APIs may present
10086 further limitations, with Vulkan in particular the QRhiAdapter is specified
10087 to the QVulkanInstance (\c VkInstance).
10088
10089 The caller is expected to destroy the QRhiAdapter objects in the list. Apart
10090 from querying \l{QRhiAdapter::}{info()}, the only purpose of these objects is
10091 to be passed on to create(), or the corresponding functions in higher layers
10092 such as Qt Quick.
10093
10094 The following snippet, written specifically for Vulkan, shows how to
10095 enumerate the available physical devices and request to create a QRhi for
10096 the chosen one. This in practice is equivalent to passing in a \c
10097 VkPhysicalDevice via a QRhiVulkanNativeHandles to create(), but it involves
10098 less API-specific code on the application side:
10099
10100 \code
10101 QRhiVulkanInitParams initParams;
10102 initParams.inst = &vulkanInstance;
10103 QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::Vulkan, &initParams);
10104 QRhiAdapter *chosenAdapter = nullptr;
10105 for (QRhiAdapter *adapter : adapters) {
10106 if (looksGood(adapter->info())) {
10107 chosenAdapter = adapter;
10108 break;
10109 }
10110 }
10111 QRhi *rhi = QRhi::create(QRhi::Vulkan, &initParams, {}, nullptr, chosenAdapter);
10112 qDeleteAll(adapters);
10113 \endcode
10114
10115 Passing in \a params is required due to some of the underlying graphics
10116 APIs' design. With Vulkan in particular, the QVulkanInstance must be
10117 provided, since enumerating is not possible without it. Other fields in the
10118 backend-specific \a params will not actually be used by this function.
10119
10120 \a nativeHandles is optional. When specified, it must be a valid
10121 QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, or QRhiVulkanNativeHandles,
10122 similarly to create(). However, unlike create(), only the physical device
10123 (in case of Vulkan) or the adapter LUID (in case of D3D) fields are used,
10124 all other fields are ignored. This can be used the restrict the results to a
10125 given adapter. The returned list will contain 1 or 0 elements in this case.
10126
10127 Note how in the previous code snippet the looksGood() function
10128 implementation cannot perform any platform-specific filtering based on the
10129 true adapter / physical device identity, such as the adapter LUID on Windows
10130 or the VkPhysicalDevice with Vulkan. This is because QRhiDriverInfo does not
10131 contain platform-specific data. Instead, use \a nativeHandles to get the
10132 results filtered already inside enumerateAdapters().
10133
10134 The following two snippets, using Direct 3D 12 as an example, are equivalent
10135 in practice:
10136
10137 \code
10138 // enumerateAdapters-based approach from Qt 6.10 on
10139 QRhiD3D12InitParams initParams;
10140 QRhiD3D12NativeHandles nativeHandles;
10141 nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
10142 nativeHandles.adapterLuidHigh = luid.HighPart;
10143 QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::D3D12, &initParams, &nativeHandles);
10144 if (adapters.isEmpty()) { qWarning("Requested adapter was not found"); }
10145 QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, nullptr, adapters[0]);
10146 qDeleteAll(adapters);
10147 \endcode
10148
10149 \code
10150 // traditional approach, more lightweight
10151 QRhiD3D12InitParams initParams;
10152 QRhiD3D12NativeHandles nativeHandles;
10153 nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
10154 nativeHandles.adapterLuidHigh = luid.HighPart;
10155 QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, &nativeHandles, nullptr);
10156 \endcode
10157
10158 \since 6.10
10159 \sa create()
10160 */
10161QRhi::AdapterList QRhi::enumerateAdapters(Implementation impl, QRhiInitParams *params, QRhiNativeHandles *nativeHandles)
10162{
10163 std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, nullptr));
10164 if (!rd)
10165 return {};
10166
10167 return rd->enumerateAdaptersBeforeCreate(nativeHandles);
10168}
10169
10170/*!
10171 \struct QRhiSwapChainProxyData
10172 \inmodule QtGuiPrivate
10173 \inheaderfile rhi/qrhi.h
10174 \since 6.6
10175
10176 \brief Opaque data describing native objects needed to set up a swapchain.
10177
10178 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10179 for details.
10180
10181 \sa QRhi::updateSwapChainProxyData()
10182 */
10183
10184/*!
10185 Generates and returns a QRhiSwapChainProxyData struct containing opaque
10186 data specific to the backend and graphics API specified by \a impl. \a
10187 window is the QWindow a swapchain is targeting.
10188
10189 The returned struct can be passed to QRhiSwapChain::setProxyData(). This
10190 makes sense in threaded rendering systems: this static function is expected
10191 to be called on the \b{main (gui) thread}, unlike all QRhi operations, then
10192 transferred to the thread working with the QRhi and QRhiSwapChain and passed
10193 on to the swapchain. This allows doing native platform queries that are
10194 only safe to be called on the main thread, for example to query the
10195 CAMetalLayer from a NSView, and then passing on the data to the
10196 QRhiSwapChain living on the rendering thread. With the Metal example, doing
10197 the view.layer access on a dedicated rendering thread causes a warning in
10198 the Xcode Thread Checker. With the data proxy mechanism, this is avoided.
10199
10200 When threads are not involved, generating and passing on the
10201 QRhiSwapChainProxyData is not required: backends are guaranteed to be able
10202 to query whatever is needed on their own, and if everything lives on the
10203 main (gui) thread, that should be sufficient.
10204
10205 \note \a impl should match what the QRhi is created with. For example,
10206 calling with QRhi::Metal on a non-Apple platform will not generate any
10207 useful data.
10208 */
10209QRhiSwapChainProxyData QRhi::updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)
10210{
10211#if QT_CONFIG(metal)
10212 if (impl == Metal)
10213 return QRhiMetal::updateSwapChainProxyData(window);
10214#else
10215 Q_UNUSED(impl);
10216 Q_UNUSED(window);
10217#endif
10218 return {};
10219}
10220
10221/*!
10222 \return the backend type for this QRhi.
10223 */
10224QRhi::Implementation QRhi::backend() const
10225{
10226 return d->implType;
10227}
10228
10229/*!
10230 \return a friendly name for the backend \a impl, usually the name of the 3D
10231 API in use.
10232 */
10233const char *QRhi::backendName(Implementation impl)
10234{
10235 switch (impl) {
10236 case QRhi::Null:
10237 return "Null";
10238 case QRhi::Vulkan:
10239 return "Vulkan";
10240 case QRhi::OpenGLES2:
10241 return "OpenGL";
10242 case QRhi::D3D11:
10243 return "D3D11";
10244 case QRhi::Metal:
10245 return "Metal";
10246 case QRhi::D3D12:
10247 return "D3D12";
10248 }
10249
10250 Q_UNREACHABLE_RETURN("Unknown");
10251}
10252
10253/*!
10254 \return the backend type as string for this QRhi.
10255 */
10256const char *QRhi::backendName() const
10257{
10258 return backendName(d->implType);
10259}
10260
10261/*!
10262 \enum QRhiDriverInfo::DeviceType
10263 Specifies the graphics device's type, when the information is available.
10264
10265 In practice this is only applicable with Vulkan and Metal. With Direct 3D
10266 11 and 12, using an adapter with the software flag set leads to the value
10267 \c CpuDevice. Otherwise, and with OpenGL, the value is always UnknownDevice.
10268
10269 \value UnknownDevice
10270 \value IntegratedDevice
10271 \value DiscreteDevice
10272 \value ExternalDevice
10273 \value VirtualDevice
10274 \value CpuDevice
10275*/
10276
10277/*!
10278 \struct QRhiDriverInfo
10279 \inmodule QtGuiPrivate
10280 \inheaderfile rhi/qrhi.h
10281 \since 6.6
10282
10283 \brief Describes the physical device, adapter, or graphics API
10284 implementation that is used by an initialized QRhi.
10285
10286 Graphics APIs offer different levels and kinds of information. The only
10287 value that is available across all APIs is the deviceName, which is a
10288 freetext description of the physical device, adapter, or is a combination
10289 of the strings reported for \c{GL_VENDOR} + \c{GL_RENDERER} +
10290 \c{GL_VERSION}. The deviceId is always 0 for OpenGL. vendorId is always 0
10291 for OpenGL and Metal. deviceType is always UnknownDevice for OpenGL and
10292 Direct 3D.
10293
10294 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10295 for details.
10296 */
10297
10298/*!
10299 \variable QRhiDriverInfo::deviceName
10300
10301 \sa QRhi::driverInfo()
10302*/
10303
10304/*!
10305 \variable QRhiDriverInfo::deviceId
10306
10307 \sa QRhi::driverInfo()
10308*/
10309
10310/*!
10311 \variable QRhiDriverInfo::vendorId
10312
10313 \sa QRhi::driverInfo()
10314*/
10315
10316/*!
10317 \variable QRhiDriverInfo::deviceType
10318
10319 \sa QRhi::driverInfo(), QRhiDriverInfo::DeviceType
10320*/
10321
10322#ifndef QT_NO_DEBUG_STREAM
10323static inline const char *deviceTypeStr(QRhiDriverInfo::DeviceType type)
10324{
10325 switch (type) {
10326 case QRhiDriverInfo::UnknownDevice:
10327 return "Unknown";
10328 case QRhiDriverInfo::IntegratedDevice:
10329 return "Integrated";
10330 case QRhiDriverInfo::DiscreteDevice:
10331 return "Discrete";
10332 case QRhiDriverInfo::ExternalDevice:
10333 return "External";
10334 case QRhiDriverInfo::VirtualDevice:
10335 return "Virtual";
10336 case QRhiDriverInfo::CpuDevice:
10337 return "Cpu";
10338 }
10339
10340 Q_UNREACHABLE_RETURN(nullptr);
10341}
10342QDebug operator<<(QDebug dbg, const QRhiDriverInfo &info)
10343{
10344 QDebugStateSaver saver(dbg);
10345 dbg.nospace() << "QRhiDriverInfo(deviceName=" << info.deviceName
10346 << " deviceId=0x" << Qt::hex << info.deviceId
10347 << " vendorId=0x" << info.vendorId
10348 << " deviceType=" << deviceTypeStr(info.deviceType)
10349 << ')';
10350 return dbg;
10351}
10352#endif
10353
10354/*!
10355 \return metadata for the graphics device used by this successfully
10356 initialized QRhi instance.
10357 */
10358QRhiDriverInfo QRhi::driverInfo() const
10359{
10360 return d->driverInfo();
10361}
10362
10363/*!
10364 \class QRhiAdapter
10365 \inmodule QtGuiPrivate
10366 \inheaderfile rhi/qrhi.h
10367 \since 6.10
10368
10369 \brief Represents a physical graphics device.
10370
10371 Some QRhi backends target graphics APIs that expose the concept of \c
10372 adapters or \c{physical devices}. Call the static \l
10373 {QRhi::}{enumerateAdapters()} function to retrieve a list of the adapters
10374 present in the system. Pass one of the returned QRhiAdapter objects to \l
10375 {QRhi::}{create()} in order to request using the adapter or physical device
10376 the QRhiAdapter corresponds to. Other than exposing the QRhiDriverInfo,
10377 QRhiAdapter is to be treated as an opaque handle.
10378
10379 \note With Vulkan, the QRhiAdapter is valid only as long as the
10380 QVulkanInstance that was used for \l{QRhi::}{enumerateAdapters()} is valid.
10381 This also means that a QRhiAdapter is tied to the Vulkan instance
10382 (QVulkanInstance, \c VkInstance) and cannot be used in the context of
10383 another Vulkan instance.
10384
10385 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10386 for details.
10387 */
10388
10389/*!
10390 \fn virtual QRhiDriverInfo QRhiAdapter::info() const = 0
10391
10392 \return the corresponding QRhiDriverInfo.
10393 */
10394
10395/*!
10396 \internal
10397 */
10398QRhiAdapter::~QRhiAdapter()
10399{
10400}
10401
10402/*!
10403 \return the thread on which the QRhi was \l{QRhi::create()}{initialized}.
10404 */
10405QThread *QRhi::thread() const
10406{
10407 return d->implThread;
10408}
10409
10410/*!
10411 Registers a \a callback that is invoked when the QRhi is destroyed.
10412
10413 The callback will run with the graphics resource still available, so this
10414 provides an opportunity for the application to cleanly release QRhiResource
10415 instances belonging to the QRhi. This is particularly useful for managing
10416 the lifetime of resources stored in \c cache type of objects, where the
10417 cache holds QRhiResources or objects containing QRhiResources.
10418
10419 \sa ~QRhi()
10420 */
10421void QRhi::addCleanupCallback(const CleanupCallback &callback)
10422{
10423 d->addCleanupCallback(callback);
10424}
10425
10426/*!
10427 \overload
10428
10429 Registers \a callback to be invoked when the QRhi is destroyed. This
10430 overload takes an opaque pointer, \a key, that is used to ensure that a
10431 given callback is registered (and so called) only once.
10432
10433 \sa removeCleanupCallback()
10434 */
10435void QRhi::addCleanupCallback(const void *key, const CleanupCallback &callback)
10436{
10437 d->addCleanupCallback(key, callback);
10438}
10439
10440/*!
10441 Deregisters the callback with \a key. If no cleanup callback was registered
10442 with \a key, the function does nothing. Callbacks registered without a key
10443 cannot be removed.
10444
10445 \sa addCleanupCallback()
10446 */
10447void QRhi::removeCleanupCallback(const void *key)
10448{
10449 d->removeCleanupCallback(key);
10450}
10451
10452void QRhiImplementation::runCleanup()
10453{
10454 for (const QRhi::CleanupCallback &f : std::as_const(cleanupCallbacks))
10455 f(q);
10456
10457 cleanupCallbacks.clear();
10458
10459 for (auto it = keyedCleanupCallbacks.cbegin(), end = keyedCleanupCallbacks.cend(); it != end; ++it)
10460 it.value()(q);
10461
10462 keyedCleanupCallbacks.clear();
10463}
10464
10465/*!
10466 \class QRhiResourceUpdateBatch
10467 \inmodule QtGuiPrivate
10468 \inheaderfile rhi/qrhi.h
10469 \since 6.6
10470 \brief Records upload and copy type of operations.
10471
10472 With QRhi it is no longer possible to perform copy type of operations at
10473 arbitrary times. Instead, all such operations are recorded into batches
10474 that are then passed, most commonly, to QRhiCommandBuffer::beginPass().
10475 What then happens under the hood is hidden from the application: the
10476 underlying implementations can defer and implement these operations in
10477 various different ways.
10478
10479 A resource update batch owns no graphics resources and does not perform any
10480 actual operations on its own. It should rather be viewed as a command
10481 buffer for update, upload, and copy type of commands.
10482
10483 To get an available, empty batch from the pool, call
10484 QRhi::nextResourceUpdateBatch().
10485
10486 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10487 for details.
10488 */
10489
10490/*!
10491 \internal
10492 */
10493QRhiResourceUpdateBatch::QRhiResourceUpdateBatch(QRhiImplementation *rhi)
10494 : d(new QRhiResourceUpdateBatchPrivate)
10495{
10496 d->q = this;
10497 d->rhi = rhi;
10498}
10499
10500QRhiResourceUpdateBatch::~QRhiResourceUpdateBatch()
10501{
10502 delete d;
10503}
10504
10505/*!
10506 \return the batch to the pool. This should only be used when the batch is
10507 not passed to one of QRhiCommandBuffer::beginPass(),
10508 QRhiCommandBuffer::endPass(), or QRhiCommandBuffer::resourceUpdate()
10509 because these implicitly call destroy().
10510
10511 \note QRhiResourceUpdateBatch instances must never by \c deleted by
10512 applications.
10513 */
10514void QRhiResourceUpdateBatch::release()
10515{
10516 d->free();
10517}
10518
10519/*!
10520 Copies all queued operations from the \a other batch into this one.
10521
10522 \note \a other may no longer contain valid data after the merge operation,
10523 and must not be submitted, but it will still need to be released by calling
10524 release().
10525
10526 This allows for a convenient pattern where resource updates that are
10527 already known during the initialization step are collected into a batch
10528 that is then merged into another when starting to first render pass later
10529 on:
10530
10531 \code
10532 void init()
10533 {
10534 initialUpdates = rhi->nextResourceUpdateBatch();
10535 initialUpdates->uploadStaticBuffer(vbuf, vertexData);
10536 initialUpdates->uploadStaticBuffer(ibuf, indexData);
10537 // ...
10538 }
10539
10540 void render()
10541 {
10542 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
10543 if (initialUpdates) {
10544 resUpdates->merge(initialUpdates);
10545 initialUpdates->release();
10546 initialUpdates = nullptr;
10547 }
10548 // resUpdates->updateDynamicBuffer(...);
10549 cb->beginPass(rt, clearCol, clearDs, resUpdates);
10550 }
10551 \endcode
10552 */
10553void QRhiResourceUpdateBatch::merge(QRhiResourceUpdateBatch *other)
10554{
10555 d->merge(other->d);
10556}
10557
10558/*!
10559 \return true until the number of buffer and texture operations enqueued
10560 onto this batch is below a reasonable limit.
10561
10562 The return value is false when the number of buffer and/or texture
10563 operations added to this batch have reached, or are about to reach, a
10564 certain limit. The batch is fully functional afterwards as well, but may
10565 need to allocate additional memory. Therefore, a renderer that collects
10566 lots of buffer and texture updates in a single batch when preparing a frame
10567 may want to consider \l{QRhiCommandBuffer::resourceUpdate()}{submitting the
10568 batch} and \l{QRhi::nextResourceUpdateBatch()}{starting a new one} when
10569 this function returns false.
10570 */
10571bool QRhiResourceUpdateBatch::hasOptimalCapacity() const
10572{
10573 return d->hasOptimalCapacity();
10574}
10575
10576/*!
10577 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10578 QRhiBuffer::Dynamic.
10579
10580 The region is specified \a offset and \a size. The actual bytes to write
10581 are specified by \a data which must have at least \a size bytes available.
10582
10583 \a data is copied and can safely be destroyed or changed once this function
10584 returns.
10585
10586 \note If host writes are involved, which is the case with
10587 updateDynamicBuffer() typically as such buffers are backed by host visible
10588 memory with most backends, they may accumulate within a frame. Thus pass 1
10589 reading a region changed by a batch passed to pass 2 may see the changes
10590 specified in pass 2's update batch.
10591
10592 \note QRhi transparently manages double buffering in order to prevent
10593 stalling the graphics pipeline. The fact that a QRhiBuffer may have
10594 multiple native buffer objects underneath can be safely ignored when using
10595 the QRhi and QRhiResourceUpdateBatch.
10596 */
10597void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
10598{
10599 if (size > 0) {
10600 const int idx = d->activeBufferOpCount++;
10601 const int opListSize = d->bufferOps.size();
10602 if (idx < opListSize)
10603 QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, size, data);
10604 else
10605 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, size, data));
10606 }
10607}
10608
10609/*!
10610 \overload
10611 \since 6.10
10612
10613 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10614 QRhiBuffer::Dynamic.
10615
10616 \a data is moved into the batch instead of copied with this overload.
10617 */
10618void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
10619{
10620 if (!data.isEmpty()) {
10621 const int idx = d->activeBufferOpCount++;
10622 const int opListSize = d->bufferOps.size();
10623 if (idx < opListSize)
10624 QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, std::move(data));
10625 else
10626 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, std::move(data)));
10627 }
10628}
10629
10630/*!
10631 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10632 QRhiBuffer::Immutable or QRhiBuffer::Static.
10633
10634 The region is specified \a offset and \a size. The actual bytes to write
10635 are specified by \a data which must have at least \a size bytes available.
10636
10637 \a data is copied and can safely be destroyed or changed once this function
10638 returns.
10639 */
10640void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
10641{
10642 if (size > 0) {
10643 const int idx = d->activeBufferOpCount++;
10644 if (idx < d->bufferOps.size())
10645 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, size, data);
10646 else
10647 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, size, data));
10648 }
10649}
10650
10651/*!
10652 \overload
10653 \since 6.10
10654
10655 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10656 QRhiBuffer::Immutable or QRhiBuffer::Static.
10657
10658 \a data is moved into the batch instead of copied with this overload.
10659 */
10660void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
10661{
10662 if (!data.isEmpty()) {
10663 const int idx = d->activeBufferOpCount++;
10664 if (idx < d->bufferOps.size())
10665 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, std::move(data));
10666 else
10667 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, std::move(data)));
10668 }
10669}
10670
10671/*!
10672 \overload
10673
10674 Enqueues updating the entire QRhiBuffer \a buf created with the type
10675 QRhiBuffer::Immutable or QRhiBuffer::Static.
10676 */
10677void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *data)
10678{
10679 if (buf->size() > 0) {
10680 const int idx = d->activeBufferOpCount++;
10681 if (idx < d->bufferOps.size())
10682 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, 0, data);
10683 else
10684 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, 0, data));
10685 }
10686}
10687
10688/*!
10689 \overload
10690 \since 6.10
10691
10692 Enqueues updating the entire QRhiBuffer \a buf created with the type
10693 QRhiBuffer::Immutable or QRhiBuffer::Static.
10694
10695 \a data is moved into the batch instead of copied with this overload.
10696
10697 \a data size must equal the size of \a buf.
10698 */
10699void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, QByteArray data)
10700{
10701 if (buf->size() > 0 && quint32(data.size()) == buf->size()) {
10702 const int idx = d->activeBufferOpCount++;
10703 if (idx < d->bufferOps.size())
10704 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, std::move(data));
10705 else
10706 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, std::move(data)));
10707 }
10708}
10709
10710/*!
10711 Enqueues reading back a region of the QRhiBuffer \a buf. The size of the
10712 region is specified by \a size in bytes, \a offset is the offset in bytes
10713 to start reading from.
10714
10715 A readback is asynchronous. \a result contains a callback that is invoked
10716 when the operation has completed. The data is provided in
10717 QRhiReadbackResult::data. Upon successful completion that QByteArray
10718 will have a size equal to \a size. On failure the QByteArray will be empty.
10719
10720 \note Reading buffers with a usage different than QRhiBuffer::UniformBuffer
10721 is supported only when the QRhi::ReadBackNonUniformBuffer feature is
10722 reported as supported.
10723
10724 \note The asynchronous readback is guaranteed to have completed when one of
10725 the following conditions is met: \l{QRhi::finish()}{finish()} has been
10726 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
10727 including the frame that issued the readback operation, and the
10728 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
10729 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
10730 QRhi::MaxAsyncReadbackFrames.
10731
10732 \sa readBackTexture(), QRhi::isFeatureSupported(), QRhi::resourceLimit()
10733 */
10734void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
10735{
10736 const int idx = d->activeBufferOpCount++;
10737 if (idx < d->bufferOps.size())
10738 d->bufferOps[idx] = QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result);
10739 else
10740 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result));
10741}
10742
10743/*!
10744 Enqueues uploading the image data for one or more mip levels in one or more
10745 layers of the texture \a tex.
10746
10747 The details of the copy (source QImage or compressed texture data, regions,
10748 target layers and levels) are described in \a desc.
10749 */
10750void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
10751{
10752 if (desc.cbeginEntries() != desc.cendEntries()) {
10753 const int idx = d->activeTextureOpCount++;
10754 if (idx < d->textureOps.size())
10755 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc);
10756 else
10757 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc));
10758 }
10759}
10760
10761/*!
10762 Enqueues uploading the image data for mip level 0 of layer 0 of the texture
10763 \a tex.
10764
10765 \a tex must have an uncompressed format. Its format must also be compatible
10766 with the QImage::format() of \a image. The source data is given in \a
10767 image.
10768 */
10769void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &image)
10770{
10771 uploadTexture(tex,
10772 QRhiTextureUploadEntry(0, 0, QRhiTextureSubresourceUploadDescription(image)));
10773}
10774
10775/*!
10776 Enqueues a texture-to-texture copy operation from \a src into \a dst as
10777 described by \a desc.
10778
10779 \note The source texture \a src must be created with
10780 QRhiTexture::UsedAsTransferSource.
10781
10782 \note The format of the textures must match. With most graphics
10783 APIs the data is copied as-is without any format conversions. If
10784 \a dst and \a src are created with different formats, unspecified
10785 issues may arise.
10786 */
10787void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
10788{
10789 const int idx = d->activeTextureOpCount++;
10790 if (idx < d->textureOps.size())
10791 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc);
10792 else
10793 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc));
10794}
10795
10796/*!
10797 Enqueues a texture-to-host copy operation as described by \a rb.
10798
10799 Normally \a rb will specify a QRhiTexture as the source. However, when the
10800 swapchain in the current frame was created with
10801 QRhiSwapChain::UsedAsTransferSource, it can also be the source of the
10802 readback. For this, leave the texture set to null in \a rb.
10803
10804 Unlike other operations, the results here need to be processed by the
10805 application. Therefore, \a result provides not just the data but also a
10806 callback as operations on the batch are asynchronous by nature:
10807
10808 \code
10809 rhi->beginFrame(swapchain);
10810 cb->beginPass(swapchain->currentFrameRenderTarget(), colorClear, dsClear);
10811 // ...
10812 QRhiReadbackResult *rbResult = new QRhiReadbackResult;
10813 rbResult->completed = [rbResult] {
10814 {
10815 const QImage::Format fmt = QImage::Format_RGBA8888_Premultiplied; // fits QRhiTexture::RGBA8
10816 const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
10817 QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
10818 image.save("result.png");
10819 }
10820 delete rbResult;
10821 };
10822 QRhiResourceUpdateBatch *u = nextResourceUpdateBatch();
10823 QRhiReadbackDescription rb; // no texture -> uses the current backbuffer of sc
10824 u->readBackTexture(rb, rbResult);
10825 cb->endPass(u);
10826 rhi->endFrame(swapchain);
10827 \endcode
10828
10829 \note The texture must be created with QRhiTexture::UsedAsTransferSource.
10830
10831 \note Multisample textures cannot be read back.
10832
10833 \note The readback returns raw byte data, in order to allow the applications
10834 to interpret it in any way they see fit. Be aware of the blending settings
10835 of rendering code: if the blending is set up to rely on premultiplied alpha,
10836 the results of the readback must also be interpreted as Premultiplied.
10837
10838 \note When interpreting the resulting raw data, be aware that the readback
10839 happens with a byte ordered format. A \l{QRhiTexture::RGBA8}{RGBA8} texture
10840 maps therefore to byte ordered QImage formats, such as,
10841 QImage::Format_RGBA8888.
10842
10843 \note The asynchronous readback is guaranteed to have completed when one of
10844 the following conditions is met: \l{QRhi::finish()}{finish()} has been
10845 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
10846 including the frame that issued the readback operation, and the
10847 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
10848 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
10849 QRhi::MaxAsyncReadbackFrames.
10850
10851 A single readback operation copies one mip level of one layer (cubemap face
10852 or 3D slice or texture array element) at a time. The level and layer are
10853 specified by the respective fields in \a rb.
10854
10855 \sa readBackBuffer(), QRhi::resourceLimit()
10856 */
10857void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
10858{
10859 const int idx = d->activeTextureOpCount++;
10860 if (idx < d->textureOps.size())
10861 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result);
10862 else
10863 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result));
10864}
10865
10866/*!
10867 Enqueues a mipmap generation operation for the specified texture \a tex.
10868
10869 2D and cube textures are supported. 1D and 3D textures are supported when
10870 the QRhi::OneDimensionalTextureMipmaps or QRhi::ThreeDimensionalTextureMipmaps
10871 feature is reported as supported, respectively.
10872
10873 \note The texture must be created with QRhiTexture::MipMapped and
10874 QRhiTexture::UsedWithGenerateMips.
10875
10876 \warning QRhi cannot guarantee that mipmaps can be generated for all
10877 supported texture formats. For example, QRhiTexture::RGBA32F is not a \c
10878 filterable format in OpenGL ES 3.0 and Metal on iOS, and therefore the
10879 mipmap generation request may fail. RGBA8 and RGBA16F are typically
10880 filterable, so it is recommended to use these formats when mipmap generation
10881 is desired.
10882 */
10883void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex)
10884{
10885 const int idx = d->activeTextureOpCount++;
10886 if (idx < d->textureOps.size())
10887 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex);
10888 else
10889 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex));
10890}
10891
10892/*!
10893 Enqueues updating the contents of the indirect command buffer \a icb from
10894 the commands recorded on it with QRhiIndirectCommandBuffer::draw() or
10895 QRhiIndirectCommandBuffer::drawIndexed().
10896
10897 Has to be called after recording and before the render pass that executes
10898 the commands. Does nothing when nothing changed since the last time, so
10899 calling it once per frame is inexpensive.
10900
10901 Has no effect on an indirect command buffer that was populated with
10902 QRhiCommandBuffer::buildIndirect() instead.
10903
10904 \note This is where backends that keep the commands in a buffer perform the
10905 upload, but it is not necessarily where the cost of a CPU-recorded indirect
10906 command buffer is: Metal has nothing to upload here and does its per-command
10907 encoding in QRhiCommandBuffer::executeIndirect() instead. An inexpensive
10908 commitIndirectCommandBuffer() therefore does not by itself mean that
10909 recording the commands was inexpensive. See \l QRhiIndirectCommandBuffer for
10910 how the cost of CPU recording scales.
10911
10912 \since 6.13
10913 */
10914void QRhiResourceUpdateBatch::commitIndirectCommandBuffer(QRhiIndirectCommandBuffer *icb)
10915{
10916 Q_ASSERT(icb);
10917 d->rhi->commitIndirectCommandBuffer(this, icb);
10918}
10919
10920/*!
10921 \return an available, empty batch to which copy type of operations can be
10922 recorded.
10923
10924 \note the return value is not owned by the caller and must never be
10925 destroyed. Instead, the batch is returned the pool for reuse by passing
10926 it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or
10927 QRhiCommandBuffer::resourceUpdate(), or by calling
10928 QRhiResourceUpdateBatch::release() on it.
10929
10930 \note Can be called outside beginFrame() - endFrame() as well since a batch
10931 instance just collects data on its own, it does not perform any operations.
10932
10933 Due to not being tied to a frame being recorded, the following sequence is
10934 valid for example:
10935
10936 \code
10937 rhi->beginFrame(swapchain);
10938 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
10939 u->uploadStaticBuffer(buf, data);
10940 // ... do not commit the batch
10941 rhi->endFrame();
10942 // u stays valid (assuming buf stays valid as well)
10943 rhi->beginFrame(swapchain);
10944 swapchain->currentFrameCommandBuffer()->resourceUpdate(u);
10945 // ... draw with buf
10946 rhi->endFrame();
10947 \endcode
10948
10949 \warning The maximum number of batches per QRhi is 64. When this limit is
10950 reached, the function will return null until a batch is returned to the
10951 pool.
10952 */
10953QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
10954{
10955 // By default we prefer spreading out the utilization of the worst case 64
10956 // (but typically 4) batches as much as possible, meaning we won't pick the
10957 // first one even if it's free, but prefer picking one after the last picked
10958 // one. Relevant due to implicit sharing (the backend may hold on to the
10959 // QRhiBufferData until frame no. current+FramesInFlight-1, but
10960 // implementations may vary), combined with the desire to reuse container
10961 // and QRhiBufferData allocations in bufferOps instead of flooding every
10962 // frame with allocs. See free(). In typical Qt Quick scenes this leads to
10963 // eventually seeding all 4 (or more) resource batches with buffer operation
10964 // data allocations which may (*) then be reused in subsequent frames. This
10965 // comes at the expense of using more memory, but has proven good results
10966 // when (CPU) profiling typical Quick/Quick3D apps.
10967 //
10968 // (*) Due to implicit sharing(ish), the exact behavior is unpredictable. If
10969 // a backend holds on to the QRhiBufferData for, e.g., a dynamic buffer
10970 // update, and then there is a new assign() for that same QRhiBufferData
10971 // while the refcount is still 2, it will "detach" (without contents) and
10972 // there is no reuse of the alloc. This is mitigated by the 'choose the one
10973 // afer the last picked one' logic when handing out batches.
10974
10975 auto nextFreeBatch = [this]() -> QRhiResourceUpdateBatch * {
10976 auto isFree = [this](int i) -> QRhiResourceUpdateBatch * {
10977 const quint64 mask = 1ULL << quint64(i);
10978 if (!(d->resUpdPoolMap & mask)) {
10979 d->resUpdPoolMap |= mask;
10980 QRhiResourceUpdateBatch *u = d->resUpdPool[i];
10981 QRhiResourceUpdateBatchPrivate::get(u)->poolIndex = i;
10982 d->lastResUpdIdx = i;
10983 return u;
10984 }
10985 return nullptr;
10986 };
10987 const int poolSize = d->resUpdPool.size();
10988 for (int i = d->lastResUpdIdx + 1; i < poolSize; ++i) {
10989 if (QRhiResourceUpdateBatch *u = isFree(i))
10990 return u;
10991 }
10992 for (int i = 0; i <= d->lastResUpdIdx; ++i) {
10993 if (QRhiResourceUpdateBatch *u = isFree(i))
10994 return u;
10995 }
10996 return nullptr;
10997 };
10998
10999 QRhiResourceUpdateBatch *u = nextFreeBatch();
11000 if (!u) {
11001 const int oldSize = d->resUpdPool.size();
11002 // 4, 8, 12, ..., up to 64
11003 const int newSize = oldSize + qMin(4, qMax(0, 64 - oldSize));
11004 d->resUpdPool.resize(newSize);
11005 for (int i = oldSize; i < newSize; ++i)
11006 d->resUpdPool[i] = new QRhiResourceUpdateBatch(d);
11007 u = nextFreeBatch();
11008 if (!u)
11009 qWarning("Resource update batch pool exhausted (max is 64)");
11010 }
11011
11012 return u;
11013}
11014
11016{
11017 Q_ASSERT(poolIndex >= 0 && rhi->resUpdPool[poolIndex] == q);
11018
11019 quint32 bufferDataTotal = 0;
11020 quint32 bufferLargeAllocTotal = 0;
11021 for (const BufferOp &op : std::as_const(bufferOps)) {
11022 bufferDataTotal += op.data.size();
11023 bufferLargeAllocTotal += op.data.largeAlloc(); // alloc when > 1 KB
11024 }
11025
11026 if (QRHI_LOG_RUB().isDebugEnabled()) {
11027 qDebug() << "[rub] release to pool upd.batch #" << poolIndex
11028 << "/ bufferOps active" << activeBufferOpCount
11029 << "of" << bufferOps.count()
11030 << "data" << bufferDataTotal
11031 << "largeAlloc" << bufferLargeAllocTotal
11032 << "textureOps active" << activeTextureOpCount
11033 << "of" << textureOps.count();
11034 }
11035
11038
11039 const quint64 mask = 1ULL << quint64(poolIndex);
11040 rhi->resUpdPoolMap &= ~mask;
11041 poolIndex = -1;
11042
11043 // textureOps is cleared, to not keep the potentially large image pixel
11044 // data alive, but it is expected that the container keeps the list alloc
11045 // at least. Only trimOpList() goes for the more aggressive route with squeeze.
11046 textureOps.clear();
11047
11048 // bufferOps is not touched in many cases, to allow reusing allocations
11049 // (incl. in the elements' QRhiBufferData) as much as possible when this
11050 // batch is used again in the future, which is important for performance, in
11051 // particular with Qt Quick where it is easy for scenes to produce lots of,
11052 // typically small buffer changes on every frame.
11053 //
11054 // However, ensure that even in the unlikely case of having the max number
11055 // of batches (64) created in resUpdPool, no more than 64 MB in total is
11056 // used up by buffer data just to help future reuse. For simplicity, if
11057 // there is more than 1 MB data -> clear. Applications with frequent, huge
11058 // buffer updates probably have other bottlenecks anyway.
11059 if (bufferLargeAllocTotal > 1024 * 1024)
11060 bufferOps.clear();
11061}
11062
11064{
11065 int combinedSize = activeBufferOpCount + other->activeBufferOpCount;
11066 if (bufferOps.size() < combinedSize)
11067 bufferOps.resize(combinedSize);
11068 for (int i = activeBufferOpCount; i < combinedSize; ++i)
11069 bufferOps[i] = std::move(other->bufferOps[i - activeBufferOpCount]);
11071
11072 combinedSize = activeTextureOpCount + other->activeTextureOpCount;
11073 if (textureOps.size() < combinedSize)
11074 textureOps.resize(combinedSize);
11075 for (int i = activeTextureOpCount; i < combinedSize; ++i)
11076 textureOps[i] = std::move(other->textureOps[i - activeTextureOpCount]);
11078}
11079
11085
11087{
11088 // Unlike free(), this is expected to aggressively deallocate all memory
11089 // used by both the buffer and texture operation lists. (i.e. using
11090 // squeeze() to only keep the stack prealloc of the QVLAs)
11091 //
11092 // This (e.g. just the destruction of bufferOps elements) may have a
11093 // non-negligible performance impact e.g. with Qt Quick with scenes where
11094 // there are lots of buffer operations per frame.
11095
11097 bufferOps.clear();
11098 bufferOps.squeeze();
11099
11101 textureOps.clear();
11102 textureOps.squeeze();
11103}
11104
11105/*!
11106 Sometimes committing resource updates is necessary or just more convenient
11107 without starting a render pass. Calling this function with \a
11108 resourceUpdates is an alternative to passing \a resourceUpdates to a
11109 beginPass() call (or endPass(), which would be typical in case of readbacks).
11110
11111 \note Cannot be called inside a pass.
11112 */
11113void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
11114{
11115 if (resourceUpdates)
11116 m_rhi->resourceUpdate(this, resourceUpdates);
11117}
11118
11119/*!
11120 Records starting a new render pass targeting the render target \a rt.
11121
11122 \a resourceUpdates, when not null, specifies a resource update batch that
11123 is to be committed and then released.
11124
11125 The color and depth/stencil buffers of the render target are normally
11126 cleared. The clear values are specified in \a colorClearValue and \a
11127 depthStencilClearValue. The exception is when the render target was created
11128 with QRhiTextureRenderTarget::PreserveColorContents and/or
11129 QRhiTextureRenderTarget::PreserveDepthStencilContents. The clear values are
11130 ignored then.
11131
11132 \note Enabling preserved color or depth contents leads to decreased
11133 performance depending on the underlying hardware. Mobile GPUs with tiled
11134 architecture benefit from not having to reload the previous contents into
11135 the tile buffer. Similarly, a QRhiTextureRenderTarget with a QRhiTexture as
11136 the depth buffer is less efficient than a QRhiRenderBuffer since using a
11137 depth texture triggers requiring writing the data out to it, while with
11138 renderbuffers this is not needed (as the API does not allow sampling or
11139 reading from a renderbuffer).
11140
11141 \note Do not assume that any state or resource bindings persist between
11142 passes.
11143
11144 \note The QRhiCommandBuffer's \c set and \c draw functions can only be
11145 called inside a pass. Also, with the exception of setGraphicsPipeline(),
11146 they expect to have a pipeline set already on the command buffer.
11147 Unspecified issues may arise otherwise, depending on the backend.
11148
11149 If \a rt is a QRhiTextureRenderTarget, beginPass() performs a check to see
11150 if the texture and renderbuffer objects referenced from the render target
11151 are up-to-date. This is similar to what setShaderResources() does for
11152 QRhiShaderResourceBindings. If any of the attachments had been rebuilt
11153 since QRhiTextureRenderTarget::create(), an implicit call to create() is
11154 made on \a rt. Therefore, if \a rt has a QRhiTexture color attachment \c
11155 texture, and one needs to make the texture a different size, the following
11156 is then valid:
11157 \code
11158 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ { texture } });
11159 rt->create();
11160 // ...
11161 texture->setPixelSize(new_size);
11162 texture->create();
11163 cb->beginPass(rt, colorClear, dsClear); // this is ok, no explicit rt->create() is required before
11164 \endcode
11165
11166 \a flags allow controlling certain advanced functionality. One commonly used
11167 flag is \c ExternalContents. This should be specified whenever
11168 beginExternal() will be called within the pass started by this function.
11169
11170 \sa endPass(), BeginPassFlags
11171 */
11172void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
11173 const QColor &colorClearValue,
11174 const QRhiDepthStencilClearValue &depthStencilClearValue,
11175 QRhiResourceUpdateBatch *resourceUpdates,
11176 BeginPassFlags flags)
11177{
11178 m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates, flags);
11179}
11180
11181/*!
11182 Records ending the current render pass.
11183
11184 \a resourceUpdates, when not null, specifies a resource update batch that
11185 is to be committed and then released.
11186
11187 \sa beginPass()
11188 */
11189void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates)
11190{
11191 m_rhi->endPass(this, resourceUpdates);
11192}
11193
11194/*!
11195 Records setting a new graphics pipeline \a ps.
11196
11197 \note This function must be called before recording other \c set or \c draw
11198 commands on the command buffer.
11199
11200 \note QRhi will optimize out unnecessary invocations within a pass, so
11201 therefore overoptimizing to avoid calls to this function is not necessary
11202 on the applications' side.
11203
11204 \note This function can only be called inside a render pass, meaning
11205 between a beginPass() and endPass() call.
11206
11207 \note The new graphics pipeline \a ps must be a valid pointer.
11208
11209 Setting a graphics pipeline that does not have the
11210 \l{QRhiGraphicsPipeline::}{UsesScissor} flag will either disable scissoring,
11211 with graphics APIs where that is applicable, or set the scissor rectangle to
11212 match the viewport that was last set (with graphics APIs where scissoring is
11213 effectively always active), in order to ensure a uniform behavior across QRhi
11214 backends.
11215 */
11216void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)
11217{
11218 Q_ASSERT(ps != nullptr);
11219 m_rhi->setGraphicsPipeline(this, ps);
11220}
11221
11222/*!
11223 Records binding a set of shader resources, such as, uniform buffers or
11224 textures, that are made visible to one or more shader stages.
11225
11226 \a srb can be null in which case the current graphics or compute pipeline's
11227 associated QRhiShaderResourceBindings is used. When \a srb is non-null, it
11228 must be
11229 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible},
11230 meaning the layout (number of bindings, the type and binding number of each
11231 binding) must fully match the QRhiShaderResourceBindings that was
11232 associated with the pipeline at the time of calling the pipeline's create().
11233
11234 There are cases when a seemingly unnecessary setShaderResources() call is
11235 mandatory: when rebuilding a resource referenced from \a srb, for example
11236 changing the size of a QRhiBuffer followed by a QRhiBuffer::create(), this
11237 is the place where associated native objects (such as descriptor sets in
11238 case of Vulkan) are updated to refer to the current native resources that
11239 back the QRhiBuffer, QRhiTexture, QRhiSampler objects referenced from \a
11240 srb. In this case setShaderResources() must be called even if \a srb is
11241 the same as in the last call.
11242
11243 When \a srb is not null, the QRhiShaderResourceBindings object the pipeline
11244 was built with in create() is guaranteed to be not accessed in any form. In
11245 fact, it does not need to be valid even at this point: destroying the
11246 pipeline's associated srb after create() and instead explicitly specifying
11247 another, \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout
11248 compatible} one in every setShaderResources() call is valid.
11249
11250 \a dynamicOffsets allows specifying buffer offsets for uniform buffers that
11251 were associated with \a srb via
11252 QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(). This is
11253 different from providing the offset in the \a srb itself: dynamic offsets
11254 do not require building a new QRhiShaderResourceBindings for every
11255 different offset, can avoid writing the underlying descriptors (with
11256 backends where applicable), and so they may be more efficient. Each element
11257 of \a dynamicOffsets is a \c binding - \c offset pair.
11258 \a dynamicOffsetCount specifies the number of elements in \a dynamicOffsets.
11259
11260 \note All offsets in \a dynamicOffsets must be byte aligned to the value
11261 returned from QRhi::ubufAlignment().
11262
11263 \note Some backends may limit the number of supported dynamic offsets.
11264 Avoid using a \a dynamicOffsetCount larger than 8.
11265
11266 \note QRhi will optimize out unnecessary invocations within a pass (taking
11267 the conditions described above into account), so therefore overoptimizing
11268 to avoid calls to this function is not necessary on the applications' side.
11269
11270 \note This function can only be called inside a render or compute pass,
11271 meaning between a beginPass() and endPass(), or beginComputePass() and
11272 endComputePass().
11273 */
11274void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb,
11275 int dynamicOffsetCount,
11276 const DynamicOffset *dynamicOffsets)
11277{
11278 m_rhi->setShaderResources(this, srb, dynamicOffsetCount, dynamicOffsets);
11279}
11280
11281/*!
11282 Records vertex input bindings.
11283
11284 The index buffer used by subsequent drawIndexed() commands is specified by
11285 \a indexBuf, \a indexOffset, and \a indexFormat. \a indexBuf can be set to
11286 null when indexed drawing is not needed.
11287
11288 Vertex buffer bindings are batched. \a startBinding specifies the first
11289 binding number. The recorded command then binds each buffer from \a
11290 bindings to the binding point \c{startBinding + i} where \c i is the index
11291 in \a bindings. Each element in \a bindings specifies a QRhiBuffer and an
11292 offset.
11293
11294 \note Some backends may limit the number of vertex buffer bindings. Avoid
11295 using a \a bindingCount larger than 8.
11296
11297 Superfluous vertex input and index changes in the same pass are ignored
11298 automatically with most backends and therefore applications do not need to
11299 overoptimize to avoid calls to this function.
11300
11301 \note This function can only be called inside a render pass, meaning
11302 between a beginPass() and endPass() call.
11303
11304 As a simple example, take a vertex shader with two inputs:
11305
11306 \badcode
11307 layout(location = 0) in vec4 position;
11308 layout(location = 1) in vec3 color;
11309 \endcode
11310
11311 and assume we have the data available in interleaved format, using only 2
11312 floats for position (so 5 floats per vertex: x, y, r, g, b). A QRhiGraphicsPipeline for
11313 this shader can then be created using the input layout:
11314
11315 \code
11316 QRhiVertexInputLayout inputLayout;
11317 inputLayout.setBindings({
11318 { 5 * sizeof(float) }
11319 });
11320 inputLayout.setAttributes({
11321 { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
11322 { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
11323 });
11324 \endcode
11325
11326 Here there is one buffer binding (binding number 0), with two inputs
11327 referencing it. When recording the pass, once the pipeline is set, the
11328 vertex bindings can be specified simply like the following, assuming vbuf
11329 is the QRhiBuffer with all the interleaved position+color data:
11330
11331 \code
11332 const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
11333 cb->setVertexInput(0, 1, &vbufBinding);
11334 \endcode
11335 */
11336void QRhiCommandBuffer::setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
11337 QRhiBuffer *indexBuf, quint32 indexOffset,
11338 IndexFormat indexFormat)
11339{
11340 m_rhi->setVertexInput(this, startBinding, bindingCount, bindings, indexBuf, indexOffset, indexFormat);
11341}
11342
11343/*!
11344 Records setting the active viewport rectangle specified in \a viewport.
11345
11346 With backends where the underlying graphics API has scissoring always
11347 enabled, this function also sets the scissor to match the viewport whenever
11348 the active QRhiGraphicsPipeline does not have
11349 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set.
11350
11351 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
11352 bottom-left.
11353
11354 \note This function can only be called inside a render pass, meaning
11355 between a beginPass() and endPass() call.
11356 */
11357void QRhiCommandBuffer::setViewport(const QRhiViewport &viewport)
11358{
11359 m_rhi->setViewport(this, viewport);
11360}
11361
11362/*!
11363 Records setting the active scissor rectangle specified in \a scissor.
11364
11365 This can only be called when the bound pipeline has
11366 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set. When the flag is
11367 set on the active pipeline, this function must be called because scissor
11368 testing will get enabled and so a scissor rectangle must be provided.
11369
11370 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
11371 bottom-left.
11372
11373 \note This function can only be called inside a render pass, meaning
11374 between a beginPass() and endPass() call.
11375 */
11376void QRhiCommandBuffer::setScissor(const QRhiScissor &scissor)
11377{
11378 m_rhi->setScissor(this, scissor);
11379}
11380
11381/*!
11382 Records setting the active blend constants to \a c.
11383
11384 This can only be called when the bound pipeline has
11385 QRhiGraphicsPipeline::UsesBlendConstants set.
11386
11387 \note This function can only be called inside a render pass, meaning
11388 between a beginPass() and endPass() call.
11389 */
11390void QRhiCommandBuffer::setBlendConstants(const QColor &c)
11391{
11392 m_rhi->setBlendConstants(this, c);
11393}
11394
11395/*!
11396 Records setting the active stencil reference value to \a refValue.
11397
11398 This can only be called when the bound pipeline has
11399 QRhiGraphicsPipeline::UsesStencilRef set.
11400
11401 \note This function can only be called inside a render pass, meaning between
11402 a beginPass() and endPass() call.
11403 */
11404void QRhiCommandBuffer::setStencilRef(quint32 refValue)
11405{
11406 m_rhi->setStencilRef(this, refValue);
11407}
11408
11409/*!
11410 Sets the shading rate for the following draw calls to \a coarsePixelSize.
11411
11412 The default is 1x1.
11413
11414 Functional only when the \l QRhi::VariableRateShading feature is reported as
11415 supported and the QRhiGraphicsPipeline(s) bound on the command buffer were
11416 declaring \l QRhiGraphicsPipeline::UsesShadingRate when creating them.
11417
11418 Call \l QRhi::supportedShadingRates() to check what shading rates are
11419 supported for a given sample count.
11420
11421 When both a QRhiShadingRateMap and this function are in use, the higher of
11422 the two shading rates is used for each tile. There is currently no control
11423 offered over the combiner behavior.
11424
11425 \since 6.9
11426 */
11427void QRhiCommandBuffer::setShadingRate(const QSize &coarsePixelSize)
11428{
11429 m_rhi->setShadingRate(this, coarsePixelSize);
11430}
11431
11432/*!
11433 Records a non-indexed draw.
11434
11435 The number of vertices is specified in \a vertexCount. For instanced
11436 drawing set \a instanceCount to a value other than 1. \a firstVertex is the
11437 index of the first vertex to draw. When drawing multiple instances, the
11438 first instance ID is specified by \a firstInstance.
11439
11440 \note \a firstInstance may not be supported, and is ignored when the
11441 QRhi::BaseInstance feature is reported as not supported. The first instance
11442 ID is always 0 in that case. QRhi::BaseInstance is never supported with
11443 OpenGL ES, and therefore portable applications should not be designed to
11444 rely on this argument.
11445
11446 \note Shaders that need to access the index of the current vertex or
11447 instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
11448 Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
11449 gl_InstanceID.
11450
11451 \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
11452 include the base value with some of the underlying 3D APIs. This is
11453 indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
11454 on a base instance value cannot be avoided, applications are advised to pass
11455 in the value as a uniform conditionally based on what that feature reports,
11456 and add it to \c gl_InstanceIndex in the shader.
11457
11458 \note This function can only be called inside a render pass, meaning
11459 between a beginPass() and endPass() call.
11460 */
11461void QRhiCommandBuffer::draw(quint32 vertexCount,
11462 quint32 instanceCount,
11463 quint32 firstVertex,
11464 quint32 firstInstance)
11465{
11466 m_rhi->draw(this, vertexCount, instanceCount, firstVertex, firstInstance);
11467}
11468
11469/*!
11470 Records an indexed draw.
11471
11472 The number of vertices is specified in \a indexCount. \a firstIndex is the
11473 base index. The effective offset in the index buffer is given by
11474 \c{indexOffset + firstIndex * n} where \c n is 2 or 4 depending on the
11475 index element type. \c indexOffset is specified in setVertexInput().
11476
11477 \note The effective offset in the index buffer must be 4 byte aligned with
11478 some backends (for example, Metal). With these backends the
11479 \l{QRhi::NonFourAlignedEffectiveIndexBufferOffset}{NonFourAlignedEffectiveIndexBufferOffset}
11480 feature will be reported as not-supported.
11481
11482 \a vertexOffset (also called \c{base vertex}) is a signed value that is
11483 added to the element index before indexing into the vertex buffer. Support
11484 for this is not always available, and the value is ignored when the feature
11485 QRhi::BaseVertex is reported as unsupported.
11486
11487 For instanced drawing set \a instanceCount to a value other than 1. When
11488 drawing multiple instances, the first instance ID is specified by \a
11489 firstInstance.
11490
11491 \note \a firstInstance may not be supported, and is ignored when the
11492 QRhi::BaseInstance feature is reported as not supported. The first instance
11493 ID is always 0 in that case. QRhi::BaseInstance is never supported with
11494 OpenGL ES, and therefore portable applications should not be designed to
11495 rely on this argument.
11496
11497 \note Shaders that need to access the index of the current vertex or
11498 instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
11499 Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
11500 gl_InstanceID.
11501
11502 \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
11503 include the base value with some of the underlying 3D APIs. This is
11504 indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
11505 on a base instance value cannot be avoided, applications are advised to pass
11506 in the value as a uniform conditionally based on what that feature reports,
11507 and add it to \c gl_InstanceIndex in the shader.
11508
11509 \note This function can only be called inside a render pass, meaning
11510 between a beginPass() and endPass() call.
11511 */
11512void QRhiCommandBuffer::drawIndexed(quint32 indexCount,
11513 quint32 instanceCount,
11514 quint32 firstIndex,
11515 qint32 vertexOffset,
11516 quint32 firstInstance)
11517{
11518 m_rhi->drawIndexed(this, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
11519}
11520
11521/*!
11522 Records a non-indexed, indirect draw.
11523
11524 The draw parameters are provided by the buffer specified in \a indirectBuffer,
11525 which must contain an array of elements of type QRhiIndirectDrawCommand.
11526 The parameters in QRhiIndirectDrawCommand have the same meaning as in draw().
11527
11528 The offset, in bytes, from which the parameters are read in the buffer is specified
11529 by \a indirectBufferOffset.
11530
11531 \a drawCount specifies the number of such draw commands to issue.
11532
11533 \a stride indicates the byte size of each individual draw command structure
11534 in the buffer. This allows interleaving custom data between commands if needed.
11535 The value must be a multiple of 4 and greater than or equal to sizeof(QRhiIndirectDrawCommand).
11536
11537 \note A \a drawCount value greater than 1 is only natively supported if the
11538 QRhi::DrawIndirectMulti feature is reported as supported.
11539 Otherwise, this function emulates multi-draw by recording multiple draw calls,
11540 offering no performance benefit over repeated draw() calls.
11541
11542 \note Leaving \a stride at its default is recommended whenever performance
11543 matters. With Direct 3D 12 a non-default stride prevents issuing a single
11544 native multi-draw, forcing the backend to record one command per draw
11545 instead. For a large \a drawCount this can be an order of magnitude slower,
11546 which defeats the purpose of the indirect draw. Vulkan, OpenGL, and Metal
11547 pass the stride on to their native multi-draw entry points and are not
11548 affected. Rather than interleaving custom data between the commands, keep
11549 that data in a separate buffer and index into it.
11550
11551 \note The render pass interruption and the render target consequences and
11552 limitations described for drawIndexedIndirect() apply here as well.
11553
11554 \note Therefore, portable applications should consider always using
11555 QRhiIndirectCommandBuffer and executeIndirect() instead of the
11556 draw*Indirect*() family of functions.
11557
11558 \note This function can only be called inside a render pass, meaning
11559 between a beginPass() and endPass() call.
11560
11561 \since 6.12
11562
11563 \sa drawIndexedIndirect(), drawIndirectCount(), drawIndexedIndirectCount()
11564 */
11565void QRhiCommandBuffer::drawIndirect(QRhiBuffer *indirectBuffer,
11566 quint32 indirectBufferOffset,
11567 quint32 drawCount,
11568 quint32 stride)
11569{
11570 Q_ASSERT(indirectBuffer);
11571 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
11572 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
11573 Q_ASSERT(stride >= sizeof(QRhiIndirectDrawCommand));
11574 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
11575 m_rhi->drawIndirect(this, indirectBuffer, indirectBufferOffset, drawCount, stride);
11576}
11577
11578/*!
11579 Records an indexed, indirect draw.
11580
11581 The draw parameters are provided by the buffer specified in \a indirectBuffer,
11582 which must contain an array of elements of type QRhiIndexedIndirectDrawCommand.
11583 The parameters in QRhiIndexedIndirectDrawCommand have the same meaning as in drawIndexed().
11584
11585 The offset, in bytes, from which the parameters are read in the buffer is specified
11586 by \a indirectBufferOffset.
11587
11588 \a drawCount specifies the number of such draw commands to issue.
11589
11590 \a stride indicates the byte size of each individual draw command structure
11591 in the buffer. This allows interleaving custom data between commands if needed.
11592 The value must be a multiple of 4 and greater than or equal to sizeof(QRhiIndexedIndirectDrawCommand).
11593
11594 \note A \a drawCount value greater than 1 is only natively supported if the
11595 QRhi::DrawIndirectMulti feature is reported as supported.
11596 Otherwise, this function emulates multi-draw by recording multiple draw calls,
11597 offering no performance benefit over repeated drawIndexed() calls.
11598
11599 \note Leaving \a stride at its default is recommended whenever performance
11600 matters. With Direct 3D 12 a non-default stride prevents issuing a single
11601 native multi-draw, forcing the backend to record one command per draw
11602 instead. For a large \a drawCount this can be an order of magnitude slower,
11603 which defeats the purpose of the indirect draw. Vulkan, OpenGL, and Metal
11604 pass the stride on to their native multi-draw entry points and are not
11605 affected. Rather than interleaving custom data between the commands, keep
11606 that data in a separate buffer and index into it.
11607
11608 \note With some backends a large \a drawCount is implemented by interrupting
11609 and then restarting the render pass internally due to launching a compute
11610 kernel to encode commands into an indirect command buffer. With Metal this
11611 happens above a certain \a drawCount (e.g., 128). This has consequences for
11612 the render targets: color attachment contents are preserved automatically,
11613 but a QRhiRenderBuffer serving as the depth-stencil buffer only keeps its
11614 contents if it was created with QRhiRenderBuffer::NoTransientBacking, which
11615 means that, with Metal, rendering errors may occur if the depth-stencil
11616 buffer is a QRhiRenderBuffer without the NoTransientBacking flag and the \a
11617 drawCount is above the threshold. Recording the same commands into a
11618 QRhiIndirectCommandBuffer and issuing them with executeIndirect() avoids
11619 this altogether: that never interrupts the pass.
11620
11621 \note Therefore, portable applications should consider always using
11622 QRhiIndirectCommandBuffer and executeIndirect() instead of the
11623 draw*Indirect*() family of functions.
11624
11625 \note This function can only be called inside a render pass, meaning
11626 between a beginPass() and endPass() call.
11627
11628 \since 6.12
11629
11630 \sa drawIndirect(), drawIndirectCount(), drawIndexedIndirectCount()
11631 */
11632void QRhiCommandBuffer::drawIndexedIndirect(QRhiBuffer *indirectBuffer,
11633 quint32 indirectBufferOffset,
11634 quint32 drawCount,
11635 quint32 stride)
11636{
11637 Q_ASSERT(indirectBuffer);
11638 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
11639 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
11640 Q_ASSERT(stride >= sizeof(QRhiIndexedIndirectDrawCommand));
11641 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
11642 m_rhi->drawIndexedIndirect(this, indirectBuffer, indirectBufferOffset, drawCount, stride);
11643}
11644
11645/*!
11646 Records a non-indexed, indirect draw, with the draw count itself read
11647 from a buffer at execution time.
11648
11649 Draw parameters are read from \a indirectBuffer at byte offset
11650 \a indirectBufferOffset as an array of QRhiIndirectDrawCommand entries
11651 spaced \a stride bytes apart. The number of draws issued is the 32-bit
11652 unsigned integer stored at \a countBufferOffset in \a countBuffer, clamped
11653 to \a maxDrawCount.
11654
11655 Both buffers must have QRhiBuffer::IndirectBuffer usage. Offsets must be
11656 4-byte aligned; \a stride must be 4-byte aligned and at least
11657 sizeof(QRhiIndirectDrawCommand).
11658
11659 Only available when \l QRhi::DrawIndirectCount is reported as supported.
11660 On other backends this is a no-op and a warning is logged. With Metal there
11661 are additional requirements, see QRhi::DrawIndirectCount.
11662
11663 \note Unlike with drawIndirect(), a non-default \a stride does not prevent
11664 the use of a single native multi-draw here. With Direct 3D 12 it does mean
11665 that an additional command signature is created and cached for each
11666 distinct stride value, so sticking to one stride is still preferable.
11667
11668 \note The value in \a countBuffer is read as a \e signed 32-bit integer by
11669 OpenGL, unlike the other backends. Counts above \c INT_MAX are therefore
11670 not portable, and neither is relying on any particular behavior for a count
11671 that exceeds \a maxDrawCount, beyond the clamping described above.
11672
11673 \note With some backends, Metal in particular, the render pass is always
11674 interrupted and restarted internally because the draw commands have to be
11675 encoded on the GPU. Color attachment contents are preserved automatically,
11676 but a QRhiRenderBuffer serving as the depth-stencil buffer only keeps its
11677 contents if it was created with QRhiRenderBuffer::NoTransientBacking.
11678 Building a QRhiIndirectCommandBuffer with buildIndirect(),
11679 which happens before the pass begins, and issuing it with
11680 executeIndirect() avoids this: that never interrupts the pass, and supports
11681 a device-side count just the same.
11682
11683 \note Therefore, portable applications should consider always using
11684 QRhiIndirectCommandBuffer and executeIndirect() instead of the
11685 draw*Indirect*() family of functions.
11686
11687 \note \a maxDrawCount is not a free upper bound. With Metal it sizes the
11688 indirect command buffer that the draw commands are encoded into, and that
11689 buffer is shared, grows on demand, and is never shrunk again for the
11690 lifetime of the QRhi. It also determines how many encoding threads are
11691 dispatched every time. Passing the capacity of \a indirectBuffer instead of
11692 a realistic upper bound therefore has a real cost.
11693
11694 \note Only valid inside a render pass.
11695
11696 \since 6.13
11697
11698 \sa drawIndirect(), drawIndexedIndirect(), drawIndexedIndirectCount()
11699 */
11700void QRhiCommandBuffer::drawIndirectCount(QRhiBuffer *indirectBuffer,
11701 quint32 indirectBufferOffset,
11702 QRhiBuffer *countBuffer,
11703 quint32 countBufferOffset,
11704 quint32 maxDrawCount,
11705 quint32 stride)
11706{
11707 Q_ASSERT(indirectBuffer);
11708 Q_ASSERT(countBuffer);
11709 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
11710 Q_ASSERT(countBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
11711 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
11712 Q_ASSERT_X((countBufferOffset & 3u) == 0u, Q_FUNC_INFO, "countBufferOffset must be a multiple of 4");
11713 Q_ASSERT(stride >= sizeof(QRhiIndirectDrawCommand));
11714 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
11715 m_rhi->drawIndirectCount(this, indirectBuffer, indirectBufferOffset,
11716 countBuffer, countBufferOffset, maxDrawCount, stride);
11717}
11718
11719/*!
11720 Indexed variant of drawIndirectCount(). \a indirectBuffer contains, at byte
11721 offset \a indirectBufferOffset, QRhiIndexedIndirectDrawCommand entries,
11722 spaced \a stride bytes apart, and \a stride must be at least
11723 sizeof(QRhiIndexedIndirectDrawCommand). All other requirements, including
11724 how \a countBuffer, \a countBufferOffset and \a maxDrawCount are
11725 interpreted, are as described for drawIndirectCount().
11726
11727 \note The render pass interruption described for drawIndirectCount() applies
11728 here as well.
11729
11730 \note Therefore, portable applications should consider always using
11731 QRhiIndirectCommandBuffer and executeIndirect() instead of the
11732 draw*Indirect*() family of functions.
11733
11734 \note Only valid inside a render pass.
11735
11736 \since 6.13
11737
11738 \sa drawIndirect(), drawIndexedIndirect(), drawIndirectCount()
11739 */
11740void QRhiCommandBuffer::drawIndexedIndirectCount(QRhiBuffer *indirectBuffer,
11741 quint32 indirectBufferOffset,
11742 QRhiBuffer *countBuffer,
11743 quint32 countBufferOffset,
11744 quint32 maxDrawCount,
11745 quint32 stride)
11746{
11747 Q_ASSERT(indirectBuffer);
11748 Q_ASSERT(countBuffer);
11749 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
11750 Q_ASSERT(countBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
11751 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
11752 Q_ASSERT_X((countBufferOffset & 3u) == 0u, Q_FUNC_INFO, "countBufferOffset must be a multiple of 4");
11753 Q_ASSERT(stride >= sizeof(QRhiIndexedIndirectDrawCommand));
11754 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
11755 m_rhi->drawIndexedIndirectCount(this, indirectBuffer, indirectBufferOffset,
11756 countBuffer, countBufferOffset, maxDrawCount, stride);
11757}
11758
11759/*!
11760 Records populating the indirect command buffer \a icb from the buffer and
11761 parameters described by \a info.
11762
11763 This is the GPU-driven counterpart of recording draw() or drawIndexed()
11764 calls on the QRhiIndirectCommandBuffer: the commands come from
11765 \c{info.sourceBuffer}, which is typically written by a compute shader
11766 earlier in the frame. Any commands recorded on the CPU side are ignored
11767 from this point on.
11768
11769 \c{info.topology} and, for an indirect command buffer of type
11770 QRhiIndirectCommandBuffer::IndexedDraws, \c{info.indexBuffer} have to be
11771 specified because some backends need them in order to build their native
11772 indirect command buffer object, and neither is available outside of a
11773 render pass. They must match what is set on the command buffer when
11774 executeIndirect() is called.
11775
11776 \c{info.commandCount} is the number of commands to take from
11777 \c{info.sourceBuffer}, and becomes what
11778 QRhiIndirectCommandBuffer::commandCount() reports from here on. Leaving it
11779 at 0 means \a{icb}'s QRhiIndirectCommandBuffer::maxCommandCount(); a larger
11780 value is clamped to that, with a warning. The size of
11781 \c{info.sourceBuffer} is not consulted. When \c{info.countBuffer} is set,
11782 \c{info.commandCount} becomes an upper bound instead, with the device-side
11783 count deciding how many commands are executed.
11784
11785 \note This function must be called outside of any pass. That is the entire
11786 point: it gives backends that need to run a compute shader in order to
11787 build their native indirect command buffer a place to do so without having
11788 to interrupt and restart the render pass.
11789
11790 \sa executeIndirect(), QRhiIndirectCommandBuffer
11791 */
11792void QRhiCommandBuffer::buildIndirect(QRhiIndirectCommandBuffer *icb,
11793 const QRhiIndirectCommandBufferBuildInfo &info)
11794{
11795 Q_ASSERT(icb);
11796 Q_ASSERT(info.sourceBuffer);
11797 Q_ASSERT(info.sourceBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
11798 Q_ASSERT_X((info.sourceBufferOffset & 3u) == 0u, Q_FUNC_INFO,
11799 "sourceBufferOffset must be a multiple of 4");
11800 Q_ASSERT_X((info.stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
11801 Q_ASSERT(!info.countBuffer || info.countBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
11802 Q_ASSERT_X((info.countBufferOffset & 3u) == 0u, Q_FUNC_INFO,
11803 "countBufferOffset must be a multiple of 4");
11804 m_rhi->buildIndirect(this, icb, info);
11805}
11806
11807/*!
11808 Records executing the commands held by the indirect command buffer \a icb,
11809 starting at \a firstCommand and executing at most \a commandCount of them.
11810 By default all commands are executed.
11811
11812 Everything else - the graphics pipeline, the vertex and index buffers, the
11813 shader resources, the viewport, the scissor - is taken from the current
11814 state of the command buffer, exactly like with drawIndirect().
11815
11816 The number of draws issued is \c{qMin(commandCount, icb->commandCount() -
11817 firstCommand)}, so leaving \a commandCount at its default executes
11818 everything from \a firstCommand onwards. What
11819 QRhiIndirectCommandBuffer::commandCount() means depends on how \a icb was
11820 populated: it is the number of draw() and drawIndexed() calls recorded on
11821 it, or, after a buildIndirect(), the count resolved from
11822 QRhiIndirectCommandBufferBuildInfo::commandCount. Nothing is drawn when \a
11823 firstCommand is at or past that count.
11824
11825 When \a icb was populated by recording draw() or drawIndexed() calls on it,
11826 the recorded contents must have been flushed with
11827 QRhiResourceUpdateBatch::commitIndirectCommandBuffer() beforehand. When it
11828 was populated with buildIndirect(), and a count buffer was specified there,
11829 the device-side count reduces the number of draws further: the number
11830 actually executed is the smallest of that, \a commandCount, and what is
11831 left in \a icb after \a firstCommand.
11832
11833 \warning With a count buffer some backends, Metal in particular, cannot combine
11834 the device-side count with a subrange. \a firstCommand and \a commandCount
11835 are then ignored, printing a warning, and all commands up to the device-side
11836 count are executed.
11837
11838 \note An indirect command buffer that was populated by recording draw() or
11839 drawIndexed() calls on it can be executed any number of times, but within
11840 one frame all those executions must use the same topology, index buffer,
11841 index buffer offset and index format: some backends bake these into their
11842 native indirect command buffer at the first executeIndirect() of the frame.
11843 A mismatch is reported with a warning, and handled by falling back to
11844 ordinary draw calls.
11845
11846 \note Unlike drawIndirect(), drawIndexedIndirect(), drawIndirectCount() and
11847 drawIndexedIndirectCount(), this never causes the render pass to be
11848 interrupted and restarted internally, whatever the number of commands.
11849 Commands built with buildIndirect() were prepared before the pass began, and
11850 CPU-recorded ones need no compute work to encode. The consequences described
11851 for those functions therefore do not apply here. Color attachment contents
11852 are not at risk, and a QRhiRenderBuffer serving as the depth-stencil buffer
11853 keeps its contents without needing QRhiRenderBuffer::NoTransientBacking.
11854
11855 \note The CPU cost of this call is not constant for a CPU-recorded indirect
11856 command buffer. When the recorded contents changed since the last execution,
11857 some backends do their per-command native encoding here rather than in
11858 QRhiResourceUpdateBatch::commitIndirectCommandBuffer(), which for a large
11859 command set re-recorded every frame can dominate the time spent between
11860 beginPass() and endPass(). See \l QRhiIndirectCommandBuffer for how the cost
11861 of CPU recording scales.
11862
11863 \note This function can only be called inside a render pass.
11864
11865 \sa buildIndirect(), drawIndirect(), QRhiIndirectCommandBuffer
11866 */
11867void QRhiCommandBuffer::executeIndirect(QRhiIndirectCommandBuffer *icb,
11868 quint32 firstCommand,
11869 quint32 commandCount)
11870{
11871 Q_ASSERT(icb);
11872 m_rhi->executeIndirect(this, icb, firstCommand, commandCount);
11873}
11874
11875/*!
11876 Records a named debug group on the command buffer with the specified \a
11877 name. This is shown in graphics debugging tools such as
11878 \l{https://renderdoc.org/}{RenderDoc} and
11879 \l{https://developer.apple.com/xcode/}{XCode}. The end of the grouping is
11880 indicated by debugMarkEnd().
11881
11882 \note Ignored when QRhi::DebugMarkers are not supported or
11883 QRhi::EnableDebugMarkers is not set.
11884
11885 \note Can be called anywhere within the frame, both inside and outside of passes.
11886 */
11887void QRhiCommandBuffer::debugMarkBegin(const QByteArray &name)
11888{
11889 m_rhi->debugMarkBegin(this, name);
11890}
11891
11892/*!
11893 Records the end of a debug group.
11894
11895 \note Ignored when QRhi::DebugMarkers are not supported or
11896 QRhi::EnableDebugMarkers is not set.
11897
11898 \note Can be called anywhere within the frame, both inside and outside of passes.
11899 */
11900void QRhiCommandBuffer::debugMarkEnd()
11901{
11902 m_rhi->debugMarkEnd(this);
11903}
11904
11905/*!
11906 Inserts a debug message \a msg into the command stream.
11907
11908 \note Ignored when QRhi::DebugMarkers are not supported or
11909 QRhi::EnableDebugMarkers is not set.
11910
11911 \note With some backends debugMarkMsg() is only supported inside a pass and
11912 is ignored when called outside a pass. With others it is recorded anywhere
11913 within the frame.
11914 */
11915void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)
11916{
11917 m_rhi->debugMarkMsg(this, msg);
11918}
11919
11920/*!
11921 Records starting a new compute pass.
11922
11923 \a resourceUpdates, when not null, specifies a resource update batch that
11924 is to be committed and then released.
11925
11926 \note Do not assume that any state or resource bindings persist between
11927 passes.
11928
11929 \note A compute pass can record setComputePipeline(), setShaderResources(),
11930 and dispatch() calls, not graphics ones. General functionality, such as,
11931 debug markers and beginExternal() is available both in render and compute
11932 passes.
11933
11934 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
11935 is reported as supported.
11936
11937 \a flags is not currently used.
11938 */
11939void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates, BeginPassFlags flags)
11940{
11941 m_rhi->beginComputePass(this, resourceUpdates, flags);
11942}
11943
11944/*!
11945 Records ending the current compute pass.
11946
11947 \a resourceUpdates, when not null, specifies a resource update batch that
11948 is to be committed and then released.
11949 */
11950void QRhiCommandBuffer::endComputePass(QRhiResourceUpdateBatch *resourceUpdates)
11951{
11952 m_rhi->endComputePass(this, resourceUpdates);
11953}
11954
11955/*!
11956 Records setting a new compute pipeline \a ps.
11957
11958 \note This function must be called before recording setShaderResources() or
11959 dispatch() commands on the command buffer.
11960
11961 \note QRhi will optimize out unnecessary invocations within a pass, so
11962 therefore overoptimizing to avoid calls to this function is not necessary
11963 on the applications' side.
11964
11965 \note This function can only be called inside a compute pass, meaning
11966 between a beginComputePass() and endComputePass() call.
11967 */
11968void QRhiCommandBuffer::setComputePipeline(QRhiComputePipeline *ps)
11969{
11970 m_rhi->setComputePipeline(this, ps);
11971}
11972
11973/*!
11974 Records dispatching compute work items, with \a x, \a y, and \a z
11975 specifying the number of local workgroups in the corresponding dimension.
11976
11977 \note This function can only be called inside a compute pass, meaning
11978 between a beginComputePass() and endComputePass() call.
11979
11980 \note \a x, \a y, and \a z must fit the limits from the underlying graphics
11981 API implementation at run time. The maximum values are typically 65535.
11982
11983 \note Watch out for possible limits on the local workgroup size as well.
11984 This is specified in the shader, for example: \c{layout(local_size_x = 16,
11985 local_size_y = 16) in;}. For example, with OpenGL the minimum value mandated
11986 by the specification for the number of invocations in a single local work
11987 group (the product of \c local_size_x, \c local_size_y, and \c local_size_z)
11988 is 1024, while with OpenGL ES (3.1) the value may be as low as 128. This
11989 means that the example given above may be rejected by some OpenGL ES
11990 implementations as the number of invocations is 256.
11991 */
11992void QRhiCommandBuffer::dispatch(int x, int y, int z)
11993{
11994 m_rhi->dispatch(this, x, y, z);
11995}
11996
11997/*!
11998 Records an indirect compute dispatch.
11999
12000 The work group counts are read by the device from \a indirectBuffer at
12001 \a indirectBufferOffset, as a single QRhiDispatchIndirectCommand.
12002 \a indirectBuffer must have QRhiBuffer::IndirectBuffer usage and
12003 \a indirectBufferOffset must be 4-byte aligned.
12004
12005 Only one dispatch per call; no native multi-dispatch variant exists.
12006 Requires \l QRhi::DispatchIndirect.
12007
12008 \note Only valid inside a compute pass.
12009
12010 \since 6.13
12011 */
12012void QRhiCommandBuffer::dispatchIndirect(QRhiBuffer *indirectBuffer,
12013 quint32 indirectBufferOffset)
12014{
12015 Q_ASSERT(indirectBuffer);
12016 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12017 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12018 m_rhi->dispatchIndirect(this, indirectBuffer, indirectBufferOffset);
12019}
12020
12021/*!
12022 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
12023 QRhiVulkanCommandBufferNativeHandles. The returned value is \nullptr when
12024 exposing the underlying native resources is not supported by, or not
12025 applicable to, the backend.
12026
12027 \sa QRhiVulkanCommandBufferNativeHandles,
12028 QRhiMetalCommandBufferNativeHandles, beginExternal(), endExternal()
12029 */
12030const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
12031{
12032 return m_rhi->nativeHandles(this);
12033}
12034
12035/*!
12036 To be called when the application before the application is about to
12037 enqueue commands to the current pass' command buffer by calling graphics
12038 API functions directly.
12039
12040 \note This is only available when the intent was declared upfront in
12041 beginPass() or beginComputePass(). Therefore this function must only be
12042 called when the pass recording was started with specifying
12043 QRhiCommandBuffer::ExternalContent.
12044
12045 With Vulkan, Metal, or Direct3D 12 one can query the native command buffer
12046 or encoder objects via nativeHandles() and enqueue commands to them. With
12047 OpenGL or Direct3D 11 the (device) context can be retrieved from
12048 QRhi::nativeHandles(). However, this must never be done without ensuring
12049 the QRhiCommandBuffer's state stays up-to-date. Hence the requirement for
12050 wrapping any externally added command recording between beginExternal() and
12051 endExternal(). Conceptually this is the same as QPainter's
12052 \l{QPainter::beginNativePainting()}{beginNativePainting()} and
12053 \l{QPainter::endNativePainting()}{endNativePainting()} functions.
12054
12055 For OpenGL in particular, this function has an additional task: it makes
12056 sure the context is made current on the current thread.
12057
12058 \note Once beginExternal() is called, no other render pass specific
12059 functions (\c set* or \c draw*) must be called on the
12060 QRhiCommandBuffer until endExternal().
12061
12062 \warning Some backends may return a native command buffer object from
12063 QRhiCommandBuffer::nativeHandles() that is different from the primary one
12064 when inside a beginExternal() - endExternal() block. Therefore it is
12065 important to (re)query the native command buffer object after calling
12066 beginExternal(). In practical terms this means that with Vulkan for example
12067 the externally recorded Vulkan commands are placed onto a secondary command
12068 buffer (with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT).
12069 nativeHandles() returns this secondary command buffer when called between
12070 begin/endExternal.
12071
12072 \sa endExternal(), nativeHandles()
12073 */
12074void QRhiCommandBuffer::beginExternal()
12075{
12076 m_rhi->beginExternal(this);
12077}
12078
12079/*!
12080 To be called once the externally added commands are recorded to the command
12081 buffer or context.
12082
12083 \note All QRhiCommandBuffer state must be assumed as invalid after calling
12084 this function. Pipelines, vertex and index buffers, and other state must be
12085 set again if more draw calls are recorded after the external commands.
12086
12087 \sa beginExternal(), nativeHandles()
12088 */
12089void QRhiCommandBuffer::endExternal()
12090{
12091 m_rhi->endExternal(this);
12092}
12093
12094/*!
12095 \return the last available timestamp, in seconds, when
12096 \l QRhi::EnableTimestamps was enabled when creating the QRhi. The value
12097 indicates the elapsed time on the GPU during the last completed frame.
12098
12099 \note Do not expect results other than 0 when the QRhi::Timestamps feature
12100 is not reported as supported, or when QRhi::EnableTimestamps was not passed
12101 to QRhi::create(). There are exceptions to this, because with some graphics
12102 APIs (Metal) timings are available without having to perform extra
12103 operations (timestamp queries), but portable applications should always
12104 consciously opt-in to timestamp collection when they know it is needed, and
12105 call this function accordingly.
12106
12107 Care must be exercised with the interpretation of the value, as its
12108 precision and granularity is often not controlled by Qt, and depends on the
12109 underlying graphics API and its implementation. In particular, comparing
12110 the values between different graphics APIs and hardware is discouraged and
12111 may be meaningless.
12112
12113 The timing values will likely become available asynchronously. The returned
12114 value may therefore be 0 (e.g., for the first 1-2 frames) or the last known
12115 value referring to some previous frame. The value my also become 0 again
12116 under certain conditions, such as when resizing the window. It can be
12117 expected that the most up-to-date available value is retrieved in
12118 beginFrame() and becomes queriable via this function once beginFrame()
12119 returns.
12120
12121 \note Do not assume that the value refers to the previous
12122 (\c{currently_recorded - 1}) frame. It may refer to \c{currently_recorded -
12123 2} or \c{currently_recorded - 3} as well. The exact behavior may depend on
12124 the graphics API and its implementation.
12125
12126 Watch out for the consequences of GPU frequency scaling and GPU clock
12127 changes, depending on the platform. For example, on Windows the returned
12128 timing may vary in a quite wide range between frames with modern graphics
12129 cards, even when submitting frames with a similar, or the same workload.
12130 This is out of scope for Qt to control and solve, generally speaking.
12131 However, the D3D12 backend automatically calls
12132 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-setstablepowerstate}{ID3D12Device::SetStablePowerState()}
12133 whenever the environment variable \c QT_D3D_STABLE_POWER_STATE is set to a
12134 non-zero value. This can greatly stabilize the result. It can also have a
12135 non-insignificant effect on the CPU-side timings measured via QElapsedTimer
12136 for example, especially when offscreen frames are involved.
12137
12138 \note Do not and never ship applications to production with
12139 \c QT_D3D_STABLE_POWER_STATE set. See the Windows API documentation for details.
12140
12141 \sa QRhi::Timestamps, QRhi::EnableTimestamps
12142 */
12143double QRhiCommandBuffer::lastCompletedGpuTime()
12144{
12145 return m_rhi->lastCompletedGpuTime(this);
12146}
12147
12148/*!
12149 \return the value (typically an offset) \a v aligned to the uniform buffer
12150 alignment given by ubufAlignment().
12151 */
12152int QRhi::ubufAligned(int v) const
12153{
12154 const int byteAlign = ubufAlignment();
12155 return (v + byteAlign - 1) & ~(byteAlign - 1);
12156}
12157
12158/*!
12159 \return the number of mip levels for a given \a size.
12160 */
12161int QRhi::mipLevelsForSize(const QSize &size)
12162{
12163 return qFloor(std::log2(qMax(size.width(), size.height()))) + 1;
12164}
12165
12166/*!
12167 \return the texture image size for a given \a mipLevel, calculated based on
12168 the level 0 size given in \a baseLevelSize.
12169 */
12170QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)
12171{
12172 const int w = qMax(1, baseLevelSize.width() >> mipLevel);
12173 const int h = qMax(1, baseLevelSize.height() >> mipLevel);
12174 return QSize(w, h);
12175}
12176
12177/*!
12178 \return \c true if the underlying graphics API has the Y axis pointing up
12179 in framebuffers and images.
12180
12181 In practice this is \c true for OpenGL only.
12182 */
12183bool QRhi::isYUpInFramebuffer() const
12184{
12185 return d->isYUpInFramebuffer();
12186}
12187
12188/*!
12189 \return \c true if the underlying graphics API has the Y axis pointing up
12190 in its normalized device coordinate system.
12191
12192 In practice this is \c false for Vulkan only.
12193
12194 \note clipSpaceCorrMatrix() includes the corresponding adjustment (to make
12195 Y point up) in its returned matrix.
12196 */
12197bool QRhi::isYUpInNDC() const
12198{
12199 return d->isYUpInNDC();
12200}
12201
12202/*!
12203 \return \c true if the underlying graphics API uses depth range [0, 1] in
12204 clip space.
12205
12206 In practice this is \c false for OpenGL only, because OpenGL uses a
12207 post-projection depth range of [-1, 1]. (not to be confused with the
12208 NDC-to-window mapping controlled by glDepthRange(), which uses a range of
12209 [0, 1], unless overridden by the QRhiViewport) In some OpenGL versions
12210 glClipControl() could be used to change this, but the OpenGL backend of
12211 QRhi does not use that function as it is not available in OpenGL ES or
12212 OpenGL versions lower than 4.5.
12213
12214 \note clipSpaceCorrMatrix() includes the corresponding adjustment in its
12215 returned matrix. Therefore, many users of QRhi do not need to take any
12216 further measures apart from pre-multiplying their projection matrices with
12217 clipSpaceCorrMatrix(). However, some graphics techniques, such as, some
12218 types of shadow mapping, involve working with and outputting depth values
12219 in the shaders. These will need to query and take the value of this
12220 function into account as appropriate.
12221 */
12222bool QRhi::isClipDepthZeroToOne() const
12223{
12224 return d->isClipDepthZeroToOne();
12225}
12226
12227/*!
12228 \return a matrix that can be used to allow applications keep using
12229 OpenGL-targeted vertex data and perspective projection matrices (such as,
12230 the ones generated by QMatrix4x4::perspective()), regardless of the active
12231 QRhi backend.
12232
12233 In a typical renderer, once \c{this_matrix * mvp} is used instead of just
12234 \c mvp, vertex data with Y up and viewports with depth range 0 - 1 can be
12235 used without considering what backend (and so graphics API) is going to be
12236 used at run time. This way branching based on isYUpInNDC() and
12237 isClipDepthZeroToOne() can be avoided (although such logic may still become
12238 required when implementing certain advanced graphics techniques).
12239
12240 See
12241 \l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this
12242 page} for a discussion of the topic from Vulkan perspective.
12243 */
12244QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
12245{
12246 return d->clipSpaceCorrMatrix();
12247}
12248
12249/*!
12250 \return \c true if the specified texture \a format modified by \a flags is
12251 supported.
12252
12253 The query is supported both for uncompressed and compressed formats.
12254 */
12255bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
12256{
12257 return d->isTextureFormatSupported(format, flags);
12258}
12259
12260/*!
12261 \return \c true if the specified \a feature is supported
12262 */
12263bool QRhi::isFeatureSupported(QRhi::Feature feature) const
12264{
12265 return d->isFeatureSupported(feature);
12266}
12267
12268/*!
12269 \return the value for the specified resource \a limit.
12270
12271 The values are expected to be queried by the backends upon initialization,
12272 meaning calling this function is a light operation.
12273 */
12274int QRhi::resourceLimit(ResourceLimit limit) const
12275{
12276 return d->resourceLimit(limit);
12277}
12278
12279/*!
12280 \return a pointer to the backend-specific collection of native objects
12281 for the device, context, and similar concepts used by the backend.
12282
12283 Cast to QRhiVulkanNativeHandles, QRhiD3D11NativeHandles,
12284 QRhiD3D12NativeHandles, QRhiGles2NativeHandles, or QRhiMetalNativeHandles
12285 as appropriate.
12286
12287 \note No ownership is transferred, neither for the returned pointer nor for
12288 any native objects.
12289 */
12290const QRhiNativeHandles *QRhi::nativeHandles()
12291{
12292 return d->nativeHandles();
12293}
12294
12295/*!
12296 With OpenGL this makes the OpenGL context current on the current thread.
12297 The function has no effect with other backends.
12298
12299 Calling this function is relevant typically in Qt framework code, when one
12300 has to ensure external OpenGL code provided by the application can still
12301 run like it did before with direct usage of OpenGL, as long as the QRhi is
12302 using the OpenGL backend.
12303
12304 \return false when failed, similarly to QOpenGLContext::makeCurrent(). When
12305 the operation failed, isDeviceLost() can be called to determine if there
12306 was a loss of context situation. Such a check is equivalent to checking via
12307 QOpenGLContext::isValid().
12308
12309 \sa QOpenGLContext::makeCurrent(), QOpenGLContext::isValid()
12310 */
12311bool QRhi::makeThreadLocalNativeContextCurrent()
12312{
12313 return d->makeThreadLocalNativeContextCurrent();
12314}
12315
12316/*!
12317 With backends and graphics APIs where applicable, this function allows to
12318 provide additional arguments to the \b next submission of commands to the
12319 graphics command queue.
12320
12321 In particular, with Vulkan this allows passing in a list of Vulkan semaphore
12322 objects for \c vkQueueSubmit() to signal and wait on. \a params must then be
12323 a \l QRhiVulkanQueueSubmitParams. This becomes essential in certain advanced
12324 use cases, such as when performing native Vulkan calls that involve having
12325 to wait on and signal VkSemaphores that the application's custom Vulkan
12326 rendering or compute code manages. In addition, this also allows specifying
12327 additional semaphores to wait on in the next \c vkQueuePresentKHR().
12328
12329 \note This function affects the next queue submission only, which will
12330 happen in endFrame(), endOffscreenFrame(), or finish(). The enqueuing of
12331 present happens in endFrame().
12332
12333 With many other backends the implementation of this function is a no-op.
12334
12335 \since 6.9
12336 */
12337void QRhi::setQueueSubmitParams(QRhiNativeHandles *params)
12338{
12339 d->setQueueSubmitParams(params);
12340}
12341
12342/*!
12343 Attempts to release resources in the backend's caches. This can include both
12344 CPU and GPU resources. Only memory and resources that can be recreated
12345 automatically are in scope. As an example, if the backend's
12346 QRhiGraphicsPipeline implementation maintains a cache of shader compilation
12347 results, calling this function leads to emptying that cache, thus
12348 potentially freeing up memory and graphics resources.
12349
12350 Calling this function makes sense in resource constrained environments,
12351 where at a certain point there is a need to ensure minimal resource usage,
12352 at the expense of performance.
12353 */
12354void QRhi::releaseCachedResources()
12355{
12356 d->releaseCachedResources();
12357
12358 for (QRhiResourceUpdateBatch *u : d->resUpdPool) {
12359 if (u->d->poolIndex < 0)
12360 u->d->trimOpLists();
12361 }
12362}
12363
12364/*!
12365 \return true if the graphics device was lost.
12366
12367 The loss of the device is typically detected in beginFrame(), endFrame() or
12368 QRhiSwapChain::createOrResize(), depending on the backend and the underlying
12369 native APIs. The most common is endFrame() because that is where presenting
12370 happens. With some backends QRhiSwapChain::createOrResize() can also fail
12371 due to a device loss. Therefore this function is provided as a generic way
12372 to check if a device loss was detected by a previous operation.
12373
12374 When the device is lost, no further operations should be done via the QRhi.
12375 Rather, all QRhi resources should be released, followed by destroying the
12376 QRhi. A new QRhi can then be attempted to be created. If successful, all
12377 graphics resources must be reinitialized. If not, try again later,
12378 repeatedly.
12379
12380 While simple applications may decide to not care about device loss,
12381 on the commonly used desktop platforms a device loss can happen
12382 due to a variety of reasons, including physically disconnecting the
12383 graphics adapter, disabling the device or driver, uninstalling or upgrading
12384 the graphics driver, or due to errors that lead to a graphics device reset.
12385 Some of these can happen under perfectly normal circumstances as well, for
12386 example the upgrade of the graphics driver to a newer version is a common
12387 task that can happen at any time while a Qt application is running. Users
12388 may very well expect applications to be able to survive this, even when the
12389 application is actively using an API like OpenGL or Direct3D.
12390
12391 Qt's own frameworks built on top of QRhi, such as, Qt Quick, can be
12392 expected to handle and take appropriate measures when a device loss occurs.
12393 If the data for graphics resources, such as textures and buffers, are still
12394 available on the CPU side, such an event may not be noticeable on the
12395 application level at all since graphics resources can seamlessly be
12396 reinitialized then. However, applications and libraries working directly
12397 with QRhi are expected to be prepared to check and handle device loss
12398 situations themselves.
12399
12400 \note With OpenGL, applications may need to opt-in to context reset
12401 notifications by setting QSurfaceFormat::ResetNotification on the
12402 QOpenGLContext. This is typically done by enabling the flag in
12403 QRhiGles2InitParams::format. Keep in mind however that some systems may
12404 generate context resets situations even when this flag is not set.
12405 */
12406bool QRhi::isDeviceLost() const
12407{
12408 return d->isDeviceLost();
12409}
12410
12411/*!
12412 \return a binary data blob with data collected from the
12413 QRhiGraphicsPipeline and QRhiComputePipeline successfully created during
12414 the lifetime of this QRhi.
12415
12416 By saving and then, in subsequent runs of the same application, reloading
12417 the cache data, pipeline and shader creation times can potentially be
12418 reduced. What exactly the cache and its serialized version includes is not
12419 specified, is always specific to the backend used, and in some cases also
12420 dependent on the particular implementation of the graphics API.
12421
12422 When the PipelineCacheDataLoadSave is reported as unsupported, the returned
12423 QByteArray is empty.
12424
12425 When the EnablePipelineCacheDataSave flag was not specified when calling
12426 create(), the returned QByteArray may be empty, even when the
12427 PipelineCacheDataLoadSave feature is supported.
12428
12429 When the returned data is non-empty, it is always specific to the Qt
12430 version and QRhi backend. In addition, in some cases there is a strong
12431 dependency to the graphics device and the exact driver version used. QRhi
12432 takes care of adding the appropriate header and safeguards that ensure that
12433 the data can always be passed safely to setPipelineCacheData(), therefore
12434 attempting to load data from a run on another version of a driver will be
12435 handled safely and gracefully.
12436
12437 \note Calling releaseCachedResources() may, depending on the backend, clear
12438 the pipeline data collected. A subsequent call to this function may then
12439 not return any data.
12440
12441 See EnablePipelineCacheDataSave for further details about this feature.
12442
12443 \note Minimize the number of calls to this function. Retrieving the blob is
12444 not always a cheap operation, and therefore this function should only be
12445 called at a low frequency, ideally only once e.g. when closing the
12446 application.
12447
12448 \sa setPipelineCacheData(), create(), isFeatureSupported()
12449 */
12450QByteArray QRhi::pipelineCacheData()
12451{
12452 return d->pipelineCacheData();
12453}
12454
12455/*!
12456 Loads \a data into the pipeline cache, when applicable.
12457
12458 When the PipelineCacheDataLoadSave is reported as unsupported, the function
12459 is safe to call, but has no effect.
12460
12461 The blob returned by pipelineCacheData() is always specific to the Qt
12462 version, the QRhi backend, and, in some cases, also to the graphics device,
12463 and a given version of the graphics driver. QRhi takes care of adding the
12464 appropriate header and safeguards that ensure that the data can always be
12465 passed safely to this function. If there is a mismatch, e.g. because the
12466 driver has been upgraded to a newer version, or because the data was
12467 generated from a different QRhi backend, a warning is printed and \a data
12468 is safely ignored.
12469
12470 With Vulkan, this maps directly to VkPipelineCache. Calling this function
12471 creates a new Vulkan pipeline cache object, with its initial data sourced
12472 from \a data. The pipeline cache object is then used by all subsequently
12473 created QRhiGraphicsPipeline and QRhiComputePipeline objects, thus
12474 accelerating, potentially, the pipeline creation.
12475
12476 With other APIs there is no real pipeline cache, but they may provide a
12477 cache with bytecode from shader compilations (D3D) or program binaries
12478 (OpenGL). In applications that perform a lot of shader compilation from
12479 source at run time this can provide a significant boost in subsequent runs
12480 if the "pipeline cache" is pre-seeded from an earlier run using this
12481 function.
12482
12483 \note QRhi cannot give any guarantees that \a data has an effect on the
12484 pipeline and shader creation performance. With APIs like Vulkan, it is up
12485 to the driver to decide if \a data is used for some purpose, or if it is
12486 ignored.
12487
12488 See EnablePipelineCacheDataSave for further details about this feature.
12489
12490 \note This mechanism offered by QRhi is independent of the drivers' own
12491 internal caching mechanism, if any. This means that, depending on the
12492 graphics API and its implementation, the exact effects of retrieving and
12493 then reloading \a data are not predictable. Improved performance may not be
12494 visible at all in case other caching mechanisms outside of Qt's control are
12495 already active.
12496
12497 \note Minimize the number of calls to this function. Loading the blob is
12498 not always a cheap operation, and therefore this function should only be
12499 called at a low frequency, ideally only once e.g. when starting the
12500 application.
12501
12502 \warning Serialized pipeline cache data is assumed to be trusted content. Qt
12503 performs robust parsing of the header and metadata included in \a data,
12504 application developers are however advised to never pass in data from
12505 untrusted sources.
12506
12507 \sa pipelineCacheData(), isFeatureSupported()
12508 */
12509void QRhi::setPipelineCacheData(const QByteArray &data)
12510{
12511 d->setPipelineCacheData(data);
12512}
12513
12514/*!
12515 \struct QRhiStats
12516 \inmodule QtGuiPrivate
12517 \inheaderfile rhi/qrhi.h
12518 \since 6.6
12519
12520 \brief Statistics provided from the underlying memory allocator.
12521
12522 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
12523 for details.
12524 */
12525
12526/*!
12527 \variable QRhiStats::totalPipelineCreationTime
12528
12529 The total time in milliseconds spent in graphics and compute pipeline
12530 creation, which usually involves shader compilation or cache lookups, and
12531 potentially expensive processing.
12532
12533 \note The value should not be compared between different backends since the
12534 concept of "pipelines" and what exactly happens under the hood during, for
12535 instance, a call to QRhiGraphicsPipeline::create(), differ greatly between
12536 graphics APIs and their implementations.
12537
12538 \sa QRhi::statistics()
12539*/
12540
12541/*!
12542 \variable QRhiStats::blockCount
12543
12544 Statistic reported from the Vulkan or D3D12 memory allocator.
12545
12546 \sa QRhi::statistics()
12547*/
12548
12549/*!
12550 \variable QRhiStats::allocCount
12551
12552 Statistic reported from the Vulkan or D3D12 memory allocator.
12553
12554 \sa QRhi::statistics()
12555*/
12556
12557/*!
12558 \variable QRhiStats::usedBytes
12559
12560 Statistic reported from the Vulkan or D3D12 memory allocator.
12561
12562 \sa QRhi::statistics()
12563*/
12564
12565/*!
12566 \variable QRhiStats::unusedBytes
12567
12568 Statistic reported from the Vulkan or D3D12 memory allocator.
12569
12570 \sa QRhi::statistics()
12571*/
12572
12573/*!
12574 \variable QRhiStats::totalUsageBytes
12575
12576 Valid only with D3D12 currently. Matches IDXGIAdapter3::QueryVideoMemoryInfo().
12577
12578 \sa QRhi::statistics()
12579*/
12580
12581#ifndef QT_NO_DEBUG_STREAM
12582QDebug operator<<(QDebug dbg, const QRhiStats &info)
12583{
12584 QDebugStateSaver saver(dbg);
12585 dbg.nospace() << "QRhiStats("
12586 << "totalPipelineCreationTime=" << info.totalPipelineCreationTime
12587 << " blockCount=" << info.blockCount
12588 << " allocCount=" << info.allocCount
12589 << " usedBytes=" << info.usedBytes
12590 << " unusedBytes=" << info.unusedBytes
12591 << " totalUsageBytes=" << info.totalUsageBytes
12592 << ')';
12593 return dbg;
12594}
12595#endif
12596
12597/*!
12598 Gathers and returns statistics about the timings and allocations of
12599 graphics resources.
12600
12601 Data about memory allocations is only available with some backends, where
12602 such operations are under Qt's control. With graphics APIs where there is
12603 no lower level control over resource memory allocations, this will never be
12604 supported and all relevant fields in the results are 0.
12605
12606 With Vulkan in particular, the values are valid always, and are queried
12607 from the underlying memory allocator library. This gives an insight into
12608 the memory requirements of the active buffers and textures.
12609
12610 The same is true for Direct 3D 12. In addition to the memory allocator
12611 library's statistics, here the result also includes a \c totalUsageBytes
12612 field which reports the total size including additional resources that are
12613 not under the memory allocator library's control (swapchain buffers,
12614 descriptor heaps, etc.), as reported by DXGI.
12615
12616 The values correspond to all types of memory used, combined. (i.e. video +
12617 system in case of a discreet GPU)
12618
12619 Additional data, such as the total time in milliseconds spent in graphics
12620 and compute pipeline creation (which usually involves shader compilation or
12621 cache lookups, and potentially expensive processing) is available with most
12622 backends.
12623
12624 \note The elapsed times for operations such as pipeline creation may be
12625 affected by various factors. The results should not be compared between
12626 different backends since the concept of "pipelines" and what exactly
12627 happens under the hood during, for instance, a call to
12628 QRhiGraphicsPipeline::create(), differ greatly between graphics APIs and
12629 their implementations.
12630
12631 \note Additionally, many drivers will likely employ various caching
12632 strategies for shaders, programs, pipelines. (independently of Qt's own
12633 similar facilities, such as setPipelineCacheData() or the OpenGL-specific
12634 program binary disk cache). Because such internal behavior is transparent
12635 to the API client, Qt and QRhi have no knowledge or control over the exact
12636 caching strategy, persistency, invalidation of the cached data, etc. When
12637 reading timings, such as the time spent on pipeline creation, the potential
12638 presence and unspecified behavior of driver-level caching mechanisms should
12639 be kept in mind.
12640 */
12641QRhiStats QRhi::statistics() const
12642{
12643 return d->statistics();
12644}
12645
12646/*!
12647 \return a new graphics pipeline resource.
12648
12649 \sa QRhiResource::destroy()
12650 */
12651QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
12652{
12653 return d->createGraphicsPipeline();
12654}
12655
12656/*!
12657 \return a new compute pipeline resource.
12658
12659 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
12660 is reported as supported.
12661
12662 \sa QRhiResource::destroy()
12663 */
12664QRhiComputePipeline *QRhi::newComputePipeline()
12665{
12666 return d->createComputePipeline();
12667}
12668
12669/*!
12670 \return a new shader resource binding collection resource.
12671
12672 \sa QRhiResource::destroy()
12673 */
12674QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
12675{
12676 return d->createShaderResourceBindings();
12677}
12678
12679/*!
12680 \return a new buffer with the specified \a type, \a usage, and \a size.
12681
12682 \note Some \a usage and \a type combinations may not be supported by all
12683 backends. See \l{QRhiBuffer::UsageFlag}{UsageFlags} and
12684 \l{QRhi::NonDynamicUniformBuffers}{the feature flags}.
12685
12686 \note Backends may choose to allocate buffers bigger than \a size. This is
12687 done transparently to applications, so there are no special restrictions on
12688 the value of \a size. QRhiBuffer::size() will always report back the value
12689 that was requested in \a size.
12690
12691 \sa QRhiResource::destroy()
12692 */
12693QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type,
12694 QRhiBuffer::UsageFlags usage,
12695 quint32 size)
12696{
12697 return d->createBuffer(type, usage, size);
12698}
12699
12700/*!
12701 \return a new renderbuffer with the specified \a type, \a pixelSize, \a
12702 sampleCount, and \a flags.
12703
12704 When \a backingFormatHint is set to a texture format other than
12705 QRhiTexture::UnknownFormat, it may be used by the backend to decide what
12706 format to use for the storage backing the renderbuffer.
12707
12708 \note \a backingFormatHint becomes relevant typically when multisampling
12709 and floating point texture formats are involved: rendering into a
12710 multisample QRhiRenderBuffer and then resolving into a non-RGBA8
12711 QRhiTexture implies (with some graphics APIs) that the storage backing the
12712 QRhiRenderBuffer uses the matching non-RGBA8 format. That means that
12713 passing a format like QRhiTexture::RGBA32F is important, because backends
12714 will typically opt for QRhiTexture::RGBA8 by default, which would then
12715 break later on due to attempting to set up RGBA8->RGBA32F multisample
12716 resolve in the color attachment(s) of the QRhiTextureRenderTarget.
12717
12718 \sa QRhiResource::destroy()
12719 */
12720QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type,
12721 const QSize &pixelSize,
12722 int sampleCount,
12723 QRhiRenderBuffer::Flags flags,
12724 QRhiTexture::Format backingFormatHint)
12725{
12726 return d->createRenderBuffer(type, pixelSize, sampleCount, flags, backingFormatHint);
12727}
12728
12729/*!
12730 \return a new 1D or 2D texture with the specified \a format, \a pixelSize, \a
12731 sampleCount, and \a flags.
12732
12733 A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This
12734 function will implicitly set this flag if the \a pixelSize height is 0.
12735
12736 \note \a format specifies the requested internal and external format,
12737 meaning the data to be uploaded to the texture will need to be in a
12738 compatible format, while the native texture may (but is not guaranteed to,
12739 in case of OpenGL at least) use this format internally.
12740
12741 \note 1D textures are only functional when the OneDimensionalTextures feature is
12742 reported as supported at run time. Further, mipmaps on 1D textures are only
12743 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
12744
12745 \sa QRhiResource::destroy()
12746 */
12747QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
12748 const QSize &pixelSize,
12749 int sampleCount,
12750 QRhiTexture::Flags flags)
12751{
12752 if (pixelSize.height() == 0)
12753 flags |= QRhiTexture::OneDimensional;
12754
12755 return d->createTexture(format, pixelSize, 1, 0, sampleCount, flags);
12756}
12757
12758/*!
12759 \return a new 1D, 2D or 3D texture with the specified \a format, \a width, \a
12760 height, \a depth, \a sampleCount, and \a flags.
12761
12762 This overload is suitable for 3D textures because it allows specifying \a
12763 depth. A 3D texture must have QRhiTexture::ThreeDimensional set in \a
12764 flags, but using this overload that can be omitted because the flag is set
12765 implicitly whenever \a depth is greater than 0. For 1D, 2D and cube textures \a
12766 depth should be set to 0.
12767
12768 A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This overload
12769 will implicitly set this flag if both \a height and \a depth are 0.
12770
12771 \note 3D textures are only functional when the ThreeDimensionalTextures
12772 feature is reported as supported at run time.
12773
12774 \note 1D textures are only functional when the OneDimensionalTextures feature is
12775 reported as supported at run time. Further, mipmaps on 1D textures are only
12776 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
12777
12778 \overload
12779 */
12780QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
12781 int width, int height, int depth,
12782 int sampleCount,
12783 QRhiTexture::Flags flags)
12784{
12785 if (depth > 0)
12786 flags |= QRhiTexture::ThreeDimensional;
12787
12788 if (height == 0 && depth == 0)
12789 flags |= QRhiTexture::OneDimensional;
12790
12791 return d->createTexture(format, QSize(width, height), depth, 0, sampleCount, flags);
12792}
12793
12794/*!
12795 \return a new 1D or 2D texture array with the specified \a format, \a arraySize,
12796 \a pixelSize, \a sampleCount, and \a flags.
12797
12798 This function implicitly sets QRhiTexture::TextureArray in \a flags.
12799
12800 A 1D texture array must have QRhiTexture::OneDimensional set in \a flags. This
12801 function will implicitly set this flag if the \a pixelSize height is 0.
12802
12803 \note Do not confuse texture arrays with arrays of textures. A QRhiTexture
12804 created by this function is usable with 1D or 2D array samplers in the shader, for
12805 example: \c{layout(binding = 1) uniform sampler2DArray texArr;}. Arrays of
12806 textures refers to a list of textures that are exposed to the shader via
12807 QRhiShaderResourceBinding::sampledTextures() and a count > 1, and declared
12808 in the shader for example like this: \c{layout(binding = 1) uniform
12809 sampler2D textures[4];}
12810
12811 \note This is only functional when the TextureArrays feature is reported as
12812 supported at run time.
12813
12814 \note 1D textures are only functional when the OneDimensionalTextures feature is
12815 reported as supported at run time. Further, mipmaps on 1D textures are only
12816 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
12817
12818
12819 \sa newTexture()
12820 */
12821QRhiTexture *QRhi::newTextureArray(QRhiTexture::Format format,
12822 int arraySize,
12823 const QSize &pixelSize,
12824 int sampleCount,
12825 QRhiTexture::Flags flags)
12826{
12827 flags |= QRhiTexture::TextureArray;
12828
12829 if (pixelSize.height() == 0)
12830 flags |= QRhiTexture::OneDimensional;
12831
12832 return d->createTexture(format, pixelSize, 1, arraySize, sampleCount, flags);
12833}
12834
12835/*!
12836 \return a new sampler with the specified magnification filter \a magFilter,
12837 minification filter \a minFilter, mipmapping mode \a mipmapMode, and the
12838 addressing (wrap) modes \a addressU, \a addressV, and \a addressW.
12839
12840 \note Setting \a mipmapMode to a value other than \c None implies that
12841 images for all relevant mip levels will be provided either via
12842 \l{QRhiResourceUpdateBatch::uploadTexture()}{texture uploads} or by calling
12843 \l{QRhiResourceUpdateBatch::generateMips()}{generateMips()} on the texture
12844 that is used with this sampler. Attempting to use the sampler with a
12845 texture that has no data for all relevant mip levels will lead to rendering
12846 errors, with the exact behavior dependent on the underlying graphics API.
12847
12848 \sa QRhiResource::destroy()
12849 */
12850QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter,
12851 QRhiSampler::Filter minFilter,
12852 QRhiSampler::Filter mipmapMode,
12853 QRhiSampler::AddressMode addressU,
12854 QRhiSampler::AddressMode addressV,
12855 QRhiSampler::AddressMode addressW)
12856{
12857 return d->createSampler(magFilter, minFilter, mipmapMode, addressU, addressV, addressW);
12858}
12859
12860/*!
12861 \return a new shading rate map object.
12862
12863 \since 6.9
12864 */
12865QRhiShadingRateMap *QRhi::newShadingRateMap()
12866{
12867 return d->createShadingRateMap();
12868}
12869
12870/*!
12871 \return a new indirect command buffer that holds commands of the specified
12872 \a type, with room for \a maxCommandCount of them.
12873
12874 \a maxCommandCount cannot be 0, otherwise create() fails. It is the upper
12875 bound for both ways of providing commands: recording them with
12876 QRhiIndirectCommandBuffer::draw() or
12877 QRhiIndirectCommandBuffer::drawIndexed(), and generating them on the GPU
12878 and calling QRhiCommandBuffer::buildIndirect(). Backends allocate their
12879 native objects, and the QRhiBuffer holding the recorded commands, based on
12880 it, which is why it is fixed up front instead of growing on demand.
12881
12882 \sa QRhiIndirectCommandBuffer::setMaxCommandCount(), QRhiIndirectCommandBuffer
12883
12884 \since 6.13
12885 */
12886QRhiIndirectCommandBuffer *QRhi::newIndirectCommandBuffer(QRhiIndirectCommandBuffer::Type type,
12887 quint32 maxCommandCount)
12888{
12889 return d->createIndirectCommandBuffer(type, maxCommandCount);
12890}
12891
12892/*!
12893 \return a new texture render target with color and depth/stencil
12894 attachments given in \a desc, and with the specified \a flags.
12895
12896 \sa QRhiResource::destroy()
12897 */
12898
12899QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
12900 QRhiTextureRenderTarget::Flags flags)
12901{
12902 return d->createTextureRenderTarget(desc, flags);
12903}
12904
12905/*!
12906 \return a new swapchain.
12907
12908 \sa QRhiResource::destroy(), QRhiSwapChain::createOrResize()
12909 */
12910QRhiSwapChain *QRhi::newSwapChain()
12911{
12912 return d->createSwapChain();
12913}
12914
12915/*!
12916 Starts a new frame targeting the next available buffer of \a swapChain.
12917
12918 A frame consists of resource updates and one or more render and compute
12919 passes.
12920
12921 \a flags can indicate certain special cases.
12922
12923 The high level pattern of rendering into a QWindow using a swapchain:
12924
12925 \list
12926
12927 \li Create a swapchain.
12928
12929 \li Call QRhiSwapChain::createOrResize() whenever the surface size is
12930 different than before.
12931
12932 \li Call QRhiSwapChain::destroy() on
12933 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed.
12934
12935 \li Then on every frame:
12936 \badcode
12937 beginFrame(sc);
12938 updates = nextResourceUpdateBatch();
12939 updates->...
12940 QRhiCommandBuffer *cb = sc->currentFrameCommandBuffer();
12941 cb->beginPass(sc->currentFrameRenderTarget(), colorClear, dsClear, updates);
12942 ...
12943 cb->endPass();
12944 ... // more passes as necessary
12945 endFrame(sc);
12946 \endcode
12947
12948 \endlist
12949
12950 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
12951 value on failure. Some of these should be treated as soft, "try again
12952 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
12953 the swapchain is to be resized or updated by calling
12954 QRhiSwapChain::createOrResize(). The application should then attempt to
12955 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
12956 lost but this may also be recoverable by releasing all resources, including
12957 the QRhi itself, and then recreating all resources. See isDeviceLost() for
12958 further discussion.
12959
12960 \sa endFrame(), beginOffscreenFrame(), isDeviceLost()
12961 */
12962QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
12963{
12964 if (d->inFrame)
12965 qWarning("Attempted to call beginFrame() within a still active frame; ignored");
12966
12967 qCDebug(QRHI_LOG_RUB) << "[rub] new frame";
12968
12969 QRhi::FrameOpResult r = !d->inFrame ? d->beginFrame(swapChain, flags) : FrameOpSuccess;
12970 if (r == FrameOpSuccess)
12971 d->inFrame = true;
12972
12973 return r;
12974}
12975
12976/*!
12977 Ends, commits, and presents a frame that was started in the last
12978 beginFrame() on \a swapChain.
12979
12980 Double (or triple) buffering is managed internally by the QRhiSwapChain and
12981 QRhi.
12982
12983 \a flags can optionally be used to change the behavior in certain ways.
12984 Passing QRhi::SkipPresent skips queuing the Present command or calling
12985 swapBuffers.
12986
12987 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
12988 value on failure. Some of these should be treated as soft, "try again
12989 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
12990 the swapchain is to be resized or updated by calling
12991 QRhiSwapChain::createOrResize(). The application should then attempt to
12992 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
12993 lost but this may also be recoverable by releasing all resources, including
12994 the QRhi itself, and then recreating all resources. See isDeviceLost() for
12995 further discussion.
12996
12997 \sa beginFrame(), isDeviceLost()
12998 */
12999QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags)
13000{
13001 if (!d->inFrame)
13002 qWarning("Attempted to call endFrame() without an active frame; ignored");
13003
13004 QRhi::FrameOpResult r = d->inFrame ? d->endFrame(swapChain, flags) : FrameOpSuccess;
13005 d->inFrame = false;
13006 // deleteLater is a high level QRhi concept the backends know
13007 // nothing about - handle it here.
13008 qDeleteAll(d->pendingDeleteResources);
13009 d->pendingDeleteResources.clear();
13010
13011 return r;
13012}
13013
13014/*!
13015 \return true when there is an active frame, meaning there was a
13016 beginFrame() (or beginOffscreenFrame()) with no corresponding endFrame()
13017 (or endOffscreenFrame()) yet.
13018
13019 \sa currentFrameSlot(), beginFrame(), endFrame()
13020 */
13021bool QRhi::isRecordingFrame() const
13022{
13023 return d->inFrame;
13024}
13025
13026/*!
13027 \return the current frame slot index while recording a frame. Unspecified
13028 when called outside an active frame (that is, when isRecordingFrame() is \c
13029 false).
13030
13031 With backends like Vulkan or Metal, it is the responsibility of the QRhi
13032 backend to block whenever starting a new frame and finding the CPU is
13033 already \c{FramesInFlight - 1} frames ahead of the GPU (because the command
13034 buffer submitted in frame no. \c{current} - \c{FramesInFlight} has not yet
13035 completed).
13036
13037 Resources that tend to change between frames (such as, the native buffer
13038 object backing a QRhiBuffer with type QRhiBuffer::Dynamic) exist in
13039 multiple versions, so that each frame, that can be submitted while a
13040 previous one is still being processed, works with its own copy, thus
13041 avoiding the need to stall the pipeline when preparing the frame. (The
13042 contents of a resource that may still be in use in the GPU should not be
13043 touched, but simply always waiting for the previous frame to finish would
13044 reduce GPU utilization and ultimately, performance and efficiency.)
13045
13046 Conceptually this is somewhat similar to copy-on-write schemes used by some
13047 C++ containers and other types. It may also be similar to what an OpenGL or
13048 Direct 3D 11 implementation performs internally for certain type of objects.
13049
13050 In practice, such double (or triple) buffering resources is realized in
13051 the Vulkan, Metal, and similar QRhi backends by having a fixed number of
13052 native resource (such as, VkBuffer) \c slots behind a QRhiResource. That
13053 can then be indexed by a frame slot index running 0, 1, ..,
13054 FramesInFlight-1, and then wrapping around.
13055
13056 All this is managed transparently to the users of QRhi. However,
13057 applications that integrate rendering done directly with the graphics API
13058 may want to perform a similar double or triple buffering of their own
13059 graphics resources. That is then most easily achieved by knowing the values
13060 of the maximum number of in-flight frames (retrievable via resourceLimit())
13061 and the current frame (slot) index (returned by this function).
13062
13063 \sa isRecordingFrame(), beginFrame(), endFrame()
13064 */
13065int QRhi::currentFrameSlot() const
13066{
13067 return d->currentFrameSlot;
13068}
13069
13070/*!
13071 Starts a new offscreen frame. Provides a command buffer suitable for
13072 recording rendering commands in \a cb. \a flags is used to indicate
13073 certain special cases, just like with beginFrame().
13074
13075 \note The QRhiCommandBuffer stored to *cb is not owned by the caller.
13076
13077 Rendering without a swapchain is possible as well. The typical use case is
13078 to use it in completely offscreen applications, e.g. to generate image
13079 sequences by rendering and reading back without ever showing a window.
13080
13081 Usage in on-screen applications (so beginFrame, endFrame,
13082 beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) is possible too.
13083
13084 When a \l{QRhiResourceUpdateBatch::readBackTexture()}{texture} or
13085 \l{QRhiResourceUpdateBatch::readBackBuffer()}{buffer} readback was
13086 scheduled, offscreen frames do not let the CPU potentially generate another
13087 frame while the GPU is still processing the previous one. This has the side
13088 effect that if readbacks are scheduled, the results are guaranteed to be
13089 available once endOffscreenFrame() returns. That is not the case with frames
13090 targeting a swapchain: there the GPU is potentially better utilized, but
13091 working with readback operations needs more care from the application
13092 because endFrame(), unlike endOffscreenFrame(), does not guarantee that the
13093 results from the readback are available at that point.
13094
13095 The skeleton of rendering a frame without a swapchain and then reading the
13096 frame contents back could look like the following:
13097
13098 \code
13099 QRhiReadbackResult rbResult;
13100 QRhiCommandBuffer *cb;
13101 rhi->beginOffscreenFrame(&cb);
13102 cb->beginPass(rt, colorClear, dsClear);
13103 // ...
13104 u = nextResourceUpdateBatch();
13105 u->readBackTexture(rb, &rbResult);
13106 cb->endPass(u);
13107 rhi->endOffscreenFrame();
13108 // image data available in rbResult
13109 \endcode
13110
13111 \sa endOffscreenFrame(), beginFrame()
13112 */
13113QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags)
13114{
13115 if (d->inFrame)
13116 qWarning("Attempted to call beginOffscreenFrame() within a still active frame; ignored");
13117
13118 qCDebug(QRHI_LOG_RUB) << "[rub] new offscreen frame";
13119
13120 QRhi::FrameOpResult r = !d->inFrame ? d->beginOffscreenFrame(cb, flags) : FrameOpSuccess;
13121 if (r == FrameOpSuccess)
13122 d->inFrame = true;
13123
13124 return r;
13125}
13126
13127/*!
13128 Ends, submits, and potentially waits for the offscreen frame.
13129
13130 Unlike endFrame(), this function will block and wait for completion of the
13131 GPU-side work when there are active buffer or texture readbacks.
13132
13133 \a flags is not currently used.
13134
13135 \sa beginOffscreenFrame()
13136 */
13137QRhi::FrameOpResult QRhi::endOffscreenFrame(EndFrameFlags flags)
13138{
13139 if (!d->inFrame)
13140 qWarning("Attempted to call endOffscreenFrame() without an active frame; ignored");
13141
13142 QRhi::FrameOpResult r = d->inFrame ? d->endOffscreenFrame(flags) : FrameOpSuccess;
13143 d->inFrame = false;
13144 qDeleteAll(d->pendingDeleteResources);
13145 d->pendingDeleteResources.clear();
13146
13147 return r;
13148}
13149
13150/*!
13151 Waits for any work on the graphics queue (where applicable) to complete,
13152 then executes all deferred operations, like completing readbacks and
13153 resource releases. Can be called inside and outside of a frame, but not
13154 inside a pass. Inside a frame it implies submitting any work on the
13155 command buffer.
13156
13157 \note Avoid this function. One case where it may be needed is when the
13158 results of an enqueued readback in a swapchain-based frame are needed at a
13159 fixed given point and so waiting for the results is desired.
13160 */
13161QRhi::FrameOpResult QRhi::finish()
13162{
13163 return d->finish();
13164}
13165
13166/*!
13167 \return the list of supported sample counts.
13168
13169 A typical example would be (1, 2, 4, 8).
13170
13171 With some backend this list of supported values is fixed in advance, while
13172 with some others the (physical) device properties indicate what is
13173 supported at run time.
13174
13175 \sa QRhiRenderBuffer::setSampleCount(), QRhiTexture::setSampleCount(),
13176 QRhiGraphicsPipeline::setSampleCount(), QRhiSwapChain::setSampleCount()
13177 */
13178QList<int> QRhi::supportedSampleCounts() const
13179{
13180 return d->supportedSampleCounts();
13181}
13182
13183/*!
13184 \return the minimum uniform buffer offset alignment in bytes. This is
13185 typically 256.
13186
13187 Attempting to bind a uniform buffer region with an offset not aligned to
13188 this value will lead to failures depending on the backend and the
13189 underlying graphics API.
13190
13191 \sa ubufAligned()
13192 */
13193int QRhi::ubufAlignment() const
13194{
13195 return d->ubufAlignment();
13196}
13197
13198/*!
13199 \return The list of supported variable shading rates for the specified \a sampleCount.
13200
13201 1x1 is always supported.
13202
13203 \since 6.9
13204 */
13205QList<QSize> QRhi::supportedShadingRates(int sampleCount) const
13206{
13207 return d->supportedShadingRates(sampleCount);
13208}
13209
13210Q_CONSTINIT static QBasicAtomicInteger<QRhiGlobalObjectIdGenerator::Type> counter = Q_BASIC_ATOMIC_INITIALIZER(0);
13211
13212QRhiGlobalObjectIdGenerator::Type QRhiGlobalObjectIdGenerator::newId()
13213{
13214 return counter.fetchAndAddRelaxed(1) + 1;
13215}
13216
13218{
13219 return m_buffers.isEmpty() && m_textures.isEmpty();
13220}
13221
13223{
13224 m_buffers.clear();
13225 m_textures.clear();
13226}
13227
13233
13234void QRhiPassResourceTracker::registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
13235 const UsageState &state)
13236{
13237 auto it = m_buffers.find(buf);
13238 if (it != m_buffers.end()) {
13239 Buffer &b = it->second;
13240 if (Q_UNLIKELY(b.access != *access)) {
13241 const QByteArray name = buf->name();
13242 qWarning("Buffer %p (%s) used with different accesses within the same pass, this is not allowed.",
13243 buf, name.constData());
13244 return;
13245 }
13246 if (b.stage != *stage) {
13247 b.stage = earlierStage(b.stage, *stage);
13248 *stage = b.stage;
13249 }
13250 return;
13251 }
13252
13253 Buffer b;
13254 b.slot = slot;
13255 b.access = *access;
13256 b.stage = *stage;
13257 b.stateAtPassBegin = state; // first use -> initial state
13258 m_buffers.insert(buf, b);
13259}
13260
13266
13273
13275 const UsageState &state)
13276{
13277 auto it = m_textures.find(tex);
13278 if (it != m_textures.end()) {
13279 Texture &t = it->second;
13280 if (t.access != *access) {
13281 // Different subresources of a texture may be used for both load
13282 // and store in the same pass. (think reading from one mip level
13283 // and writing to another one in a compute shader) This we can
13284 // handle by treating the entire resource as read-write.
13285 if (Q_LIKELY(isImageLoadStore(t.access) && isImageLoadStore(*access))) {
13287 *access = t.access;
13288 } else {
13289 const QByteArray name = tex->name();
13290 qWarning("Texture %p (%s) used with different accesses within the same pass, this is not allowed.",
13291 tex, name.constData());
13292 }
13293 }
13294 if (t.stage != *stage) {
13295 t.stage = earlierStage(t.stage, *stage);
13296 *stage = t.stage;
13297 }
13298 return;
13299 }
13300
13301 Texture t;
13302 t.access = *access;
13303 t.stage = *stage;
13304 t.stateAtPassBegin = state; // first use -> initial state
13305 m_textures.insert(tex, t);
13306}
13307
13308QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
13309{
13310 // pick the earlier stage (as this is going to be dstAccessMask)
13311 if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
13313 if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
13315 if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
13317 if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
13319 if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
13321 if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
13323
13324 Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::BufVertexStage);
13325}
13326
13327QRhiPassResourceTracker::TextureStage QRhiPassResourceTracker::toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
13328{
13329 // pick the earlier stage (as this is going to be dstAccessMask)
13330 if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
13332 if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
13334 if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
13336 if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
13338 if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
13340 if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
13342
13343 Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::TexVertexStage);
13344}
13345
13346QSize QRhiImplementation::clampedSubResourceUploadSize(QSize size, QPoint dstPos, int level, QSize textureSizeAtLevelZero, bool warn)
13347{
13348 const QSize subResSize = q->sizeForMipLevel(level, textureSizeAtLevelZero);
13349 const bool outOfBoundsHoriz = dstPos.x() + size.width() > subResSize.width();
13350 const bool outOfBoundsVert = dstPos.y() + size.height() > subResSize.height();
13351 if (Q_UNLIKELY(outOfBoundsHoriz || outOfBoundsVert)) {
13352 if (warn) {
13353 qWarning("Invalid texture upload issued; size %dx%d dst.position %d,%d dst.subresource size %dx%d; size will be clamped",
13354 size.width(), size.height(), dstPos.x(), dstPos.y(), subResSize.width(), subResSize.height());
13355 }
13356 if (outOfBoundsHoriz)
13357 size.setWidth(subResSize.width() - dstPos.x());
13358 if (outOfBoundsVert)
13359 size.setHeight(subResSize.height() - dstPos.y());
13360 }
13361 return size;
13362}
13363
13364// Clamps size so that reading the image with a source row stride of bpl does
13365// not go past dataSize bytes. bpl may be 0, meaning the data is tightly packed.
13366// Returns a size with a height of 0 when not even a single row can be
13367// satisfied, in which case the caller is expected to skip the copy.
13368QSize QRhiImplementation::clampedSubResourceUploadSizeForSourceData(QSize size, quint32 bpl,
13369 quint32 bytesPerPixel,
13370 qsizetype dataSize, bool warn)
13371{
13372 if (size.isEmpty() || !bytesPerPixel)
13373 return size;
13374
13375 const quint64 rowBytes = quint64(bytesPerPixel) * quint64(size.width());
13376 if (!bpl)
13377 bpl = quint32(qMin(rowBytes, quint64(std::numeric_limits<quint32>::max())));
13378
13379 if (quint64(bpl) < rowBytes) {
13380 if (warn) {
13381 qWarning("Invalid texture upload issued; source row stride %u is smaller than the %llu "
13382 "bytes a row of %d pixels needs; upload will be skipped",
13383 bpl, rowBytes, size.width());
13384 }
13385 return QSize(size.width(), 0);
13386 }
13387
13388 // Row y is read from y * bpl and needs rowBytes bytes, so the last row ends
13389 // at (height - 1) * bpl + rowBytes.
13390 const quint64 needed = quint64(bpl) * quint64(size.height() - 1) + rowBytes;
13391 if (quint64(dataSize) >= needed)
13392 return size;
13393
13394 int rows = 0;
13395 if (quint64(dataSize) >= rowBytes)
13396 rows = int((quint64(dataSize) - rowBytes) / quint64(bpl)) + 1;
13397
13398 if (warn) {
13399 qWarning("Invalid texture upload issued; %lld bytes of data cannot back a %dx%d upload with "
13400 "source row stride %u (needs %llu bytes); height will be clamped to %d",
13401 qint64(dataSize), size.width(), size.height(), bpl, needed, rows);
13402 }
13403
13404 return QSize(size.width(), rows);
13405}
13406
13407QT_END_NAMESPACE
friend bool operator==(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
Returns true if lhs and rhs are equal, otherwise returns false.
Definition qbytearray.h:838
friend bool operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
Returns true if lhs and rhs are different, otherwise returns false.
Definition qbytearray.h:849
void execute(QRhiCommandBuffer *cb, quint32 firstCommand, quint32 commandCount)
Definition qrhi.cpp:9183
QRhiBufferBackedIndirectCommandBuffer(QRhiImplementation *rhi, Type type, quint32 maxCommandCount)
\variable QRhiIndirectCommandBufferBuildInfo::topology
Definition qrhi.cpp:9093
void enqueueUpload(QRhiResourceUpdateBatch *u)
Definition qrhi.cpp:9147
void build(const QRhiIndirectCommandBufferBuildInfo &info)
Definition qrhi.cpp:9170
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
Definition qrhi.cpp:9105
bool create() override
Creates the corresponding native objects.
Definition qrhi.cpp:9128
bool isEmpty() const
Definition qrhi.cpp:13217
void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage, const UsageState &state)
Definition qrhi.cpp:13234
void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage, const UsageState &state)
Definition qrhi.cpp:13274
QRhiImplementation * rhi
Definition qrhi_p.h:631
static const int BUFFER_OPS_STATIC_ALLOC
Definition qrhi_p.h:623
void merge(QRhiResourceUpdateBatchPrivate *other)
Definition qrhi.cpp:11063
QRhiResourceUpdateBatch * q
Definition qrhi_p.h:630
static const int TEXTURE_OPS_STATIC_ALLOC
Definition qrhi_p.h:627
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
static const char * resourceTypeStr(const QRhiResource *res)
Definition qrhi.cpp:9344
static QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a, QRhiPassResourceTracker::BufferStage b)
Definition qrhi.cpp:13228
QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
Definition qrhi.cpp:8396
static bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess access)
Definition qrhi.cpp:13267
static const char * deviceTypeStr(QRhiDriverInfo::DeviceType type)
\variable QRhiDriverInfo::deviceName
Definition qrhi.cpp:10323
static QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a, QRhiPassResourceTracker::TextureStage b)
Definition qrhi.cpp:13261
constexpr size_t qHash(const QSize &s, size_t seed=0) noexcept
Definition qsize.h:192
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1566
LimitsType limitsType
Definition qrhi.h:1577
float maxPotentialColorComponentValue
Definition qrhi.h:1585
LuminanceBehavior luminanceBehavior
Definition qrhi.h:1588
float maxColorComponentValue
Definition qrhi.h:1584