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 all versions of OpenGL. The latter is due to OpenGL ES not
845 supporting draw calls with a base instance at all. Currently QRhi's OpenGL
846 backend does not implement the functionality for OpenGL (non-ES) either,
847 because portable applications cannot rely on a non-zero base instance in
848 practice due to GLES. If the application still chooses to do so, it should
849 be aware of the InstanceIndexIncludesBaseInstance feature as well.
850
851 \value TriangleFanTopology Indicates that QRhiGraphicsPipeline::setTopology()
852 supports QRhiGraphicsPipeline::TriangleFan. In practice this feature will be
853 unsupported with Metal and Direct 3D 11/12.
854
855 \value ReadBackNonUniformBuffer Indicates that
856 \l{QRhiResourceUpdateBatch::readBackBuffer()}{reading buffer contents} is
857 supported for QRhiBuffer instances with a usage different than
858 UniformBuffer. In practice this feature will be unsupported with OpenGL ES
859 2.0.
860
861 \value ReadBackNonBaseMipLevel Indicates that specifying a mip level other
862 than 0 is supported when reading back texture contents. When not supported,
863 specifying a non-zero level in QRhiReadbackDescription leads to returning
864 an all-zero image. In practice this feature will be unsupported with OpenGL
865 ES 2.0.
866
867 \value TexelFetch Indicates that texelFetch() and textureLod() are available
868 in shaders. In practice this will be reported as unsupported with OpenGL ES
869 2.0 and OpenGL 2.x contexts, because GLSL 100 es and versions before 130 do
870 not support these functions.
871
872 \value RenderToNonBaseMipLevel Indicates that specifying a mip level other
873 than 0 is supported when creating a QRhiTextureRenderTarget with a
874 QRhiTexture as its color attachment. When not supported, create() will fail
875 whenever the target mip level is not zero. In practice this feature will be
876 unsupported with OpenGL ES 2.0.
877
878 \value IntAttributes Indicates that specifying input attributes with
879 signed and unsigned integer types for a shader pipeline is supported. When
880 not supported,
881 \l{QRhiGraphicsPipeline::create()}{QRhiGraphicsPipeline::create()} will
882 succeed but show a warning message and the values of the target attributes
883 will be broken. In practice this feature will be unsupported with OpenGL ES
884 2.0 and OpenGL 2.x.
885
886 \value ScreenSpaceDerivatives Indicates that functions such as dFdx(),
887 dFdy(), and fwidth() are supported in shaders. In practice this feature will
888 be unsupported with OpenGL ES 2.0 without the GL_OES_standard_derivatives
889 extension.
890
891 \value ReadBackAnyTextureFormat Indicates that reading back texture
892 contents can be expected to work for any QRhiTexture::Format. Backends
893 other than OpenGL can be expected to return true for this feature. When
894 reported as false, which will typically happen with OpenGL, only the
895 formats QRhiTexture::RGBA8 and QRhiTexture::BGRA8 are guaranteed to be
896 supported for readbacks. In addition, with OpenGL, but not OpenGL ES,
897 reading back the 1 byte per component formats QRhiTexture::R8 and
898 QRhiTexture::RED_OR_ALPHA8 are supported as well. Reading back floating
899 point formats QRhiTexture::RGBA16F and RGBA32F may work too with OpenGL, as
900 long as the implementation provides support for these, but QRhi can give no
901 guarantees, as indicated by this flag.
902
903 \value PipelineCacheDataLoadSave Indicates that the pipelineCacheData() and
904 setPipelineCacheData() functions are functional. When not supported, the
905 functions will not perform any action, the retrieved blob is always empty,
906 and thus no benefits can be expected from retrieving and, during a
907 subsequent run of the application, reloading the pipeline cache content.
908
909 \value ImageDataStride Indicates that specifying a custom stride (row
910 length) for raw image data in texture uploads is supported. When not
911 supported (which can happen when the underlying API is OpenGL ES 2.0 without
912 support for GL_UNPACK_ROW_LENGTH),
913 QRhiTextureSubresourceUploadDescription::setDataStride() must not be used.
914
915 \value RenderBufferImport Indicates that QRhiRenderBuffer::createFrom() is
916 supported. For most graphics APIs this is not sensible because
917 QRhiRenderBuffer encapsulates texture objects internally, just like
918 QRhiTexture. With OpenGL however, renderbuffer object exist as a separate
919 object type in the API, and in certain environments (for example, where one
920 may want to associated a renderbuffer object with an EGLImage object) it is
921 important to allow wrapping an existing OpenGL renderbuffer object with a
922 QRhiRenderBuffer.
923
924 \value ThreeDimensionalTextures Indicates that 3D textures are supported.
925 In practice this feature will be unsupported with OpenGL and OpenGL ES
926 versions lower than 3.0.
927
928 \value RenderTo3DTextureSlice Indicates that rendering to a slice in a 3D
929 texture is supported. This can be unsupported with Vulkan 1.0 due to
930 relying on VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT which is a Vulkan 1.1
931 feature.
932
933 \value TextureArrays Indicates that texture arrays are supported and
934 QRhi::newTextureArray() is functional. Note that even when texture arrays
935 are not supported, arrays of textures are still available as those are two
936 independent features.
937
938 \value Tessellation Indicates that the tessellation control and evaluation
939 stages are supported. When reported as supported, the topology of a
940 QRhiGraphicsPipeline can be set to
941 \l{QRhiGraphicsPipeline::Patches}{Patches}, the number of control points
942 can be set via
943 \l{QRhiGraphicsPipeline::setPatchControlPointCount()}{setPatchControlPointCount()},
944 and shaders for tessellation control and evaluation can be specified in the
945 QRhiShaderStage list. Tessellation shaders have portability issues between
946 APIs (for example, translating GLSL/SPIR-V to HLSL is problematic due to
947 the way hull shaders are structured, whereas Metal uses a somewhat
948 different tessellation pipeline than others), and therefore unexpected
949 issues may still arise, even though basic functionality is implemented
950 across all the underlying APIs. For Direct 3D in particular, handwritten
951 HLSL hull and domain shaders must be injected into each QShader for the
952 tessellation control and evaluation stages, respectively, since qsb cannot
953 generate these from SPIR-V. Note that isoline tessellation should be
954 avoided as it will not be supported by all backends. The maximum patch
955 control point count portable between backends is 32.
956
957 \value GeometryShader Indicates that the geometry shader stage is supported.
958 When supported, a geometry shader can be specified in the QRhiShaderStage
959 list. Geometry Shaders are considered an experimental feature in QRhi and
960 can only be expected to be supported with Vulkan, Direct 3D 11 and 12,
961 OpenGL (3.2+) and OpenGL ES (3.2+), assuming the implementation reports it
962 as supported at run time. Starting with Qt 6.11 geometry shaders are
963 automatically translated to HLSL, and therefore no injection of handwritten
964 HLSL geometry shaders is necessary anymore (but note that gl_in and
965 expressions such as gl_in[0].gl_Position are not supported; rather, pass the
966 position as an output variable from the vertex shader). Geometry shaders are
967 not supported with Metal.
968
969 \value TextureArrayRange Indicates that for
970 \l{QRhi::newTextureArray()}{texture arrays} it is possible to specify a
971 range that is exposed to the shaders. Normally all array layers are exposed
972 and it is up to the shader to select the layer (via the third coordinate
973 passed to texture() when sampling the \c sampler2DArray). When supported,
974 calling QRhiTexture::setArrayRangeStart() and
975 QRhiTexture::setArrayRangeLength() before
976 \l{QRhiTexture::create()}{building} or
977 \l{QRhiTexture::createFrom()}{importing} the native texture has an effect,
978 and leads to selecting only the specified range from the array. This will
979 be necessary in special cases, such as when working with accelerated video
980 decoding and Direct 3D 11, because a texture array with both
981 \c{D3D11_BIND_DECODER} and \c{D3D11_BIND_SHADER_RESOURCE} on it is only
982 usable as a shader resource if a single array layer is selected. Note that
983 all this is applicable only when the texture is used as a
984 QRhiShaderResourceBinding::SampledTexture or
985 QRhiShaderResourceBinding::Texture shader resource, and is not compatible
986 with image load/store. This feature is only available with some backends as
987 it does not map well to all graphics APIs, and it is only meant to provide
988 support for special cases anyhow. In practice the feature can be expected to
989 be supported with Direct3D 11/12 and Vulkan.
990
991 \value NonFillPolygonMode Indicates that setting a PolygonMode other than
992 the default Fill is supported for QRhiGraphicsPipeline. A common use case
993 for changing the mode to Line is to get wireframe rendering. This however
994 is not available as a core OpenGL ES feature, and is optional with Vulkan
995 as well as some mobile GPUs may not offer the feature.
996
997 \value OneDimensionalTextures Indicates that 1D textures are supported.
998 In practice this feature will be unsupported on OpenGL ES.
999
1000 \value OneDimensionalTextureMipmaps Indicates that generating 1D texture
1001 mipmaps is supported. In practice this feature will be unsupported on
1002 backends that do not report support for
1003 \l{OneDimensionalTextures}, Metal, and Direct 3D 12.
1004
1005 \value HalfAttributes Indicates that specifying input attributes with half
1006 precision (16bit) floating point types for a shader pipeline is supported.
1007 When not supported,
1008 \l{QRhiGraphicsPipeline::create()}{QRhiGraphicsPipeline::create()} will
1009 succeed but show a warning message and the values of the target attributes
1010 will be broken. In practice this feature will be unsupported in some OpenGL
1011 ES 2.0 and OpenGL 2.x
1012 implementations. Note that while Direct3D 11/12 does support half precision
1013 input attributes, it does not support the half3 type. The D3D backends pass
1014 half3 attributes as half4. To ensure cross platform compatibility, half3
1015 inputs should be padded to 8 bytes.
1016
1017 \value RenderToOneDimensionalTexture Indicates that 1D texture render
1018 targets are supported. In practice this feature will be unsupported on
1019 backends that do not report support for
1020 \l{OneDimensionalTextures}, and Metal.
1021
1022 \value ThreeDimensionalTextureMipmaps Indicates that generating 3D texture
1023 mipmaps is supported. This is typically supported with all backends starting
1024 with Qt 6.10.
1025
1026 \value MultiView Indicates that multiview, see e.g.
1027 \l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_multiview.html}{VK_KHR_multiview}
1028 is supported. With OpenGL ES 2.0, Direct 3D 11, and OpenGL (ES)
1029 implementations without \c{GL_OVR_multiview2} this feature will not be
1030 supported. With Vulkan 1.1 and newer, and Direct 3D 12 multiview is
1031 typically supported. When reported as supported, creating a
1032 QRhiTextureRenderTarget with a QRhiColorAttachment that references a texture
1033 array and has \l{QRhiColorAttachment::setMultiViewCount()}{multiViewCount}
1034 set enables recording a render pass that uses multiview rendering. In addition,
1035 any QRhiGraphicsPipeline used in that render pass must have
1036 \l{QRhiGraphicsPipeline::setMultiViewCount()}{the same view count set}. Note that
1037 multiview is only available in combination with 2D texture arrays. It cannot
1038 be used to optimize the rendering into individual textures (e.g. two, for
1039 the left and right eyes). Rather, the target of a multiview render pass is
1040 always a texture array, automatically rendering to the layer (array element)
1041 corresponding to each view. Therefore this feature implies \l TextureArrays
1042 as well. Multiview rendering is not supported in combination with
1043 tessellation or geometry shaders. See QRhiColorAttachment::setMultiViewCount()
1044 for further details on multiview rendering. This enum value has been introduced in Qt 6.7.
1045
1046 \value TextureViewFormat Indicates that setting a
1047 \l{QRhiTexture::setWriteViewFormat()}{view format} on a QRhiTexture is
1048 effective. When reported as supported, setting the read (sampling) or write
1049 (render target / image load-store) view mode changes the texture's viewing
1050 format. When unsupported, setting a view format has no effect. Note that Qt
1051 has no knowledge or control over format compatibility or resource view rules
1052 in the underlying 3D API and its implementation. Passing in unsuitable,
1053 incompatible formats may lead to errors and unspecified behavior. This is
1054 provided mainly to allow "casting" rendering into a texture created with an
1055 sRGB format to non-sRGB to avoid the unwanted linear->sRGB conversion on
1056 shader writes. Other types of casting may or may not be functional,
1057 depending on the underlying API. Currently implemented for Vulkan and Direct
1058 3D 12. With D3D12 the feature is available only if
1059 \c CastingFullyTypedFormatSupported is supported, see
1060 \l{https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html} (and
1061 note that QRhi always uses fully typed formats for textures.) This enum
1062 value has been introduced in Qt 6.8.
1063
1064 \value ResolveDepthStencil Indicates that resolving a multisample depth or
1065 depth-stencil texture is supported. Otherwise,
1066 \l{QRhiTextureRenderTargetDescription::setDepthResolveTexture()}{setting a
1067 depth resolve texture} is not functional and must be avoided. Direct 3D 11
1068 and 12 have no support for resolving depth/depth-stencil formats, and
1069 therefore this feature will never be supported with those. Vulkan 1.0 has no
1070 API to request resolving a depth-stencil attachment. Therefore, with Vulkan
1071 this feature will only be supported with Vulkan 1.2 and up, and on 1.1
1072 implementations with the appropriate extensions present. This feature is
1073 provided for the rare case when resolving into a non-multisample depth
1074 texture becomes necessary, for example when rendering into an
1075 OpenXR-provided depth texture (XR_KHR_composition_layer_depth). This enum
1076 value has been introduced in Qt 6.8.
1077
1078 \value VariableRateShading Indicates that per-draw (per-pipeline) variable
1079 rate shading is supported. When reported as supported, \l
1080 QRhiCommandBuffer::setShadingRate() is functional and has an effect for
1081 QRhiGraphicsPipeline objects that declared \l
1082 QRhiGraphicsPipeline::UsesShadingRate in their flags. Call \l
1083 QRhi::supportedShadingRates() to check which rates are supported. (1x1 is
1084 always supported, other typical values are 2x2, 1x2, 2x1, 2x4, 4x2, 4x4).
1085 This feature can be expected to be supported with Direct 3D 12 and Vulkan,
1086 assuming the implementation and GPU used at run time supports VRS. This enum
1087 value has been introduced in Qt 6.9.
1088
1089 \value VariableRateShadingMap Indicates that image-based specification of
1090 the shading rate is possible. The "image" is not necessarily a texture, it
1091 may be a native 3D API object, depending on the underlying backend and
1092 graphics API at run time. In practice this feature can be expected to be
1093 supported with Direct 3D 12, Vulkan, and Metal, assuming the GPU is modern
1094 enough to support VRS. To check if D3D12/Vulkan-style image-based VRS is
1095 supported, use VariableRateShadingMapWithTexture instead. When this feature
1096 is reported as supported, there are two possibilities: when
1097 VariableRateShadingMapWithTexture is also true, then QRhiShadingRateMap
1098 consumes QRhiTexture objects via the createFrom() overload taking a
1099 QRhiTexture argument. When VariableRateShadingMapWithTexture is false, then
1100 QRhiShadingRateMap consumes some other type of native objects, for example
1101 an MTLRasterizationRateMap in case of Metal. Use the createFrom() overload
1102 taking a NativeShadingRateMap in this case. This enum value has been
1103 introduced in Qt 6.9.
1104
1105 \value VariableRateShadingMapWithTexture Indicates that image-based
1106 specification of the shading rate is supported via regular textures. In
1107 practice this may be supported with Direct 3D 12 and Vulkan. This enum value
1108 has been introduced in Qt 6.9.
1109
1110 \value PerRenderTargetBlending Indicates that per rendertarget blending is
1111 supported i.e. different render targets in MRT framebuffer can have different
1112 blending modes. In practice this can be expected to be supported everywhere
1113 except OpenGL ES, where it is only available with GLES 3.2 implementations.
1114 This enum value has been introduced in Qt 6.9.
1115
1116 \value SampleVariables Indicates that gl_SampleID, gl_SamplePosition,
1117 gl_SampleMaskIn and gl_SampleMask variables are available in fragment shaders.
1118 In practice this can be expected to be supported everywhere except OpenGL ES,
1119 where it is only available with GLES 3.2 implementations.
1120 This enum value has been introduced in Qt 6.9.
1121
1122 \value InstanceIndexIncludesBaseInstance Indicates that \c gl_InstanceIndex
1123 includes the base instance (the \c firstInstance argument in draw calls) in
1124 its value. When this feature is unsupported, but BaseInstance is, it
1125 indicates that \c gl_InstanceIndex always starts at 0, not the base value.
1126 In practice this will be the case for Direct 3D 11 and 12 at the moment.
1127 With Vulkan and Metal this feature is expected to be reported as supported
1128 always. This enum value has been introduced in Qt 6.11.
1129
1130 \value [since 6.11] DepthClamp Indicates that enabling depth clamping is
1131 supported. When reported as unsupported, which will be the case with OpenGL
1132 ES, OpenGL versions before 3.2 without the relevant extension present, and
1133 Metal on the iOS Simulator, calling \l{QRhiGraphicsPipeline::setDepthClamp()}
1134 with an argument of \c true has no effect.
1135
1136 \value [since 6.12] DrawIndirect Indicates that the
1137 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
1138 and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}
1139 functions are available.
1140 In practice this can be expected to be supported everywhere except on
1141 OpenGL ES < 3.1.
1142
1143 \value [since 6.12] DrawIndirectMulti Indicates that a drawCount > 1 is natively
1144 supported by the backend in \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
1145 and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}.
1146 Otherwise, multiple draw calls are issued on the CPU by the RHI.
1147 In practice this can be expected to be supported on Vulkan 1.1+, OpenGL 4.3+
1148 and D3D12.
1149
1150 \value [since 6.12] ShaderDrawParameters Indicates that the \c{gl_BaseInstance},
1151 \c{gl_BaseVertex} and \c{gl_DrawID} built-in variables are available in shaders.
1152 In practice this can be expected to be supported on Vulkan 1.1+ and with desktop OpenGL
1153 4.6 or \c{GL_ARB_shader_draw_parameters}.
1154 */
1155
1156/*!
1157 \enum QRhi::BeginFrameFlag
1158 Flag values for QRhi::beginFrame()
1159 */
1160
1161/*!
1162 \enum QRhi::EndFrameFlag
1163 Flag values for QRhi::endFrame()
1164
1165 \value SkipPresent Specifies that no present command is to be queued or no
1166 swapBuffers call is to be made. This way no image is presented. Generating
1167 multiple frames with all having this flag set is not recommended (except,
1168 for example, for benchmarking purposes - but keep in mind that backends may
1169 behave differently when it comes to waiting for command completion without
1170 presenting so the results are not comparable between them)
1171 */
1172
1173/*!
1174 \enum QRhi::ResourceLimit
1175 Describes the resource limit to query.
1176
1177 \value TextureSizeMin Minimum texture width and height. This is typically
1178 1. The minimum texture size is handled gracefully, meaning attempting to
1179 create a texture with an empty size will instead create a texture with the
1180 minimum size.
1181
1182 \value TextureSizeMax Maximum texture width and height. This depends on the
1183 graphics API and sometimes the platform or implementation as well.
1184 Typically the value is in the range 4096 - 16384. Attempting to create
1185 textures larger than this is expected to fail.
1186
1187 \value MaxColorAttachments The maximum number of color attachments for a
1188 QRhiTextureRenderTarget, in case multiple render targets are supported. When
1189 MRT is not supported, the value is 1. Otherwise this is typically 8, but
1190 watch out for the fact that OpenGL only mandates 4 as the minimum, and that
1191 is what some OpenGL ES implementations provide.
1192
1193 \value FramesInFlight The number of frames the backend may keep "in
1194 flight": with backends like Vulkan or Metal, it is the responsibility of
1195 QRhi to block whenever starting a new frame and finding the CPU is already
1196 \c{N - 1} frames ahead of the GPU (because the command buffer submitted in
1197 frame no. \c{current} - \c{N} has not yet completed). The value N is what
1198 is returned from here, and is typically 2. This can be relevant to
1199 applications that integrate rendering done directly with the graphics API,
1200 as such rendering code may want to perform double (if the value is 2)
1201 buffering for resources, such as, buffers, similarly to the QRhi backends
1202 themselves. The current frame slot index (a value running 0, 1, .., N-1,
1203 then wrapping around) is retrievable from QRhi::currentFrameSlot(). The
1204 value is 1 for backends where the graphics API offers no such low level
1205 control over the command submission process. Note that pipelining may still
1206 happen even when this value is 1 (some backends, such as D3D11, are
1207 designed to attempt to enable this, for instance, by using an update
1208 strategy for uniform buffers that does not stall the pipeline), but that is
1209 then not controlled by QRhi and so not reflected here in the API.
1210
1211 \value MaxAsyncReadbackFrames The number of \l{QRhi::endFrame()}{submitted}
1212 frames (including the one that contains the readback) after which an
1213 asynchronous texture or buffer readback is guaranteed to complete upon
1214 \l{QRhi::beginFrame()}{starting a new frame}.
1215
1216 \value MaxThreadGroupsPerDimension The maximum number of compute
1217 work/thread groups that can be dispatched. Effectively the maximum value
1218 for the arguments of QRhiCommandBuffer::dispatch(). Typically 65535.
1219
1220 \value MaxThreadsPerThreadGroup The maximum number of invocations in a
1221 single local work group, or in other terminology, the maximum number of
1222 threads in a thread group. Effectively the maximum value for the product of
1223 \c local_size_x, \c local_size_y, and \c local_size_z in the compute
1224 shader. Typical values are 128, 256, 512, 1024, or 1536. Watch out that
1225 both OpenGL ES and Vulkan specify only 128 as the minimum required limit
1226 for implementations. While uncommon for Vulkan, some OpenGL ES 3.1
1227 implementations for mobile/embedded devices only support the spec-mandated
1228 minimum value.
1229
1230 \value MaxThreadGroupX The maximum size of a work/thread group in the X
1231 dimension. Effectively the maximum value of \c local_size_x in the compute
1232 shader. Typically 256 or 1024.
1233
1234 \value MaxThreadGroupY The maximum size of a work/thread group in the Y
1235 dimension. Effectively the maximum value of \c local_size_y in the compute
1236 shader. Typically 256 or 1024.
1237
1238 \value MaxThreadGroupZ The maximum size of a work/thread group in the Z
1239 dimension. Effectively the maximum value of \c local_size_z in the compute
1240 shader. Typically 64 or 256.
1241
1242 \value TextureArraySizeMax Maximum texture array size. Typically in range
1243 256 - 2048. Attempting to \l{QRhi::newTextureArray()}{create a texture
1244 array} with more elements will likely fail.
1245
1246 \value MaxUniformBufferRange The number of bytes that can be exposed from a
1247 uniform buffer to the shaders at once. On OpenGL ES 2.0 and 3.0
1248 implementations this may be as low as 3584 bytes (224 four component, 32
1249 bits per component vectors). Elsewhere the value is typically 16384 (1024
1250 vec4s) or 65536 (4096 vec4s).
1251
1252 \value MaxVertexInputs The number of input attributes to the vertex shader.
1253 The location in a QRhiVertexInputAttribute must be in range \c{[0,
1254 MaxVertexInputs-1]}. The value may be as low as 8 with OpenGL ES 2.0.
1255 Elsewhere, typical values are 16, 31, or 32.
1256
1257 \value MaxVertexOutputs The maximum number of outputs (4 component vector
1258 \c out variables) from the vertex shader. The value may be as low as 8 with
1259 OpenGL ES 2.0, and 15 with OpenGL ES 3.0 and some Metal devices. Elsewhere,
1260 a typical value is 32.
1261
1262 \value ShadingRateImageTileSize The tile size for shading rate textures. 0
1263 if the QRhi::VariableRateShadingMapWithTexture feature is not supported.
1264 Otherwise a value such as 16, indicating, for example, a tile size of 16x16.
1265 Each byte in the (R8UI) shading rate texture defines then the shading rate
1266 for a tile of 16x16 pixels. See \l QRhiShadingRateMap for details.
1267 */
1268
1269/*!
1270 \class QRhiInitParams
1271 \inmodule QtGuiPrivate
1272 \inheaderfile rhi/qrhi.h
1273 \since 6.6
1274 \brief Base class for backend-specific initialization parameters.
1275
1276 Contains fields that are relevant to all backends.
1277
1278 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1279 for details.
1280 */
1281
1282/*!
1283 \class QRhiDepthStencilClearValue
1284 \inmodule QtGuiPrivate
1285 \inheaderfile rhi/qrhi.h
1286 \since 6.6
1287 \brief Specifies clear values for a depth or stencil buffer.
1288
1289 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1290 for details.
1291 */
1292
1293/*!
1294 \fn QRhiDepthStencilClearValue::QRhiDepthStencilClearValue() = default
1295
1296 Constructs a depth/stencil clear value with depth clear value 1.0f and
1297 stencil clear value 0.
1298 */
1299
1300/*!
1301 Constructs a depth/stencil clear value with depth clear value \a d and
1302 stencil clear value \a s.
1303 */
1304QRhiDepthStencilClearValue::QRhiDepthStencilClearValue(float d, quint32 s)
1305 : m_d(d),
1306 m_s(s)
1307{
1308}
1309
1310/*!
1311 \fn float QRhiDepthStencilClearValue::depthClearValue() const
1312 \return the depth clear value. In most cases this is 1.0f.
1313 */
1314
1315/*!
1316 \fn void QRhiDepthStencilClearValue::setDepthClearValue(float d)
1317 Sets the depth clear value to \a d.
1318 */
1319
1320/*!
1321 \fn quint32 QRhiDepthStencilClearValue::stencilClearValue() const
1322 \return the stencil clear value. In most cases this is 0.
1323 */
1324
1325/*!
1326 \fn void QRhiDepthStencilClearValue::setStencilClearValue(quint32 s)
1327 Sets the stencil clear value to \a s.
1328 */
1329
1330/*!
1331 \fn bool QRhiDepthStencilClearValue::operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1332
1333 \return \c true if the values in the two QRhiDepthStencilClearValue objects
1334 \a a and \a b are equal.
1335 */
1336
1337/*!
1338 \fn bool QRhiDepthStencilClearValue::operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1339
1340 \return \c false if the values in the two QRhiDepthStencilClearValue
1341 objects \a a and \a b are equal; otherwise returns \c true.
1342
1343*/
1344
1345/*!
1346 \fn size_t QRhiDepthStencilClearValue::qHash(const QRhiDepthStencilClearValue &key, size_t seed)
1347 \qhash{QRhiDepthStencilClearValue}
1348 */
1349
1350#ifndef QT_NO_DEBUG_STREAM
1351QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
1352{
1353 QDebugStateSaver saver(dbg);
1354 dbg.nospace() << "QRhiDepthStencilClearValue(depth-clear=" << v.depthClearValue()
1355 << " stencil-clear=" << v.stencilClearValue()
1356 << ')';
1357 return dbg;
1358}
1359#endif
1360
1361/*!
1362 \class QRhiViewport
1363 \inmodule QtGuiPrivate
1364 \inheaderfile rhi/qrhi.h
1365 \since 6.6
1366 \brief Specifies a viewport rectangle.
1367
1368 Used with QRhiCommandBuffer::setViewport().
1369
1370 QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
1371 bottom-left. Negative width or height are not allowed.
1372
1373 Typical usage is like the following:
1374
1375 \code
1376 const QSize outputSizeInPixels = swapchain->currentPixelSize();
1377 const QRhiViewport viewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height());
1378 cb->beginPass(swapchain->currentFrameRenderTarget(), Qt::black, { 1.0f, 0 });
1379 cb->setGraphicsPipeline(ps);
1380 cb->setViewport(viewport);
1381 // ...
1382 \endcode
1383
1384 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1385 for details.
1386
1387 \sa QRhiCommandBuffer::setViewport(), QRhi::clipSpaceCorrMatrix(), QRhiScissor
1388 */
1389
1390/*!
1391 \fn QRhiViewport::QRhiViewport() = default
1392
1393 Constructs a viewport description with an empty rectangle and a depth range
1394 of 0.0f - 1.0f.
1395
1396 \sa QRhi::clipSpaceCorrMatrix()
1397 */
1398
1399/*!
1400 Constructs a viewport description with the rectangle specified by \a x, \a
1401 y, \a w, \a h and the depth range \a minDepth and \a maxDepth.
1402
1403 \note \a x and \a y are assumed to be the bottom-left position. \a w and \a
1404 h should not be negative, the viewport will be ignored by
1405 QRhiCommandBuffer::setViewport() otherwise.
1406
1407 \sa QRhi::clipSpaceCorrMatrix()
1408 */
1409QRhiViewport::QRhiViewport(float x, float y, float w, float h, float minDepth, float maxDepth)
1410 : m_rect { { x, y, w, h } },
1411 m_minDepth(minDepth),
1412 m_maxDepth(maxDepth)
1413{
1414}
1415
1416/*!
1417 \fn std::array<float, 4> QRhiViewport::viewport() const
1418 \return the viewport x, y, width, and height.
1419 */
1420
1421/*!
1422 \fn void QRhiViewport::setViewport(float x, float y, float w, float h)
1423 Sets the viewport's position and size to \a x, \a y, \a w, and \a h.
1424
1425 \note Viewports are specified in a coordinate system that has its origin in
1426 the bottom-left.
1427 */
1428
1429/*!
1430 \fn float QRhiViewport::minDepth() const
1431 \return the minDepth value of the depth range of the viewport.
1432 */
1433
1434/*!
1435 \fn void QRhiViewport::setMinDepth(float minDepth)
1436 Sets the \a minDepth of the depth range of the viewport.
1437 By default this is set to 0.0f.
1438 */
1439
1440/*!
1441 \fn float QRhiViewport::maxDepth() const
1442 \return the maxDepth value of the depth range of the viewport.
1443 */
1444
1445/*!
1446 \fn void QRhiViewport::setMaxDepth(float maxDepth)
1447 Sets the \a maxDepth of the depth range of the viewport.
1448 By default this is set to 1.0f.
1449 */
1450
1451/*!
1452 \fn bool QRhiViewport::operator==(const QRhiViewport &a, const QRhiViewport &b) noexcept
1453
1454 \return \c true if the values in the two QRhiViewport objects
1455 \a a and \a b are equal.
1456 */
1457
1458/*!
1459 \fn bool QRhiViewport::operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept
1460
1461 \return \c false if the values in the two QRhiViewport
1462 objects \a a and \a b are equal; otherwise returns \c true.
1463*/
1464
1465/*!
1466 \fn size_t QRhiViewport::qHash(const QRhiViewport &key, size_t seed)
1467 \qhash{QRhiViewport}
1468 */
1469
1470#ifndef QT_NO_DEBUG_STREAM
1471QDebug operator<<(QDebug dbg, const QRhiViewport &v)
1472{
1473 QDebugStateSaver saver(dbg);
1474 const std::array<float, 4> r = v.viewport();
1475 dbg.nospace() << "QRhiViewport(bottom-left-x=" << r[0]
1476 << " bottom-left-y=" << r[1]
1477 << " width=" << r[2]
1478 << " height=" << r[3]
1479 << " minDepth=" << v.minDepth()
1480 << " maxDepth=" << v.maxDepth()
1481 << ')';
1482 return dbg;
1483}
1484#endif
1485
1486/*!
1487 \class QRhiScissor
1488 \inmodule QtGuiPrivate
1489 \inheaderfile rhi/qrhi.h
1490 \since 6.6
1491 \brief Specifies a scissor rectangle.
1492
1493 Used with QRhiCommandBuffer::setScissor(). Setting a scissor rectangle is
1494 only possible with a QRhiGraphicsPipeline that has
1495 QRhiGraphicsPipeline::UsesScissor set.
1496
1497 QRhi assumes OpenGL-style scissor coordinates, meaning x and y are
1498 bottom-left. Negative width or height are not allowed. However, apart from
1499 that, the flexible OpenGL semantics apply: negative x and y, partially out
1500 of bounds rectangles, etc. will be handled gracefully, clamping as
1501 appropriate. Therefore, any rendering logic targeting OpenGL can feed
1502 scissor rectangles into QRhiScissor as-is, without any adaptation.
1503
1504 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1505 for details.
1506
1507 \sa QRhiCommandBuffer::setScissor(), QRhiViewport
1508 */
1509
1510/*!
1511 \fn QRhiScissor::QRhiScissor() = default
1512
1513 Constructs an empty scissor.
1514 */
1515
1516/*!
1517 Constructs a scissor with the rectangle specified by \a x, \a y, \a w, and
1518 \a h.
1519
1520 \note \a x and \a y are assumed to be the bottom-left position. Negative \a w
1521 or \a h are not allowed, such scissor rectangles will be ignored by
1522 QRhiCommandBuffer. Other than that, the flexible OpenGL semantics apply:
1523 negative x and y, partially out of bounds rectangles, etc. will be handled
1524 gracefully, clamping as appropriate.
1525 */
1526QRhiScissor::QRhiScissor(int x, int y, int w, int h)
1527 : m_rect { { x, y, w, h } }
1528{
1529}
1530
1531/*!
1532 \fn std::array<int, 4> QRhiScissor::scissor() const
1533 \return the scissor position and size.
1534 */
1535
1536/*!
1537 \fn void QRhiScissor::setScissor(int x, int y, int w, int h)
1538 Sets the scissor position and size to \a x, \a y, \a w, \a h.
1539
1540 \note The position is always expected to be specified in a coordinate
1541 system that has its origin in the bottom-left corner, like OpenGL.
1542 */
1543
1544/*!
1545 \fn bool QRhiScissor::operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept
1546
1547 \return \c true if the values in the two QRhiScissor objects
1548 \a a and \a b are equal.
1549 */
1550
1551/*!
1552 \fn bool QRhiScissor::operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept
1553
1554 \return \c false if the values in the two QRhiScissor
1555 objects \a a and \a b are equal; otherwise returns \c true.
1556*/
1557
1558/*!
1559 \fn size_t QRhiScissor::qHash(const QRhiScissor &key, size_t seed)
1560 \qhash{QRhiScissor}
1561 */
1562
1563#ifndef QT_NO_DEBUG_STREAM
1564QDebug operator<<(QDebug dbg, const QRhiScissor &s)
1565{
1566 QDebugStateSaver saver(dbg);
1567 const std::array<int, 4> r = s.scissor();
1568 dbg.nospace() << "QRhiScissor(bottom-left-x=" << r[0]
1569 << " bottom-left-y=" << r[1]
1570 << " width=" << r[2]
1571 << " height=" << r[3]
1572 << ')';
1573 return dbg;
1574}
1575#endif
1576
1577/*!
1578 \class QRhiVertexInputBinding
1579 \inmodule QtGuiPrivate
1580 \inheaderfile rhi/qrhi.h
1581 \since 6.6
1582 \brief Describes a vertex input binding.
1583
1584 Specifies the stride (in bytes, must be a multiple of 4), the
1585 classification and optionally the instance step rate.
1586
1587 As an example, assume a vertex shader with the following inputs:
1588
1589 \badcode
1590 layout(location = 0) in vec4 position;
1591 layout(location = 1) in vec2 texcoord;
1592 \endcode
1593
1594 Now let's assume also that 3 component vertex positions \c{(x, y, z)} and 2
1595 component texture coordinates \c{(u, v)} are provided in a non-interleaved
1596 format in a buffer (or separate buffers even). Defining two bindings
1597 could then be done like this:
1598
1599 \code
1600 QRhiVertexInputLayout inputLayout;
1601 inputLayout.setBindings({
1602 { 3 * sizeof(float) },
1603 { 2 * sizeof(float) }
1604 });
1605 \endcode
1606
1607 Only the stride is interesting here since instancing is not used. The
1608 binding number is given by the index of the QRhiVertexInputBinding
1609 element in the bindings vector of the QRhiVertexInputLayout.
1610
1611 Once a graphics pipeline with this vertex input layout is bound, the vertex
1612 inputs could be set up like the following for drawing a cube with 36
1613 vertices, assuming we have a single buffer with first the positions and
1614 then the texture coordinates:
1615
1616 \code
1617 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1618 { cubeBuf, 0 },
1619 { cubeBuf, 36 * 3 * sizeof(float) }
1620 };
1621 cb->setVertexInput(0, 2, vbufBindings);
1622 \endcode
1623
1624 Note how the index defined by \c {startBinding + i}, where \c i is the
1625 index in the second argument of
1626 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}, matches the
1627 index of the corresponding entry in the \c bindings vector of the
1628 QRhiVertexInputLayout.
1629
1630 \note the stride must always be a multiple of 4.
1631
1632 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1633 for details.
1634
1635 \sa QRhiCommandBuffer::setVertexInput()
1636 */
1637
1638/*!
1639 \enum QRhiVertexInputBinding::Classification
1640 Describes the input data classification.
1641
1642 \value PerVertex Data is per-vertex
1643 \value PerInstance Data is per-instance
1644 */
1645
1646/*!
1647 \fn QRhiVertexInputBinding::QRhiVertexInputBinding() = default
1648
1649 Constructs a default vertex input binding description.
1650 */
1651
1652/*!
1653 Constructs a vertex input binding description with the specified \a stride,
1654 classification \a cls, and instance step rate \a stepRate.
1655
1656 \note \a stepRate other than 1 is only supported when
1657 QRhi::CustomInstanceStepRate is reported to be supported.
1658 */
1659QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cls, quint32 stepRate)
1660 : m_stride(stride),
1661 m_classification(cls),
1662 m_instanceStepRate(stepRate)
1663{
1664}
1665
1666/*!
1667 \fn quint32 QRhiVertexInputBinding::stride() const
1668 \return the stride in bytes.
1669 */
1670
1671/*!
1672 \fn void QRhiVertexInputBinding::setStride(quint32 s)
1673 Sets the stride to \a s.
1674 */
1675
1676/*!
1677 \fn QRhiVertexInputBinding::Classification QRhiVertexInputBinding::classification() const
1678 \return the input data classification.
1679 */
1680
1681/*!
1682 \fn void QRhiVertexInputBinding::setClassification(Classification c)
1683 Sets the input data classification \a c. By default this is set to PerVertex.
1684 */
1685
1686/*!
1687 \fn quint32 QRhiVertexInputBinding::instanceStepRate() const
1688 \return the instance step rate.
1689 */
1690
1691/*!
1692 \fn void QRhiVertexInputBinding::setInstanceStepRate(quint32 rate)
1693 Sets the instance step \a rate. By default this is set to 1.
1694 */
1695
1696/*!
1697 \fn bool QRhiVertexInputBinding::operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1698
1699 \return \c true if the values in the two QRhiVertexInputBinding objects
1700 \a a and \a b are equal.
1701 */
1702
1703/*!
1704 \fn bool QRhiVertexInputBinding::operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1705
1706 \return \c false if the values in the two QRhiVertexInputBinding
1707 objects \a a and \a b are equal; otherwise returns \c true.
1708*/
1709
1710/*!
1711 \fn size_t QRhiVertexInputBinding::qHash(const QRhiVertexInputBinding &key, size_t seed)
1712 \qhash{QRhiVertexInputBinding}
1713 */
1714
1715#ifndef QT_NO_DEBUG_STREAM
1716QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
1717{
1718 QDebugStateSaver saver(dbg);
1719 dbg.nospace() << "QRhiVertexInputBinding(stride=" << b.stride()
1720 << " cls=" << b.classification()
1721 << " step-rate=" << b.instanceStepRate()
1722 << ')';
1723 return dbg;
1724}
1725#endif
1726
1727/*!
1728 \class QRhiVertexInputAttribute
1729 \inmodule QtGuiPrivate
1730 \inheaderfile rhi/qrhi.h
1731 \since 6.6
1732 \brief Describes a single vertex input element.
1733
1734 The members specify the binding number, location, format, and offset for a
1735 single vertex input element.
1736
1737 \note For HLSL it is assumed that the vertex shader translated from SPIR-V
1738 uses
1739 \c{TEXCOORD<location>} as the semantic for each input. Hence no separate
1740 semantic name and index.
1741
1742 As an example, assume a vertex shader with the following inputs:
1743
1744 \badcode
1745 layout(location = 0) in vec4 position;
1746 layout(location = 1) in vec2 texcoord;
1747 \endcode
1748
1749 Now let's assume that we have 3 component vertex positions \c{(x, y, z)}
1750 and 2 component texture coordinates \c{(u, v)} are provided in a
1751 non-interleaved format in a buffer (or separate buffers even). Once two
1752 bindings are defined, the attributes could be specified as:
1753
1754 \code
1755 QRhiVertexInputLayout inputLayout;
1756 inputLayout.setBindings({
1757 { 3 * sizeof(float) },
1758 { 2 * sizeof(float) }
1759 });
1760 inputLayout.setAttributes({
1761 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1762 { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
1763 });
1764 \endcode
1765
1766 Once a graphics pipeline with this vertex input layout is bound, the vertex
1767 inputs could be set up like the following for drawing a cube with 36
1768 vertices, assuming we have a single buffer with first the positions and
1769 then the texture coordinates:
1770
1771 \code
1772 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1773 { cubeBuf, 0 },
1774 { cubeBuf, 36 * 3 * sizeof(float) }
1775 };
1776 cb->setVertexInput(0, 2, vbufBindings);
1777 \endcode
1778
1779 When working with interleaved data, there will typically be just one
1780 binding, with multiple attributes referring to that same buffer binding
1781 point:
1782
1783 \code
1784 QRhiVertexInputLayout inputLayout;
1785 inputLayout.setBindings({
1786 { 5 * sizeof(float) }
1787 });
1788 inputLayout.setAttributes({
1789 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1790 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
1791 });
1792 \endcode
1793
1794 and then:
1795
1796 \code
1797 const QRhiCommandBuffer::VertexInput vbufBinding(interleavedCubeBuf, 0);
1798 cb->setVertexInput(0, 1, &vbufBinding);
1799 \endcode
1800
1801 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1802 for details.
1803
1804 \sa QRhiCommandBuffer::setVertexInput()
1805 */
1806
1807/*!
1808 \enum QRhiVertexInputAttribute::Format
1809 Specifies the type of the element data.
1810
1811 \value Float4 Four component float vector
1812 \value Float3 Three component float vector
1813 \value Float2 Two component float vector
1814 \value Float Float
1815 \value UNormByte4 Four component normalized unsigned byte vector
1816 \value UNormByte2 Two component normalized unsigned byte vector
1817 \value UNormByte Normalized unsigned byte
1818 \value UInt4 Four component unsigned integer vector
1819 \value UInt3 Three component unsigned integer vector
1820 \value UInt2 Two component unsigned integer vector
1821 \value UInt Unsigned integer
1822 \value SInt4 Four component signed integer vector
1823 \value SInt3 Three component signed integer vector
1824 \value SInt2 Two component signed integer vector
1825 \value SInt Signed integer
1826 \value Half4 Four component half precision (16 bit) float vector
1827 \value Half3 Three component half precision (16 bit) float vector
1828 \value Half2 Two component half precision (16 bit) float vector
1829 \value Half Half precision (16 bit) float
1830 \value UShort4 Four component unsigned short (16 bit) integer vector
1831 \value UShort3 Three component unsigned short (16 bit) integer vector
1832 \value UShort2 Two component unsigned short (16 bit) integer vector
1833 \value UShort Unsigned short (16 bit) integer
1834 \value SShort4 Four component signed short (16 bit) integer vector
1835 \value SShort3 Three component signed short (16 bit) integer vector
1836 \value SShort2 Two component signed short (16 bit) integer vector
1837 \value SShort Signed short (16 bit) integer
1838
1839 \note Support for half precision floating point attributes is indicated at
1840 run time by the QRhi::Feature::HalfAttributes feature flag.
1841
1842 \note Direct3D 11/12 supports 16 bit input attributes, but does not support
1843 the Half3, UShort3 or SShort3 types. The D3D backends pass through Half3 as
1844 Half4, UShort3 as UShort4, and SShort3 as SShort4. To ensure cross platform
1845 compatibility, 16 bit inputs should be padded to 8 bytes.
1846 */
1847
1848/*!
1849 \fn QRhiVertexInputAttribute::QRhiVertexInputAttribute() = default
1850
1851 Constructs a default vertex input attribute description.
1852 */
1853
1854/*!
1855 Constructs a vertex input attribute description with the specified \a
1856 binding number, \a location, \a format, and \a offset.
1857
1858 \a matrixSlice should be -1 except when this attribute corresponds to a row
1859 or column of a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming
1860 4 consecutive vertex input locations), in which case it is the index of the
1861 row or column. \c{location - matrixSlice} must always be equal to the \c
1862 location for the first row or column of the unrolled matrix.
1863 */
1864QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset, int matrixSlice)
1865 : m_binding(binding),
1866 m_location(location),
1867 m_format(format),
1868 m_offset(offset),
1869 m_matrixSlice(matrixSlice)
1870{
1871}
1872
1873/*!
1874 \fn int QRhiVertexInputAttribute::binding() const
1875 \return the binding point index.
1876 */
1877
1878/*!
1879 \fn void QRhiVertexInputAttribute::setBinding(int b)
1880 Sets the binding point index to \a b.
1881 By default this is set to 0.
1882 */
1883
1884/*!
1885 \fn int QRhiVertexInputAttribute::location() const
1886 \return the location of the vertex input element.
1887 */
1888
1889/*!
1890 \fn void QRhiVertexInputAttribute::setLocation(int loc)
1891 Sets the location of the vertex input element to \a loc.
1892 By default this is set to 0.
1893 */
1894
1895/*!
1896 \fn QRhiVertexInputAttribute::Format QRhiVertexInputAttribute::format() const
1897 \return the format of the vertex input element.
1898 */
1899
1900/*!
1901 \fn void QRhiVertexInputAttribute::setFormat(Format f)
1902 Sets the format of the vertex input element to \a f.
1903 By default this is set to Float4.
1904 */
1905
1906/*!
1907 \fn quint32 QRhiVertexInputAttribute::offset() const
1908 \return the byte offset for the input element.
1909 */
1910
1911/*!
1912 \fn void QRhiVertexInputAttribute::setOffset(quint32 ofs)
1913 Sets the byte offset for the input element to \a ofs.
1914 */
1915
1916/*!
1917 \fn int QRhiVertexInputAttribute::matrixSlice() const
1918
1919 \return the matrix slice if the input element corresponds to a row or
1920 column of a matrix, or -1 if not relevant.
1921 */
1922
1923/*!
1924 \fn void QRhiVertexInputAttribute::setMatrixSlice(int slice)
1925
1926 Sets the matrix \a slice. By default this is set to -1, and should be set
1927 to a >= 0 value only when this attribute corresponds to a row or column of
1928 a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming 4
1929 consecutive vertex input locations), in which case it is the index of the
1930 row or column. \c{location - matrixSlice} must always be equal to the \c
1931 location for the first row or column of the unrolled matrix.
1932 */
1933
1934/*!
1935 \fn bool QRhiVertexInputAttribute::operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
1936
1937 \return \c true if the values in the two QRhiVertexInputAttribute objects
1938 \a a and \a b are equal.
1939 */
1940
1941/*!
1942 \fn bool QRhiVertexInputAttribute::operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
1943
1944 \return \c false if the values in the two QRhiVertexInputAttribute
1945 objects \a a and \a b are equal; otherwise returns \c true.
1946*/
1947
1948/*!
1949 \fn size_t QRhiVertexInputAttribute::qHash(const QRhiVertexInputAttribute &key, size_t seed)
1950 \qhash{QRhiVertexInputAttribute}
1951 */
1952
1953#ifndef QT_NO_DEBUG_STREAM
1954QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a)
1955{
1956 QDebugStateSaver saver(dbg);
1957 dbg.nospace() << "QRhiVertexInputAttribute(binding=" << a.binding()
1958 << " location=" << a.location()
1959 << " format=" << a.format()
1960 << " offset=" << a.offset()
1961 << ')';
1962 return dbg;
1963}
1964#endif
1965
1966QRhiVertexInputAttribute::Format QRhiImplementation::shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const
1967{
1968 switch (type) {
1969 case QShaderDescription::Vec4:
1970 return QRhiVertexInputAttribute::Float4;
1971 case QShaderDescription::Vec3:
1972 return QRhiVertexInputAttribute::Float3;
1973 case QShaderDescription::Vec2:
1974 return QRhiVertexInputAttribute::Float2;
1975 case QShaderDescription::Float:
1976 return QRhiVertexInputAttribute::Float;
1977
1978 case QShaderDescription::Int4:
1979 return QRhiVertexInputAttribute::SInt4;
1980 case QShaderDescription::Int3:
1981 return QRhiVertexInputAttribute::SInt3;
1982 case QShaderDescription::Int2:
1983 return QRhiVertexInputAttribute::SInt2;
1984 case QShaderDescription::Int:
1985 return QRhiVertexInputAttribute::SInt;
1986
1987 case QShaderDescription::Uint4:
1988 return QRhiVertexInputAttribute::UInt4;
1989 case QShaderDescription::Uint3:
1990 return QRhiVertexInputAttribute::UInt3;
1991 case QShaderDescription::Uint2:
1992 return QRhiVertexInputAttribute::UInt2;
1993 case QShaderDescription::Uint:
1994 return QRhiVertexInputAttribute::UInt;
1995
1996 case QShaderDescription::Half4:
1997 return QRhiVertexInputAttribute::Half4;
1998 case QShaderDescription::Half3:
1999 return QRhiVertexInputAttribute::Half3;
2000 case QShaderDescription::Half2:
2001 return QRhiVertexInputAttribute::Half2;
2002 case QShaderDescription::Half:
2003 return QRhiVertexInputAttribute::Half;
2004
2005 default:
2006 Q_UNREACHABLE_RETURN(QRhiVertexInputAttribute::Float);
2007 }
2008}
2009
2010quint32 QRhiImplementation::byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const
2011{
2012 switch (format) {
2013 case QRhiVertexInputAttribute::Float4:
2014 return 4 * sizeof(float);
2015 case QRhiVertexInputAttribute::Float3:
2016 return 4 * sizeof(float); // vec3 still takes 16 bytes
2017 case QRhiVertexInputAttribute::Float2:
2018 return 2 * sizeof(float);
2019 case QRhiVertexInputAttribute::Float:
2020 return sizeof(float);
2021
2022 case QRhiVertexInputAttribute::UNormByte4:
2023 return 4 * sizeof(quint8);
2024 case QRhiVertexInputAttribute::UNormByte2:
2025 return 2 * sizeof(quint8);
2026 case QRhiVertexInputAttribute::UNormByte:
2027 return sizeof(quint8);
2028
2029 case QRhiVertexInputAttribute::UInt4:
2030 return 4 * sizeof(quint32);
2031 case QRhiVertexInputAttribute::UInt3:
2032 return 4 * sizeof(quint32); // ivec3 still takes 16 bytes
2033 case QRhiVertexInputAttribute::UInt2:
2034 return 2 * sizeof(quint32);
2035 case QRhiVertexInputAttribute::UInt:
2036 return sizeof(quint32);
2037
2038 case QRhiVertexInputAttribute::SInt4:
2039 return 4 * sizeof(qint32);
2040 case QRhiVertexInputAttribute::SInt3:
2041 return 4 * sizeof(qint32); // uvec3 still takes 16 bytes
2042 case QRhiVertexInputAttribute::SInt2:
2043 return 2 * sizeof(qint32);
2044 case QRhiVertexInputAttribute::SInt:
2045 return sizeof(qint32);
2046
2047 case QRhiVertexInputAttribute::Half4:
2048 return 4 * sizeof(qfloat16);
2049 case QRhiVertexInputAttribute::Half3:
2050 return 4 * sizeof(qfloat16); // half3 still takes 8 bytes
2051 case QRhiVertexInputAttribute::Half2:
2052 return 2 * sizeof(qfloat16);
2053 case QRhiVertexInputAttribute::Half:
2054 return sizeof(qfloat16);
2055
2056 case QRhiVertexInputAttribute::UShort4:
2057 return 4 * sizeof(quint16);
2058 case QRhiVertexInputAttribute::UShort3:
2059 return 4 * sizeof(quint16); // ivec3 still takes 8 bytes
2060 case QRhiVertexInputAttribute::UShort2:
2061 return 2 * sizeof(quint16);
2062 case QRhiVertexInputAttribute::UShort:
2063 return sizeof(quint16);
2064
2065 case QRhiVertexInputAttribute::SShort4:
2066 return 4 * sizeof(qint16);
2067 case QRhiVertexInputAttribute::SShort3:
2068 return 4 * sizeof(qint16); // uvec3 still takes 8 bytes
2069 case QRhiVertexInputAttribute::SShort2:
2070 return 2 * sizeof(qint16);
2071 case QRhiVertexInputAttribute::SShort:
2072 return sizeof(qint16);
2073
2074 default:
2075 Q_UNREACHABLE_RETURN(1);
2076 }
2077}
2078
2079/*!
2080 \class QRhiVertexInputLayout
2081 \inmodule QtGuiPrivate
2082 \inheaderfile rhi/qrhi.h
2083 \since 6.6
2084 \brief Describes the layout of vertex inputs consumed by a vertex shader.
2085
2086 The vertex input layout is defined by the collections of
2087 QRhiVertexInputBinding and QRhiVertexInputAttribute.
2088
2089 As an example, let's assume that we have a single buffer with 3 component
2090 vertex positions and 2 component UV coordinates interleaved (\c x, \c y, \c
2091 z, \c u, \c v), that the position and UV are expected at input locations 0
2092 and 1 by the vertex shader, and that the vertex buffer will be bound at
2093 binding point 0 using
2094 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()} later on:
2095
2096 \code
2097 QRhiVertexInputLayout inputLayout;
2098 inputLayout.setBindings({
2099 { 5 * sizeof(float) }
2100 });
2101 inputLayout.setAttributes({
2102 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
2103 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
2104 });
2105 \endcode
2106
2107 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2108 for details.
2109 */
2110
2111/*!
2112 \fn QRhiVertexInputLayout::QRhiVertexInputLayout() = default
2113
2114 Constructs an empty vertex input layout description.
2115 */
2116
2117/*!
2118 \fn void QRhiVertexInputLayout::setBindings(std::initializer_list<QRhiVertexInputBinding> list)
2119 Sets the bindings from the specified \a list.
2120 */
2121
2122/*!
2123 \fn template<typename InputIterator> void QRhiVertexInputLayout::setBindings(InputIterator first, InputIterator last)
2124 Sets the bindings using the iterators \a first and \a last.
2125 */
2126
2127/*!
2128 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cbeginBindings() const
2129 \return a const iterator pointing to the first item in the binding list.
2130 */
2131
2132/*!
2133 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cendBindings() const
2134 \return a const iterator pointing just after the last item in the binding list.
2135 */
2136
2137/*!
2138 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::bindingAt(qsizetype index) const
2139 \return the binding at the given \a index.
2140 */
2141
2142/*!
2143 \fn qsizetype QRhiVertexInputLayout::bindingCount() const
2144 \return the number of bindings.
2145 */
2146
2147/*!
2148 \fn void QRhiVertexInputLayout::setAttributes(std::initializer_list<QRhiVertexInputAttribute> list)
2149 Sets the attributes from the specified \a list.
2150 */
2151
2152/*!
2153 \fn template<typename InputIterator> void QRhiVertexInputLayout::setAttributes(InputIterator first, InputIterator last)
2154 Sets the attributes using the iterators \a first and \a last.
2155 */
2156
2157/*!
2158 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cbeginAttributes() const
2159 \return a const iterator pointing to the first item in the attribute list.
2160 */
2161
2162/*!
2163 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cendAttributes() const
2164 \return a const iterator pointing just after the last item in the attribute list.
2165 */
2166
2167/*!
2168 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::attributeAt(qsizetype index) const
2169 \return the attribute at the given \a index.
2170 */
2171
2172/*!
2173 \fn qsizetype QRhiVertexInputLayout::attributeCount() const
2174 \return the number of attributes.
2175 */
2176
2177/*!
2178 \fn bool QRhiVertexInputLayout::operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2179
2180 \return \c true if the values in the two QRhiVertexInputLayout objects
2181 \a a and \a b are equal.
2182 */
2183
2184/*!
2185 \fn bool QRhiVertexInputLayout::operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2186
2187 \return \c false if the values in the two QRhiVertexInputLayout
2188 objects \a a and \a b are equal; otherwise returns \c true.
2189*/
2190
2191/*!
2192 \fn size_t QRhiVertexInputLayout::qHash(const QRhiVertexInputLayout &key, size_t seed)
2193 \qhash{QRhiVertexInputLayout}
2194 */
2195
2196#ifndef QT_NO_DEBUG_STREAM
2197QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
2198{
2199 QDebugStateSaver saver(dbg);
2200 dbg.nospace() << "QRhiVertexInputLayout(bindings=" << v.m_bindings
2201 << " attributes=" << v.m_attributes
2202 << ')';
2203 return dbg;
2204}
2205#endif
2206
2207/*!
2208 \class QRhiShaderStage
2209 \inmodule QtGuiPrivate
2210 \inheaderfile rhi/qrhi.h
2211 \since 6.6
2212 \brief Specifies the type and the shader code for a shader stage in the pipeline.
2213
2214 When setting up a QRhiGraphicsPipeline, a collection of shader stages are
2215 specified. The QRhiShaderStage contains a QShader and some associated
2216 metadata, such as the graphics pipeline stage, and the
2217 \l{QShader::Variant}{shader variant} to select. There is no need to specify
2218 the shader language or version because the QRhi backend in use at runtime
2219 will take care of choosing the appropriate shader version from the
2220 collection within the QShader.
2221
2222 The typical usage is in combination with
2223 QRhiGraphicsPipeline::setShaderStages(), shown here with a simple approach
2224 to load the QShader from \c{.qsb} files generated offline or at build time:
2225
2226 \code
2227 QShader getShader(const QString &name)
2228 {
2229 QFile f(name);
2230 return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
2231 }
2232
2233 QShader vs = getShader("material.vert.qsb");
2234 QShader fs = getShader("material.frag.qsb");
2235 pipeline->setShaderStages({
2236 { QRhiShaderStage::Vertex, vs },
2237 { QRhiShaderStage::Fragment, fs }
2238 });
2239 \endcode
2240
2241 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2242 for details.
2243 */
2244
2245/*!
2246 \enum QRhiShaderStage::Type
2247 Specifies the type of the shader stage.
2248
2249 \value Vertex Vertex stage
2250
2251 \value TessellationControl Tessellation control (hull shader) stage. Must
2252 be used only when the QRhi::Tessellation feature is supported.
2253
2254 \value TessellationEvaluation Tessellation evaluation (domain shader)
2255 stage. Must be used only when the QRhi::Tessellation feature is supported.
2256
2257 \value Fragment Fragment (pixel shader) stage
2258
2259 \value Compute Compute stage. Must be used only when the QRhi::Compute
2260 feature is supported.
2261
2262 \value Geometry Geometry stage. Must be used only when the
2263 QRhi::GeometryShader feature is supported.
2264 */
2265
2266/*!
2267 \fn QRhiShaderStage::QRhiShaderStage() = default
2268
2269 Constructs a shader stage description for the vertex stage with an empty
2270 QShader.
2271 */
2272
2273/*!
2274 \fn QRhiShaderStage::Type QRhiShaderStage::type() const
2275 \return the type of the stage.
2276 */
2277
2278/*!
2279 \fn void QRhiShaderStage::setType(Type t)
2280
2281 Sets the type of the stage to \a t. Setters should rarely be needed in
2282 pratice. Most applications will likely use the QRhiShaderStage constructor
2283 in most cases.
2284 */
2285
2286/*!
2287 \fn QShader QRhiShaderStage::shader() const
2288 \return the QShader to be used for this stage in the graphics pipeline.
2289 */
2290
2291/*!
2292 \fn void QRhiShaderStage::setShader(const QShader &s)
2293 Sets the shader collection \a s.
2294 */
2295
2296/*!
2297 \fn QShader::Variant QRhiShaderStage::shaderVariant() const
2298 \return the requested shader variant.
2299 */
2300
2301/*!
2302 \fn void QRhiShaderStage::setShaderVariant(QShader::Variant v)
2303 Sets the requested shader variant \a v.
2304 */
2305
2306/*!
2307 Constructs a shader stage description with the \a type of the stage and the
2308 \a shader.
2309
2310 The shader variant \a v defaults to QShader::StandardShader. A
2311 QShader contains multiple source and binary versions of a shader.
2312 In addition, it can also contain variants of the shader with slightly
2313 modified code. \a v can then be used to select the desired variant.
2314 */
2315QRhiShaderStage::QRhiShaderStage(Type type, const QShader &shader, QShader::Variant v)
2316 : m_type(type),
2317 m_shader(shader),
2318 m_shaderVariant(v)
2319{
2320}
2321
2322/*!
2323 \fn bool QRhiShaderStage::operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2324
2325 \return \c true if the values in the two QRhiShaderStage objects
2326 \a a and \a b are equal.
2327 */
2328
2329/*!
2330 \fn bool QRhiShaderStage::operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2331
2332 \return \c false if the values in the two QRhiShaderStage
2333 objects \a a and \a b are equal; otherwise returns \c true.
2334*/
2335
2336/*!
2337 \fn size_t QRhiShaderStage::qHash(const QRhiShaderStage &key, size_t seed)
2338 \qhash{QRhiShaderStage}
2339 */
2340
2341#ifndef QT_NO_DEBUG_STREAM
2342QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
2343{
2344 QDebugStateSaver saver(dbg);
2345 dbg.nospace() << "QRhiShaderStage(type=" << s.type()
2346 << " shader=" << s.shader()
2347 << " variant=" << s.shaderVariant()
2348 << ')';
2349 return dbg;
2350}
2351#endif
2352
2353/*!
2354 \class QRhiColorAttachment
2355 \inmodule QtGuiPrivate
2356 \inheaderfile rhi/qrhi.h
2357 \since 6.6
2358 \brief Describes the a single color attachment of a render target.
2359
2360 A color attachment is either a QRhiTexture or a QRhiRenderBuffer. The
2361 former, i.e. when texture() is set, is used in most cases.
2362 QRhiColorAttachment is commonly used in combination with
2363 QRhiTextureRenderTargetDescription.
2364
2365 \note texture() and renderBuffer() cannot be both set (be non-null at the
2366 same time).
2367
2368 Setting renderBuffer instead is recommended only when multisampling is
2369 needed. Relying on QRhi::MultisampleRenderBuffer is a better choice than
2370 QRhi::MultisampleTexture in practice since the former is available in more
2371 run time configurations (e.g. when running on OpenGL ES 3.0 which has no
2372 support for multisample textures, but does support multisample
2373 renderbuffers).
2374
2375 When targeting a non-multisample texture, the layer() and level() indicate
2376 the targeted layer (face index \c{0-5} for cubemaps) and mip level. For 3D
2377 textures layer() specifies the slice (one 2D image within the 3D texture)
2378 to render to. For texture arrays layer() is the array index.
2379
2380 When texture() or renderBuffer() is multisample, resolveTexture() can be
2381 set optionally. When set, samples are resolved automatically into that
2382 (non-multisample) texture at the end of the render pass. When rendering
2383 into a multisample renderbuffers, this is the only way to get resolved,
2384 non-multisample content out of them. Multisample textures allow sampling in
2385 shaders so for them this is just one option.
2386
2387 \note when resolving is enabled, the multisample data may not be written
2388 out at all. This means that the multisample texture() must not be used
2389 afterwards with shaders for sampling when resolveTexture() is set.
2390
2391 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2392 for details.
2393
2394 \sa QRhiTextureRenderTargetDescription
2395 */
2396
2397/*!
2398 \fn QRhiColorAttachment::QRhiColorAttachment() = default
2399
2400 Constructs an empty color attachment description.
2401 */
2402
2403/*!
2404 Constructs a color attachment description that specifies \a texture as the
2405 associated color buffer.
2406 */
2407QRhiColorAttachment::QRhiColorAttachment(QRhiTexture *texture)
2408 : m_texture(texture)
2409{
2410}
2411
2412/*!
2413 Constructs a color attachment description that specifies \a renderBuffer as
2414 the associated color buffer.
2415 */
2416QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
2417 : m_renderBuffer(renderBuffer)
2418{
2419}
2420
2421/*!
2422 \fn QRhiTexture *QRhiColorAttachment::texture() const
2423
2424 \return the texture this attachment description references, or \nullptr if
2425 there is none.
2426 */
2427
2428/*!
2429 \fn void QRhiColorAttachment::setTexture(QRhiTexture *tex)
2430
2431 Sets the texture \a tex.
2432
2433 \note texture() and renderBuffer() cannot be both set (be non-null at the
2434 same time).
2435 */
2436
2437/*!
2438 \fn QRhiRenderBuffer *QRhiColorAttachment::renderBuffer() const
2439
2440 \return the renderbuffer this attachment description references, or
2441 \nullptr if there is none.
2442
2443 In practice associating a QRhiRenderBuffer with a QRhiColorAttachment makes
2444 the most sense when setting up multisample rendering via a multisample
2445 \l{QRhiRenderBuffer::Type}{color} renderbuffer that is then resolved into a
2446 non-multisample texture at the end of the render pass.
2447 */
2448
2449/*!
2450 \fn void QRhiColorAttachment::setRenderBuffer(QRhiRenderBuffer *rb)
2451
2452 Sets the renderbuffer \a rb.
2453
2454 \note texture() and renderBuffer() cannot be both set (be non-null at the
2455 same time).
2456 */
2457
2458/*!
2459 \fn int QRhiColorAttachment::layer() const
2460 \return the layer index (cubemap face or array layer). 0 by default.
2461 */
2462
2463/*!
2464 \fn void QRhiColorAttachment::setLayer(int layer)
2465 Sets the \a layer index.
2466 */
2467
2468/*!
2469 \fn int QRhiColorAttachment::level() const
2470 \return the mip level. 0 by default.
2471 */
2472
2473/*!
2474 \fn void QRhiColorAttachment::setLevel(int level)
2475 Sets the mip \a level.
2476 */
2477
2478/*!
2479 \fn QRhiTexture *QRhiColorAttachment::resolveTexture() const
2480
2481 \return the resolve texture this attachment description references, or
2482 \nullptr if there is none.
2483
2484 Setting a non-null resolve texture is applicable when the attachment
2485 references a multisample texture or renderbuffer. The QRhiTexture in the
2486 resolveTexture() is then a non-multisample 2D texture (or texture array)
2487 with the same size (but a sample count of 1). The multisample content is
2488 automatically resolved into this texture at the end of each render pass.
2489 */
2490
2491/*!
2492 \fn void QRhiColorAttachment::setResolveTexture(QRhiTexture *tex)
2493
2494 Sets the resolve texture \a tex.
2495
2496 \a tex is expected to be a 2D texture or a 2D texture array. In either
2497 case, resolving targets a single mip level of a single layer (array
2498 element) of \a tex. The mip level and array layer are specified by
2499 resolveLevel() and resolveLayer().
2500
2501 An exception is \l{setMultiViewCount()}{multiview}: when the color
2502 attachment is associated with a texture array and multiview is enabled, the
2503 resolve texture must also be a texture array with sufficient elements for
2504 all views. In this case all elements that correspond to views are resolved
2505 automatically; the behavior is similar to the following pseudo-code:
2506 \badcode
2507 for (i = 0; i < multiViewCount(); ++i)
2508 resolve texture's layer() + i into resolveTexture's resolveLayer() + i
2509 \endcode
2510
2511 Setting a non-multisample texture to resolve a multisample texture or
2512 renderbuffer automatically at the end of the render pass is often
2513 preferable to working with multisample textures (and not setting a resolve
2514 texture), because it avoids the need for writing dedicated fragment shaders
2515 that work exclusively with multisample textures (\c sampler2DMS, \c
2516 texelFetch, etc.), and rather allows using the same shader as one would if
2517 the attachment's texture was not multisampled to begin with. This comes at
2518 the expense of an additional resource (the non-multisample \a tex).
2519 */
2520
2521/*!
2522 \fn int QRhiColorAttachment::resolveLayer() const
2523 \return the currently set resolve texture layer. Defaults to 0.
2524 */
2525
2526/*!
2527 \fn void QRhiColorAttachment::setResolveLayer(int layer)
2528 Sets the resolve texture \a layer to use.
2529 */
2530
2531/*!
2532 \fn int QRhiColorAttachment::resolveLevel() const
2533 \return the currently set resolve texture mip level. Defaults to 0.
2534 */
2535
2536/*!
2537 \fn void QRhiColorAttachment::setResolveLevel(int level)
2538 Sets the resolve texture mip \a level to use.
2539 */
2540
2541/*!
2542 \fn int QRhiColorAttachment::multiViewCount() const
2543
2544 \return the currently set number of views. Defaults to 0 which indicates
2545 the render target with this color attachment is not going to be used with
2546 multiview rendering.
2547
2548 \since 6.7
2549 */
2550
2551/*!
2552 \fn void QRhiColorAttachment::setMultiViewCount(int count)
2553
2554 Sets the view \a count. Setting a value larger than 1 indicates that the
2555 render target with this color attachment is going to be used with multiview
2556 rendering. The default value is 0. Values smaller than 2 indicate no
2557 multiview rendering.
2558
2559 When \a count is set to \c 2 or greater, the color attachment must be
2560 associated with a 2D texture array. layer() and multiViewCount() together
2561 define the range of texture array elements that are targeted during
2562 multiview rendering.
2563
2564 For example, if \c layer is \c 0 and \c multiViewCount is \c 2, the texture
2565 array must have 2 (or more) elements, and the multiview rendering will
2566 target elements 0 and 1. The \c{gl_ViewIndex} variable in the shaders has a
2567 value of \c 0 or \c 1 then, where view \c 0 corresponds to the texture array
2568 element \c 0, and view \c 1 to the array element \c 1.
2569
2570 \note Setting a \a count larger than 1, using a texture array as texture(),
2571 and calling \l{QRhiCommandBuffer::beginPass()}{beginPass()} on a
2572 QRhiTextureRenderTarget with this color attachment implies multiview
2573 rendering for the entire render pass. multiViewCount() should not be set
2574 unless multiview rendering is wanted. Multiview cannot be used with texture
2575 types other than 2D texture arrays. (although 3D textures may work,
2576 depending on the graphics API and backend; applications are nonetheless
2577 advised not to rely on that and only use 2D texture arrays as the render
2578 targets of multiview rendering)
2579
2580 See
2581 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2582 for more details regarding multiview rendering. Do note that Qt requires
2583 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview2.txt}{GL_OVR_multiview2}
2584 as well, when running on OpenGL (ES).
2585
2586 Multiview rendering is available only when the
2587 \l{QRhi::MultiView}{MultiView} feature is reported as supported from
2588 \l{QRhi::isFeatureSupported()}{isFeatureSupported()}.
2589
2590 \note For portability, be aware of limitations that exist for multiview
2591 rendering with some of the graphics APIs. It is recommended that multiview
2592 render passes do not rely on any of the features that
2593 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2594 declares as unsupported. The one exception is shader stage outputs other
2595 than \c{gl_Position} depending on \c{gl_ViewIndex}: that can be relied on
2596 (even with OpenGL) because QRhi never reports multiview as supported without
2597 \c{GL_OVR_multiview2} also being present.
2598
2599 \note Multiview rendering is not supported in combination with tessellation
2600 or geometry shaders, even though some implementations of some graphics APIs
2601 may allow this.
2602
2603 \since 6.7
2604 */
2605
2606/*!
2607 \class QRhiTextureRenderTargetDescription
2608 \inmodule QtGuiPrivate
2609 \inheaderfile rhi/qrhi.h
2610 \since 6.6
2611 \brief Describes the color and depth or depth/stencil attachments of a render target.
2612
2613 A texture render target has zero or more textures as color attachments,
2614 zero or one renderbuffer as combined depth/stencil buffer or zero or one
2615 texture as depth buffer.
2616
2617 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2618 non-null at the same time).
2619
2620 Let's look at some example usages in combination with
2621 QRhiTextureRenderTarget.
2622
2623 Due to the constructors, the targeting a texture (and no depth/stencil
2624 buffer) is simple:
2625
2626 \code
2627 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256), 1, QRhiTexture::RenderTarget);
2628 texture->create();
2629 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture }));
2630 \endcode
2631
2632 The following creates a texture render target that is set up to target mip
2633 level #2 of a texture:
2634
2635 \code
2636 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget | QRhiTexture::MipMapped);
2637 texture->create();
2638 QRhiColorAttachment colorAtt(texture);
2639 colorAtt.setLevel(2);
2640 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt });
2641 \endcode
2642
2643 Another example, this time to render into a depth texture:
2644
2645 \code
2646 QRhiTexture *shadowMap = rhi->newTexture(QRhiTexture::D32F, QSize(1024, 1024), 1, QRhiTexture::RenderTarget);
2647 shadowMap->create();
2648 QRhiTextureRenderTargetDescription rtDesc;
2649 rtDesc.setDepthTexture(shadowMap);
2650 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2651 \endcode
2652
2653 A very common case, having a texture as the color attachment and a
2654 renderbuffer as depth/stencil to enable depth testing:
2655
2656 \code
2657 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2658 texture->create();
2659 QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512));
2660 depthStencil->create();
2661 QRhiTextureRenderTargetDescription rtDesc({ texture }, depthStencil);
2662 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2663 \endcode
2664
2665 Finally, to enable multisample rendering in a portable manner (so also
2666 supporting OpenGL ES 3.0), using a QRhiRenderBuffer as the (multisample)
2667 color buffer and then resolving into a regular (non-multisample) 2D
2668 texture. To enable depth testing, a depth-stencil buffer, which also must
2669 use the same sample count, is used as well:
2670
2671 \code
2672 QRhiRenderBuffer *colorBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4); // 4x MSAA
2673 colorBuffer->create();
2674 QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512), 4);
2675 depthStencil->create();
2676 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2677 texture->create();
2678 QRhiColorAttachment colorAtt(colorBuffer);
2679 colorAtt.setResolveTexture(texture);
2680 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt, depthStencil });
2681 \endcode
2682
2683 \note when multisample resolving is enabled, the multisample data may not be
2684 written out at all. This means that the multisample texture in a color
2685 attachment must not be used afterwards with shaders for sampling (or other
2686 purposes) whenever a resolve texture is set, since the multisample color
2687 buffer is merely an intermediate storage then that gets no data written back
2688 on some GPU architectures at all. See
2689 \l{QRhiTextureRenderTarget::Flag}{PreserveColorContents} for more details.
2690
2691 \note When using setDepthTexture(), not setDepthStencilBuffer(), and the
2692 depth (stencil) data is not of interest afterwards, set the
2693 DoNotStoreDepthStencilContents flag on the QRhiTextureRenderTarget. This
2694 allows indicating to the underlying 3D API that the depth/stencil data can
2695 be discarded, leading potentially to better performance with tiled GPU
2696 architectures. When the depth-stencil buffer is a QRhiRenderBuffer (and also
2697 for the multisample color texture, see previous note) this is implicit, but
2698 with a depth (stencil) QRhiTexture the intention needs to be declared
2699 explicitly. By default QRhi assumes that the data is of interest (e.g., the
2700 depth texture is sampled in a shader afterwards).
2701
2702 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2703 for details.
2704
2705 \sa QRhiColorAttachment, QRhiTextureRenderTarget
2706 */
2707
2708/*!
2709 \fn QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription() = default
2710
2711 Constructs an empty texture render target description.
2712 */
2713
2714/*!
2715 Constructs a texture render target description with one attachment
2716 described by \a colorAttachment.
2717 */
2718QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment)
2719{
2720 m_colorAttachments.append(colorAttachment);
2721}
2722
2723/*!
2724 Constructs a texture render target description with two attachments, a
2725 color attachment described by \a colorAttachment, and a depth/stencil
2726 attachment with \a depthStencilBuffer.
2727 */
2728QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2729 QRhiRenderBuffer *depthStencilBuffer)
2730 : m_depthStencilBuffer(depthStencilBuffer)
2731{
2732 m_colorAttachments.append(colorAttachment);
2733}
2734
2735/*!
2736 Constructs a texture render target description with two attachments, a
2737 color attachment described by \a colorAttachment, and a depth attachment
2738 with \a depthTexture.
2739
2740 \note \a depthTexture must have a suitable format, such as QRhiTexture::D16
2741 or QRhiTexture::D32F.
2742 */
2743QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2744 QRhiTexture *depthTexture)
2745 : m_depthTexture(depthTexture)
2746{
2747 m_colorAttachments.append(colorAttachment);
2748}
2749
2750/*!
2751 \fn void QRhiTextureRenderTargetDescription::setColorAttachments(std::initializer_list<QRhiColorAttachment> list)
2752 Sets the \a list of color attachments.
2753 */
2754
2755/*!
2756 \fn template<typename InputIterator> void QRhiTextureRenderTargetDescription::setColorAttachments(InputIterator first, InputIterator last)
2757 Sets the list of color attachments via the iterators \a first and \a last.
2758 */
2759
2760/*!
2761 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cbeginColorAttachments() const
2762 \return a const iterator pointing to the first item in the attachment list.
2763 */
2764
2765/*!
2766 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cendColorAttachments() const
2767 \return a const iterator pointing just after the last item in the attachment list.
2768 */
2769
2770/*!
2771 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::colorAttachmentAt(qsizetype index) const
2772 \return the color attachment at the specified \a index.
2773 */
2774
2775/*!
2776 \fn qsizetype QRhiTextureRenderTargetDescription::colorAttachmentCount() const
2777 \return the number of currently set color attachments.
2778 */
2779
2780/*!
2781 \fn QRhiRenderBuffer *QRhiTextureRenderTargetDescription::depthStencilBuffer() const
2782 \return the renderbuffer used as depth-stencil buffer, or \nullptr if none was set.
2783 */
2784
2785/*!
2786 \fn void QRhiTextureRenderTargetDescription::setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer)
2787
2788 Sets the \a renderBuffer for depth-stencil. Not mandatory, e.g. when no
2789 depth test/write or stencil-related features are used within any graphics
2790 pipelines in any of the render passes for this render target, it can be
2791 left set to \nullptr.
2792
2793 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2794 non-null at the same time).
2795
2796 Using a QRhiRenderBuffer over a 2D QRhiTexture as the depth or
2797 depth/stencil buffer is very common, and is the recommended approach for
2798 applications. Using a QRhiTexture, and so setDepthTexture() becomes
2799 relevant if the depth data is meant to be accessed (e.g. sampled in a
2800 shader) afterwards, or when
2801 \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering} is
2802 involved (because then the depth texture must be a texture array).
2803
2804 \sa setDepthTexture()
2805 */
2806
2807/*!
2808 \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthTexture() const
2809 \return the currently referenced depth texture, or \nullptr if none was set.
2810 */
2811
2812/*!
2813 \fn void QRhiTextureRenderTargetDescription::setDepthTexture(QRhiTexture *texture)
2814
2815 Sets the \a texture for depth-stencil. This is an alternative to
2816 setDepthStencilBuffer(), where instead of a QRhiRenderBuffer a QRhiTexture
2817 with a suitable type (e.g., QRhiTexture::D32F) is provided.
2818
2819 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2820 non-null at the same time).
2821
2822 \a texture can either be a 2D texture or a 2D texture array (when texture
2823 arrays are supported). Specifying a texture array is relevant in particular
2824 with
2825 \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering}.
2826
2827 \note If \a texture is a format with a stencil component, such as
2828 \l QRhiTexture::D24S8, it will serve as the stencil buffer as well.
2829
2830 \sa setDepthStencilBuffer()
2831 */
2832
2833/*!
2834 \fn int QRhiTextureRenderTargetDescription::depthLayer() const
2835 \return the array slice index to be used for the depth/stencil attachment,
2836 or -1 by default.
2837
2838 \since 6.12
2839 \sa setDepthLayer(), setDepthTexture()
2840 */
2841
2842/*!
2843 \fn void QRhiTextureRenderTargetDescription::setDepthLayer(int depthLayer)
2844
2845 Sets the array slice index to be used for the depth/stencil attachment.
2846
2847 Pass -1 (the default) to not target a particular layer. When set to a
2848 non-negative value, the render target attaches a view that targets exactly
2849 that layer (slice) of the depth texture. This is only effective when a 2D
2850 array depth texture is provided via setDepthTexture(); otherwise the value
2851 is ignored.
2852
2853 The value must be within the array size of the depth texture; passing an
2854 out-of-range index leads to undefined behavior. The index is absolute
2855 with respect to the underlying texture, regardless of any array range
2856 that may have been specified when creating the texture.
2857
2858 Specifying a \a depthLayer disables layered/multiview rendering for the
2859 depth attachment.
2860
2861 \since 6.12
2862 \sa depthLayer(), setDepthTexture()
2863 */
2864
2865/*!
2866 \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthResolveTexture() const
2867
2868 \return the texture to which a multisample depth (or depth-stencil) texture
2869 (or texture array) is resolved to. \nullptr if there is none, which is the
2870 most common case.
2871
2872 \since 6.8
2873 \sa QRhiColorAttachment::resolveTexture(), depthTexture()
2874 */
2875
2876/*!
2877 \fn void QRhiTextureRenderTargetDescription::setDepthResolveTexture(QRhiTexture *tex)
2878
2879 Sets the depth (or depth-stencil) resolve texture \a tex.
2880
2881 \a tex is expected to be a 2D texture or a 2D texture array with a format
2882 matching the texture set via setDepthTexture().
2883
2884 \note Resolving depth (or depth-stencil) data is only functional when the
2885 \l QRhi::ResolveDepthStencil feature is reported as supported at run time.
2886 Support for depth-stencil resolve is not universally available among the
2887 graphics APIs. Designs assuming unconditional availability of depth-stencil
2888 resolve are therefore non-portable, and should be avoided.
2889
2890 \note As an additional limitation for OpenGL ES in particular, setting a
2891 depth resolve texture may only be functional in combination with
2892 setDepthTexture(), not with setDepthStencilBuffer().
2893
2894 \since 6.8
2895 \sa QRhiColorAttachment::setResolveTexture(), setDepthTexture()
2896 */
2897
2898/*!
2899 \fn QRhiShadingRateMap *QRhiTextureRenderTargetDescription::shadingRateMap() const
2900 \return the currently set QRhiShadingRateMap. By default this is \nullptr.
2901 \since 6.9
2902 */
2903
2904/*!
2905 \fn void QRhiTextureRenderTargetDescription::setShadingRateMap(QRhiShadingRateMap *map)
2906
2907 Associates with the specified QRhiShadingRateMap \a map. This is functional
2908 only when the \l QRhi::VariableRateShadingMap feature is reported as
2909 supported.
2910
2911 When QRhiCommandBuffer::setShadingRate() is also called, the higher of the
2912 two shading rates is used for each tile. There is currently no control
2913 offered over the combiner behavior.
2914
2915 \note When the render target had already been built (create() was called
2916 successfully), setting a shading rate map implies that a different, new
2917 QRhiRenderPassDescriptor is needed and thus a rebuild is needed. Call
2918 setRenderPassDescriptor() again (outside of a render pass) and then rebuild
2919 by calling create(). This has other rolling consequences as well, for
2920 example for graphics pipelines: those also need to be associated with the
2921 new QRhiRenderPassDescriptor and then rebuilt. See \l
2922 QRhiRenderPassDescriptor::serializedFormat() for some suggestions on how to
2923 deal with this. Remember to set the QRhiGraphicsPipeline::UsesShadingRate
2924 flag as well.
2925
2926 \since 6.9
2927 */
2928
2929/*!
2930 \class QRhiTextureSubresourceUploadDescription
2931 \inmodule QtGuiPrivate
2932 \inheaderfile rhi/qrhi.h
2933 \since 6.6
2934 \brief Describes the source for one mip level in a layer in a texture upload operation.
2935
2936 The source content is specified either as a QImage or as a raw blob. The
2937 former is only allowed for uncompressed textures with a format that can be
2938 mapped to QImage, while the latter is supported for all formats, including
2939 floating point and compressed.
2940
2941 \note image() and data() cannot be both set at the same time.
2942
2943 destinationTopLeft() specifies the top-left corner of the target
2944 rectangle. Defaults to (0, 0).
2945
2946 An empty sourceSize() (the default) indicates that size is assumed to be
2947 the size of the subresource. With QImage-based uploads this implies that
2948 the size of the source image() must match the subresource. When providing
2949 raw data instead, sufficient number of bytes must be provided in data().
2950
2951 sourceTopLeft() is supported only for QImage-based uploads, and specifies
2952 the top-left corner of the source rectangle.
2953
2954 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
2955 internally, depending on the format and the backend.
2956
2957 When providing raw data, and the stride is not specified via
2958 setDataStride(), the stride (row pitch, row length in bytes) of the
2959 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
2960 the number of bytes used for one pixel, and there must be no additional
2961 padding between rows. There is no row start alignment requirement.
2962
2963 When there is unused data at the end of each row in the input raw data,
2964 call setDataStride() with the total number of bytes per row. The stride
2965 must always be a multiple of the number of bytes for one pixel. The row
2966 stride is only applicable to image data for textures with an uncompressed
2967 format.
2968
2969 \note The format of the source data must be compatible with the texture
2970 format. With many graphics APIs the data is copied as-is into a staging
2971 buffer, there is no intermediate format conversion provided by QRhi. This
2972 applies to floating point formats as well, with, for example, RGBA16F
2973 requiring half floats in the source data.
2974
2975 \note Setting the stride via setDataStride() is only functional when
2976 QRhi::ImageDataStride is reported as
2977 \l{QRhi::isFeatureSupported()}{supported}. In practice this can be expected
2978 to be supported everywhere except for OpenGL ES 2.0.
2979
2980 \note When a QImage is given, the stride returned from
2981 QImage::bytesPerLine() is taken into account automatically.
2982
2983 \warning When a QImage is given and the QImage does not own the underlying
2984 pixel data, it is up to the caller to ensure that the associated data stays
2985 valid until the end of the frame. (just submitting the resource update batch
2986 is not sufficient, the data must stay valid until QRhi::endFrame() is called
2987 in order to be portable across all backends) If this cannot be ensured, the
2988 caller is strongly encouraged to call QImage::detach() on the image before
2989 passing it to uploadTexture().
2990
2991 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2992 for details.
2993
2994 \sa QRhiTextureUploadDescription
2995 */
2996
2997/*!
2998 \fn QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription() = default
2999
3000 Constructs an empty subresource description.
3001
3002 \note an empty QRhiTextureSubresourceUploadDescription is not useful on its
3003 own and should not be submitted to a QRhiTextureUploadEntry. At minimum
3004 image or data must be set first.
3005 */
3006
3007/*!
3008 Constructs a mip level description with a \a image.
3009
3010 The \l{QImage::size()}{size} of \a image must match the size of the mip
3011 level. For level 0 that is the \l{QRhiTexture::pixelSize()}{texture size}.
3012
3013 The bit depth of \a image must be compatible with the
3014 \l{QRhiTexture::Format}{texture format}.
3015
3016 To describe a partial upload, call setSourceSize(), setSourceTopLeft(), or
3017 setDestinationTopLeft() afterwards.
3018 */
3019QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QImage &image)
3020 : m_image(image)
3021{
3022}
3023
3024/*!
3025 Constructs a mip level description with the image data is specified by \a
3026 data and \a size. This is suitable for floating point and compressed
3027 formats as well.
3028
3029 \a data can safely be destroyed or changed once this function returns.
3030 */
3031QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const void *data, quint32 size)
3032 : m_data(reinterpret_cast<const char *>(data), size)
3033{
3034}
3035
3036/*!
3037 Constructs a mip level description with the image data specified by \a
3038 data. This is suitable for floating point and compressed formats as well.
3039 */
3040QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QByteArray &data)
3041 : m_data(data)
3042{
3043}
3044
3045/*!
3046 \fn QImage QRhiTextureSubresourceUploadDescription::image() const
3047 \return the currently set QImage.
3048 */
3049
3050/*!
3051 \fn void QRhiTextureSubresourceUploadDescription::setImage(const QImage &image)
3052
3053 Sets \a image.
3054 Upon textures loading, the image data will be read as is, with no formats conversions.
3055
3056 \note image() and data() cannot be both set at the same time.
3057 */
3058
3059/*!
3060 \fn QByteArray QRhiTextureSubresourceUploadDescription::data() const
3061 \return the currently set raw pixel data.
3062 */
3063
3064/*!
3065 \fn void QRhiTextureSubresourceUploadDescription::setData(const QByteArray &data)
3066
3067 Sets \a data.
3068
3069 \note image() and data() cannot be both set at the same time.
3070 */
3071
3072/*!
3073 \fn quint32 QRhiTextureSubresourceUploadDescription::dataStride() const
3074 \return the currently set data stride.
3075 */
3076
3077/*!
3078 \fn void QRhiTextureSubresourceUploadDescription::setDataStride(quint32 stride)
3079
3080 Sets the data \a stride in bytes. By default this is 0 and not always
3081 relevant. When providing raw data(), and the stride is not specified via
3082 setDataStride(), the stride (row pitch, row length in bytes) of the
3083 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
3084 the number of bytes used for one pixel, and there must be no additional
3085 padding between rows. Otherwise, if there is additional space between the
3086 lines, set a non-zero \a stride. All this is applicable only when raw image
3087 data is provided, and is not necessary when working QImage since that has
3088 its own \l{QImage::bytesPerLine()}{stride} value.
3089
3090 \note When a non-zero \a stride is set, make sure the data contains the
3091 trailing padding for the last row as well, i.e. at least \c{stride * height}
3092 bytes in total. While providing the data without the last row's padding
3093 (i.e., interpreting stride as not applicable to the last row) could be safe,
3094 and is in fact safe with Vulkan, OpenGL, and D3D12, this cannot be
3095 guaranteed for all backends, so the safe approach is to avoid this and treat
3096 the last line like all others.
3097
3098 \note Setting the stride via setDataStride() is only functional when
3099 QRhi::ImageDataStride is reported as
3100 \l{QRhi::isFeatureSupported()}{supported}.
3101
3102 \note When a QImage is given, the stride returned from
3103 QImage::bytesPerLine() is taken into account automatically and therefore
3104 there is no need to set the data stride manually.
3105 */
3106
3107/*!
3108 \fn QPoint QRhiTextureSubresourceUploadDescription::destinationTopLeft() const
3109 \return the currently set destination top-left position. Defaults to (0, 0).
3110 */
3111
3112/*!
3113 \fn void QRhiTextureSubresourceUploadDescription::setDestinationTopLeft(const QPoint &p)
3114 Sets the destination top-left position \a p.
3115
3116 \note In the most common case of sourcing the image data from a QImage, Qt
3117 performs clamping of invalid texture upload sizes when the destination
3118 position + the source size exceeds the size of the targeted texture
3119 subresource (i.e, the size at the given mip level). There is also a
3120 qWarning() message printed on the debug output in this case. This is done in
3121 order to avoid confusion when the underlying 3D APIs crash and lead to GPU
3122 device removals at a later point when submitting the commands. Regardless,
3123 developers are encouraged to always validate applications by running with the
3124 Vulkan, D3D12, or Metal validation/debug layers enabled, since those offer a
3125 much wider range of checks on API usage.
3126 */
3127
3128/*!
3129 \fn QSize QRhiTextureSubresourceUploadDescription::sourceSize() const
3130
3131 \return the source size in pixels. Defaults to a default-constructed QSize,
3132 which indicates the entire subresource.
3133 */
3134
3135/*!
3136 \fn void QRhiTextureSubresourceUploadDescription::setSourceSize(const QSize &size)
3137
3138 Sets the source \a size in pixels.
3139
3140 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3141 internally, depending on the format and the backend.
3142 */
3143
3144/*!
3145 \fn QPoint QRhiTextureSubresourceUploadDescription::sourceTopLeft() const
3146 \return the currently set source top-left position. Defaults to (0, 0).
3147 */
3148
3149/*!
3150 \fn void QRhiTextureSubresourceUploadDescription::setSourceTopLeft(const QPoint &p)
3151
3152 Sets the source top-left position \a p.
3153
3154 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3155 internally, depending on the format and the backend.
3156 */
3157
3158/*!
3159 \class QRhiTextureUploadEntry
3160 \inmodule QtGuiPrivate
3161 \inheaderfile rhi/qrhi.h
3162 \since 6.6
3163
3164 \brief Describes one layer (face for cubemaps, slice for 3D textures,
3165 element for texture arrays) in a texture upload operation.
3166
3167 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3168 for details.
3169 */
3170
3171/*!
3172 \fn QRhiTextureUploadEntry::QRhiTextureUploadEntry()
3173
3174 Constructs an empty QRhiTextureUploadEntry targeting layer 0 and level 0.
3175
3176 \note an empty QRhiTextureUploadEntry should not be submitted without
3177 setting a QRhiTextureSubresourceUploadDescription via setDescription()
3178 first.
3179 */
3180
3181/*!
3182 Constructs a QRhiTextureUploadEntry targeting the given \a layer and mip
3183 \a level, with the subresource contents described by \a desc.
3184 */
3185QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
3186 const QRhiTextureSubresourceUploadDescription &desc)
3187 : m_layer(layer),
3188 m_level(level),
3189 m_desc(desc)
3190{
3191}
3192
3193/*!
3194 \fn int QRhiTextureUploadEntry::layer() const
3195 \return the currently set layer index (cubemap face, array layer). Defaults to 0.
3196 */
3197
3198/*!
3199 \fn void QRhiTextureUploadEntry::setLayer(int layer)
3200 Sets the \a layer.
3201 */
3202
3203/*!
3204 \fn int QRhiTextureUploadEntry::level() const
3205 \return the currently set mip level. Defaults to 0.
3206 */
3207
3208/*!
3209 \fn void QRhiTextureUploadEntry::setLevel(int level)
3210 Sets the mip \a level.
3211 */
3212
3213/*!
3214 \fn QRhiTextureSubresourceUploadDescription QRhiTextureUploadEntry::description() const
3215 \return the currently set subresource description.
3216 */
3217
3218/*!
3219 \fn void QRhiTextureUploadEntry::setDescription(const QRhiTextureSubresourceUploadDescription &desc)
3220 Sets the subresource description \a desc.
3221 */
3222
3223/*!
3224 \class QRhiTextureUploadDescription
3225 \inmodule QtGuiPrivate
3226 \inheaderfile rhi/qrhi.h
3227 \since 6.6
3228 \brief Describes a texture upload operation.
3229
3230 Used with QRhiResourceUpdateBatch::uploadTexture(). That function has two
3231 variants: one taking a QImage and one taking a
3232 QRhiTextureUploadDescription. The former is a convenience version,
3233 internally creating a QRhiTextureUploadDescription with a single image
3234 targeting level 0 for layer 0.
3235
3236 An example of the common, simple case of wanting to upload the contents
3237 of a QImage to a QRhiTexture with a matching pixel size:
3238
3239 \code
3240 QImage image(256, 256, QImage::Format_RGBA8888);
3241 image.fill(Qt::green); // or could use a QPainter targeting image
3242 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256));
3243 texture->create();
3244 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
3245 u->uploadTexture(texture, image);
3246 \endcode
3247
3248 When cubemaps, pre-generated mip images, compressed textures, or partial
3249 uploads are involved, applications will have to use this class instead.
3250
3251 QRhiTextureUploadDescription also enables specifying batched uploads, which
3252 are useful for example when generating an atlas or glyph cache texture:
3253 multiple, partial uploads for the same subresource (meaning the same layer
3254 and level) are supported, and can be, depending on the backend and the
3255 underlying graphics API, more efficient when batched into the same
3256 QRhiTextureUploadDescription as opposed to issuing individual
3257 \l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} commands for
3258 each of them.
3259
3260 \note Cubemaps have one layer for each of the six faces in the order +X,
3261 -X, +Y, -Y, +Z, -Z.
3262
3263 For example, specifying the faces of a cubemap could look like the following:
3264
3265 \code
3266 QImage faces[6];
3267 // ...
3268 QVarLengthArray<QRhiTextureUploadEntry, 6> entries;
3269 for (int i = 0; i < 6; ++i)
3270 entries.append(QRhiTextureUploadEntry(i, 0, faces[i]));
3271 QRhiTextureUploadDescription desc;
3272 desc.setEntries(entries.cbegin(), entries.cend());
3273 resourceUpdates->uploadTexture(texture, desc);
3274 \endcode
3275
3276 Another example that specifies mip images for a compressed texture:
3277
3278 \code
3279 QList<QRhiTextureUploadEntry> entries;
3280 const int mipCount = rhi->mipLevelsForSize(compressedTexture->pixelSize());
3281 for (int level = 0; level < mipCount; ++level) {
3282 const QByteArray compressedDataForLevel = ..
3283 entries.append(QRhiTextureUploadEntry(0, level, compressedDataForLevel));
3284 }
3285 QRhiTextureUploadDescription desc;
3286 desc.setEntries(entries.cbegin(), entries.cend());
3287 resourceUpdates->uploadTexture(compressedTexture, desc);
3288 \endcode
3289
3290 With partial uploads targeting the same subresource, it is recommended to
3291 batch them into a single upload request, whenever possible:
3292
3293 \code
3294 QRhiTextureSubresourceUploadDescription subresDesc(image);
3295 subresDesc.setSourceSize(QSize(10, 10));
3296 subResDesc.setDestinationTopLeft(QPoint(50, 40));
3297 QRhiTextureUploadEntry entry(0, 0, subresDesc); // layer 0, level 0
3298
3299 QRhiTextureSubresourceUploadDescription subresDesc2(image);
3300 subresDesc2.setSourceSize(QSize(30, 40));
3301 subResDesc2.setDestinationTopLeft(QPoint(100, 200));
3302 QRhiTextureUploadEntry entry2(0, 0, subresDesc2); // layer 0, level 0, i.e. same subresource
3303
3304 QRhiTextureUploadDescription desc({ entry, entry2});
3305 resourceUpdates->uploadTexture(texture, desc);
3306 \endcode
3307
3308 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3309 for details.
3310
3311 \sa QRhiResourceUpdateBatch
3312 */
3313
3314/*!
3315 \fn QRhiTextureUploadDescription::QRhiTextureUploadDescription()
3316
3317 Constructs an empty texture upload description.
3318 */
3319
3320/*!
3321 Constructs a texture upload description with a single subresource upload
3322 described by \a entry.
3323 */
3324QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry)
3325{
3326 m_entries.append(entry);
3327}
3328
3329/*!
3330 Constructs a texture upload description with the specified \a list of entries.
3331
3332 \note \a list can also contain multiple QRhiTextureUploadEntry elements
3333 with the same layer and level. This makes sense when those uploads are
3334 partial, meaning their subresource description has a source size or image
3335 smaller than the subresource dimensions, and can be more efficient than
3336 issuing separate uploadTexture()'s.
3337 */
3338QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list)
3339 : m_entries(list)
3340{
3341}
3342
3343/*!
3344 \fn void QRhiTextureUploadDescription::setEntries(std::initializer_list<QRhiTextureUploadEntry> list)
3345 Sets the \a list of entries.
3346 */
3347
3348/*!
3349 \fn template<typename InputIterator> void QRhiTextureUploadDescription::setEntries(InputIterator first, InputIterator last)
3350 Sets the list of entries using the iterators \a first and \a last.
3351 */
3352
3353/*!
3354 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cbeginEntries() const
3355 \return a const iterator pointing to the first item in the entry list.
3356 */
3357
3358/*!
3359 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cendEntries() const
3360 \return a const iterator pointing just after the last item in the entry list.
3361 */
3362
3363/*!
3364 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::entryAt(qsizetype index) const
3365 \return the entry at \a index.
3366 */
3367
3368/*!
3369 \fn qsizetype QRhiTextureUploadDescription::entryCount() const
3370 \return the number of entries.
3371 */
3372
3373/*!
3374 \class QRhiTextureCopyDescription
3375 \inmodule QtGuiPrivate
3376 \inheaderfile rhi/qrhi.h
3377 \since 6.6
3378 \brief Describes a texture-to-texture copy operation.
3379
3380 An empty pixelSize() indicates that the entire subresource is to be copied.
3381 A default constructed copy description therefore leads to copying the
3382 entire subresource at level 0 of layer 0.
3383
3384 \note The source texture must be created with
3385 QRhiTexture::UsedAsTransferSource.
3386
3387 \note The source and destination rectangles defined by pixelSize(),
3388 sourceTopLeft(), and destinationTopLeft() must fit the source and
3389 destination textures, respectively. The behavior is undefined otherwise.
3390
3391 With cubemaps, 3D textures, and texture arrays one face or slice can be
3392 copied at a time. The face or slice is specified by the source and
3393 destination layer indices. With mipmapped textures one mip level can be
3394 copied at a time. The source and destination layer and mip level indices can
3395 differ, but the size and position must be carefully controlled to avoid out
3396 of bounds copies, in which case the behavior is undefined.
3397
3398 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3399 for details.
3400 */
3401
3402/*!
3403 \fn QRhiTextureCopyDescription::QRhiTextureCopyDescription()
3404
3405 Constructs an empty texture copy description.
3406 */
3407
3408/*!
3409 \fn QSize QRhiTextureCopyDescription::pixelSize() const
3410 \return the size of the region to copy.
3411
3412 \note An empty pixelSize() indicates that the entire subresource is to be
3413 copied. A default constructed copy description therefore leads to copying
3414 the entire subresource at level 0 of layer 0.
3415 */
3416
3417/*!
3418 \fn void QRhiTextureCopyDescription::setPixelSize(const QSize &sz)
3419 Sets the size of the region to copy to \a sz.
3420 */
3421
3422/*!
3423 \fn int QRhiTextureCopyDescription::sourceLayer() const
3424 \return the source array layer (cubemap face or array layer index). Defaults to 0.
3425 */
3426
3427/*!
3428 \fn void QRhiTextureCopyDescription::setSourceLayer(int layer)
3429 Sets the source array \a layer.
3430 */
3431
3432/*!
3433 \fn int QRhiTextureCopyDescription::sourceLevel() const
3434 \return the source mip level. Defaults to 0.
3435 */
3436
3437/*!
3438 \fn void QRhiTextureCopyDescription::setSourceLevel(int level)
3439 Sets the source mip \a level.
3440 */
3441
3442/*!
3443 \fn QPoint QRhiTextureCopyDescription::sourceTopLeft() const
3444 \return the source top-left position (in pixels). Defaults to (0, 0).
3445 */
3446
3447/*!
3448 \fn void QRhiTextureCopyDescription::setSourceTopLeft(const QPoint &p)
3449 Sets the source top-left position to \a p.
3450 */
3451
3452/*!
3453 \fn int QRhiTextureCopyDescription::destinationLayer() const
3454 \return the destination array layer (cubemap face or array layer index). Default to 0.
3455 */
3456
3457/*!
3458 \fn void QRhiTextureCopyDescription::setDestinationLayer(int layer)
3459 Sets the destination array \a layer.
3460 */
3461
3462/*!
3463 \fn int QRhiTextureCopyDescription::destinationLevel() const
3464 \return the destionation mip level. Defaults to 0.
3465 */
3466
3467/*!
3468 \fn void QRhiTextureCopyDescription::setDestinationLevel(int level)
3469 Sets the destination mip \a level.
3470 */
3471
3472/*!
3473 \fn QPoint QRhiTextureCopyDescription::destinationTopLeft() const
3474 \return the destionation top-left position in pixels. Defaults to (0, 0).
3475 */
3476
3477/*!
3478 \fn void QRhiTextureCopyDescription::setDestinationTopLeft(const QPoint &p)
3479 Sets the destination top-left position \a p.
3480 */
3481
3482/*!
3483 \class QRhiReadbackDescription
3484 \inmodule QtGuiPrivate
3485 \inheaderfile rhi/qrhi.h
3486 \since 6.6
3487 \brief Describes a readback (reading back texture contents from possibly GPU-only memory) operation.
3488
3489 The source of the readback operation is either a QRhiTexture or the
3490 current backbuffer of the currently targeted QRhiSwapChain. When
3491 texture() is not set, the swapchain is used. Otherwise the specified
3492 QRhiTexture is treated as the source.
3493
3494 \note Textures used in readbacks must be created with
3495 QRhiTexture::UsedAsTransferSource.
3496
3497 \note Swapchains used in readbacks must be created with
3498 QRhiSwapChain::UsedAsTransferSource.
3499
3500 layer() and level() are only applicable when the source is a QRhiTexture.
3501
3502 \note Multisample textures cannot be read back. Readbacks are supported for
3503 multisample swapchain buffers however.
3504
3505 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3506 for details.
3507 */
3508
3509/*!
3510 \fn QRhiReadbackDescription::QRhiReadbackDescription() = default
3511
3512 Constructs an empty texture readback description.
3513
3514 \note The source texture is set to null by default, which is still a valid
3515 readback: it specifies that the backbuffer of the current swapchain is to
3516 be read back. (current meaning the frame's target swapchain at the time of
3517 committing the QRhiResourceUpdateBatch with the
3518 \l{QRhiResourceUpdateBatch::readBackTexture()}{texture readback} on it)
3519 */
3520
3521/*!
3522 Constructs an texture readback description that specifies that level 0 of
3523 layer 0 of \a texture is to be read back.
3524
3525 \note \a texture can also be null in which case this constructor is
3526 identical to the argumentless variant.
3527 */
3528QRhiReadbackDescription::QRhiReadbackDescription(QRhiTexture *texture)
3529 : m_texture(texture)
3530{
3531}
3532
3533/*!
3534 \fn QRhiTexture *QRhiReadbackDescription::texture() const
3535
3536 \return the QRhiTexture that is read back. Can be left set to \nullptr
3537 which indicates that the backbuffer of the current swapchain is to be used
3538 instead.
3539 */
3540
3541/*!
3542 \fn void QRhiReadbackDescription::setTexture(QRhiTexture *tex)
3543
3544 Sets the texture \a tex as the source of the readback operation.
3545
3546 Setting \nullptr is valid too, in which case the current swapchain's
3547 current backbuffer is used. (but then the readback cannot be issued in a
3548 non-swapchain-based frame)
3549
3550 \note Multisample textures cannot be read back. Readbacks are supported for
3551 multisample swapchain buffers however.
3552
3553 \note Textures used in readbacks must be created with
3554 QRhiTexture::UsedAsTransferSource.
3555
3556 \note Swapchains used in readbacks must be created with
3557 QRhiSwapChain::UsedAsTransferSource.
3558 */
3559
3560/*!
3561 \fn int QRhiReadbackDescription::layer() const
3562
3563 \return the currently set array layer (cubemap face, array index). Defaults to 0.
3564
3565 Applicable only when the source of the readback is a QRhiTexture.
3566 */
3567
3568/*!
3569 \fn void QRhiReadbackDescription::setLayer(int layer)
3570 Sets the array \a layer to read back.
3571 */
3572
3573/*!
3574 \fn int QRhiReadbackDescription::level() const
3575
3576 \return the currently set mip level. Defaults to 0.
3577
3578 Applicable only when the source of the readback is a QRhiTexture.
3579 */
3580
3581/*!
3582 \fn void QRhiReadbackDescription::setLevel(int level)
3583 Sets the mip \a level to read back.
3584 */
3585
3586/*!
3587 \fn const QRect &QRhiReadbackDescription::rect() const
3588 \since 6.10
3589
3590 \return the rectangle to read back. Defaults to an invalid rectangle.
3591
3592 If invalid, the entire texture or swapchain backbuffer is read back.
3593 */
3594
3595/*!
3596 \fn void QRhiReadbackDescription::setRect(const QRect &rectangle)
3597 \since 6.10
3598
3599 Sets the \a rectangle to read back.
3600 */
3601
3602/*!
3603 \class QRhiReadbackResult
3604 \inmodule QtGuiPrivate
3605 \inheaderfile rhi/qrhi.h
3606 \since 6.6
3607 \brief Describes the results of a potentially asynchronous buffer or texture readback operation.
3608
3609 When \l completed is set, the function is invoked when the \l data is
3610 available. \l format and \l pixelSize are set upon completion together with
3611 \l data.
3612
3613 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3614 for details.
3615 */
3616
3617/*!
3618 \variable QRhiReadbackResult::completed
3619
3620 Callback that is invoked upon completion, on the thread the QRhi operates
3621 on. Can be left set to \nullptr, in which case no callback is invoked.
3622 */
3623
3624/*!
3625 \variable QRhiReadbackResult::format
3626
3627 Valid only for textures, the texture format.
3628 */
3629
3630/*!
3631 \variable QRhiReadbackResult::pixelSize
3632
3633 Valid only for textures, the size in pixels.
3634 */
3635
3636/*!
3637 \variable QRhiReadbackResult::data
3638
3639 The buffer or image data.
3640
3641 \sa QRhiResourceUpdateBatch::readBackTexture(), QRhiResourceUpdateBatch::readBackBuffer()
3642 */
3643
3644
3645/*!
3646 \class QRhiNativeHandles
3647 \inmodule QtGuiPrivate
3648 \inheaderfile rhi/qrhi.h
3649 \since 6.6
3650 \brief Base class for classes exposing backend-specific collections of native resource objects.
3651
3652 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3653 for details.
3654 */
3655
3656/*!
3657 \class QRhiResource
3658 \inmodule QtGuiPrivate
3659 \inheaderfile rhi/qrhi.h
3660 \since 6.6
3661 \brief Base class for classes encapsulating native resource objects.
3662
3663 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3664 for details.
3665 */
3666
3667/*!
3668 \enum QRhiResource::Type
3669 Specifies type of the resource.
3670
3671 \value Buffer
3672 \value Texture
3673 \value Sampler
3674 \value RenderBuffer
3675 \value RenderPassDescriptor
3676 \value SwapChainRenderTarget
3677 \value TextureRenderTarget
3678 \value ShaderResourceBindings
3679 \value GraphicsPipeline
3680 \value SwapChain
3681 \value ComputePipeline
3682 \value CommandBuffer
3683 \value ShadingRateMap
3684 */
3685
3686/*!
3687 \fn virtual QRhiResource::Type QRhiResource::resourceType() const = 0
3688
3689 \return the type of the resource.
3690 */
3691
3692/*!
3693 \internal
3694 */
3695QRhiResource::QRhiResource(QRhiImplementation *rhi)
3696 : m_rhi(rhi)
3697{
3698 m_id = QRhiGlobalObjectIdGenerator::newId();
3699}
3700
3701/*!
3702 Destructor.
3703
3704 Releases (or requests deferred releasing of) the underlying native graphics
3705 resources, if there are any.
3706
3707 \note Resources referenced by commands for the current frame should not be
3708 released until the frame is submitted by QRhi::endFrame().
3709
3710 \sa destroy()
3711 */
3712QRhiResource::~QRhiResource()
3713{
3714 // destroy() cannot be called here, due to virtuals; it is up to the
3715 // subclasses to do that.
3716}
3717
3718/*!
3719 \fn virtual void QRhiResource::destroy() = 0
3720
3721 Releases (or requests deferred releasing of) the underlying native graphics
3722 resources. Safe to call multiple times, subsequent invocations will be a
3723 no-op then.
3724
3725 Once destroy() is called, the QRhiResource instance can be reused, by
3726 calling \c create() again. That will then result in creating new native
3727 graphics resources underneath.
3728
3729 \note Resources referenced by commands for the current frame should not be
3730 released until the frame is submitted by QRhi::endFrame().
3731
3732 The QRhiResource destructor also performs the same task, so calling this
3733 function is not necessary before deleting a QRhiResource.
3734
3735 \sa deleteLater()
3736 */
3737
3738/*!
3739 When called without a frame being recorded, this function is equivalent to
3740 deleting the object. Between a QRhi::beginFrame() and QRhi::endFrame()
3741 however the behavior is different: the QRhiResource will not be destroyed
3742 until the frame is submitted via QRhi::endFrame(), thus satisfying the QRhi
3743 requirement of not altering QRhiResource objects that are referenced by the
3744 frame being recorded.
3745
3746 If the QRhi that created this object is already destroyed, the object is
3747 deleted immediately.
3748
3749 Using deleteLater() can be a useful convenience in many cases, and it
3750 complements the low-level guarantee (that the underlying native graphics
3751 objects are never destroyed until it is safe to do so and it is known for
3752 sure that they are not used by the GPU in an still in-flight frame), by
3753 offering a way to make sure the C++ object instances (of QRhiBuffer,
3754 QRhiTexture, etc.) themselves also stay valid until the end of the current
3755 frame.
3756
3757 The following example shows a convenient way of creating a throwaway buffer
3758 that is only used in one frame and gets automatically released in
3759 endFrame(). (when it comes to the underlying native buffer(s), the usual
3760 guarantee applies: the QRhi backend defers the releasing of those until it
3761 is guaranteed that the frame in which the buffer is accessed by the GPU has
3762 completed)
3763
3764 \code
3765 rhi->beginFrame(swapchain);
3766 QRhiBuffer *buf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, 256);
3767 buf->deleteLater(); // !
3768 u = rhi->nextResourceUpdateBatch();
3769 u->uploadStaticBuffer(buf, data);
3770 // ... draw with buf
3771 rhi->endFrame();
3772 \endcode
3773
3774 \sa destroy()
3775 */
3776void QRhiResource::deleteLater()
3777{
3778 if (m_rhi)
3779 m_rhi->addDeleteLater(this);
3780 else
3781 delete this;
3782}
3783
3784/*!
3785 \return the currently set object name. By default the name is empty.
3786 */
3787QByteArray QRhiResource::name() const
3788{
3789 return m_objectName;
3790}
3791
3792/*!
3793 Sets a \a name for the object.
3794
3795 This allows getting descriptive names for the native graphics
3796 resources visible in graphics debugging tools, such as
3797 \l{https://renderdoc.org/}{RenderDoc} and
3798 \l{https://developer.apple.com/xcode/}{XCode}.
3799
3800 When it comes to naming native objects by relaying the name via the
3801 appropriate graphics API, note that the name is ignored when
3802 QRhi::DebugMarkers are not supported, and may, depending on the backend,
3803 also be ignored when QRhi::EnableDebugMarkers is not set.
3804
3805 \note The name may be ignored for objects other than buffers,
3806 renderbuffers, and textures, depending on the backend.
3807
3808 \note The name may be modified. For slotted resources, such as a QRhiBuffer
3809 backed by multiple native buffers, QRhi will append a suffix to make the
3810 underlying native buffers easily distinguishable from each other.
3811 */
3812void QRhiResource::setName(const QByteArray &name)
3813{
3814 m_objectName = name;
3815}
3816
3817/*!
3818 \return the global, unique identifier of this QRhiResource.
3819
3820 User code rarely needs to deal with the value directly. It is used
3821 internally for tracking and bookkeeping purposes.
3822 */
3823quint64 QRhiResource::globalResourceId() const
3824{
3825 return m_id;
3826}
3827
3828/*!
3829 \return the QRhi that created this resource.
3830
3831 If the QRhi that created this object is already destroyed, the result is
3832 \nullptr.
3833 */
3834QRhi *QRhiResource::rhi() const
3835{
3836 return m_rhi ? m_rhi->q : nullptr;
3837}
3838
3839/*!
3840 \class QRhiBuffer
3841 \inmodule QtGuiPrivate
3842 \inheaderfile rhi/qrhi.h
3843 \since 6.6
3844 \brief Vertex, index, or uniform (constant) buffer resource.
3845
3846 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3847 for details.
3848
3849 A QRhiBuffer encapsulates zero, one, or more native buffer objects (such as
3850 a \c VkBuffer or \c MTLBuffer). With some graphics APIs and backends
3851 certain types of buffers may not use a native buffer object at all (e.g.
3852 OpenGL if uniform buffer objects are not used), but this is transparent to
3853 the user of the QRhiBuffer API. Similarly, the fact that some types of
3854 buffers may use two or three native buffers underneath, in order to allow
3855 efficient per-frame content update without stalling the GPU pipeline, is
3856 mostly invisible to the applications and libraries.
3857
3858 A QRhiBuffer instance is always created by calling
3859 \l{QRhi::newBuffer()}{the QRhi's newBuffer() function}. This creates no
3860 native graphics resources. To do that, call create() after setting the
3861 appropriate options, such as the type, usage flags, size, although in most cases these
3862 are already set based on the arguments passed to
3863 \l{QRhi::newBuffer()}{newBuffer()}.
3864
3865 \section2 Example usage
3866
3867 To create a uniform buffer for a shader where the GLSL uniform block
3868 contains a single \c mat4 member, and update the contents:
3869
3870 \code
3871 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64);
3872 if (!ubuf->create()) { error(); }
3873 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3874 QMatrix4x4 mvp;
3875 // ... set up the modelview-projection matrix
3876 batch->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
3877 // ...
3878 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
3879 \endcode
3880
3881 An example of creating a buffer with vertex data:
3882
3883 \code
3884 const float vertices[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f };
3885 QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices));
3886 if (!vbuf->create()) { error(); }
3887 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3888 batch->uploadStaticBuffer(vbuf, vertices);
3889 // ...
3890 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
3891 \endcode
3892
3893 An index buffer:
3894
3895 \code
3896 static const quint16 indices[] = { 0, 1, 2 };
3897 QRhiBuffer *ibuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices));
3898 if (!ibuf->create()) { error(); }
3899 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3900 batch->uploadStaticBuffer(ibuf, indices);
3901 // ...
3902 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
3903 \endcode
3904
3905 \section2 Common patterns
3906
3907 A call to create() destroys any existing native resources if create() was
3908 successfully called before. If those native resources are still in use by
3909 an in-flight frame (i.e., there's a chance they are still read by the GPU),
3910 the destroying of those resources is deferred automatically. Thus a very
3911 common and convenient pattern to safely increase the size of an already
3912 initialized buffer is the following. In practice this drops and creates a
3913 whole new set of native resources underneath, so it is not necessarily a
3914 cheap operation, but is more convenient and still faster than the
3915 alternatives, because by not destroying the \c buf object itself, all
3916 references to it stay valid in other data structures (e.g., in any
3917 QRhiShaderResourceBinding the QRhiBuffer is referenced from).
3918
3919 \code
3920 if (buf->size() < newSize) {
3921 buf->setSize(newSize);
3922 if (!buf->create()) { error(); }
3923 }
3924 // continue using buf, fill it with new data
3925 \endcode
3926
3927 When working with uniform buffers, it will sometimes be necessary to
3928 combine data for multiple draw calls into a single buffer for efficiency
3929 reasons. Be aware of the aligment requirements: with some graphics APIs
3930 offsets for a uniform buffer must be aligned to 256 bytes. This applies
3931 both to QRhiShaderResourceBinding and to the dynamic offsets passed to
3932 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}. Use the
3933 \l{QRhi::ubufAlignment()}{ubufAlignment()} and
3934 \l{QRhi::ubufAligned()}{ubufAligned()} functions to create portable code.
3935 As an example, the following is an outline for issuing multiple (\c N) draw
3936 calls with the same pipeline and geometry, but with a different data in the
3937 uniform buffers exposed at binding point 0. This assumes the buffer is
3938 exposed via
3939 \l{QRhiShaderResourceBinding::uniformBufferWithDynamicOffset()}{uniformBufferWithDynamicOffset()}
3940 which allows passing a QRhiCommandBuffer::DynamicOffset list to
3941 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}.
3942
3943 \code
3944 const int N = 2;
3945 const int UB_SIZE = 64 + 4; // assuming a uniform block with { mat4 matrix; float opacity; }
3946 const int ONE_UBUF_SIZE = rhi->ubufAligned(UB_SIZE);
3947 const int TOTAL_UBUF_SIZE = N * ONE_UBUF_SIZE;
3948 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, TOTAL_UBUF_SIZE);
3949 if (!ubuf->create()) { error(); }
3950 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3951 for (int i = 0; i < N; ++i) {
3952 batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE, 64, matrix.constData());
3953 batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE + 64, 4, &opacity);
3954 }
3955 // ...
3956 // beginPass(), set pipeline, etc., and then:
3957 for (int i = 0; i < N; ++i) {
3958 QRhiCommandBuffer::DynamicOffset dynOfs[] = { { 0, i * ONE_UBUF_SIZE } };
3959 cb->setShaderResources(srb, 1, dynOfs);
3960 cb->draw(36);
3961 }
3962 \endcode
3963
3964 \sa QRhiResourceUpdateBatch, QRhi, QRhiCommandBuffer
3965 */
3966
3967/*!
3968 \enum QRhiBuffer::Type
3969 Specifies storage type of buffer resource.
3970
3971 \value Immutable Indicates that the data is not expected to change ever
3972 after the initial upload. Under the hood such buffer resources are
3973 typically placed in device local (GPU) memory (on systems where
3974 applicable). Uploading new data is possible, but may be expensive. The
3975 upload typically happens by copying to a separate, host visible staging
3976 buffer from which a GPU buffer-to-buffer copy is issued into the actual
3977 GPU-only buffer.
3978
3979 \value Static Indicates that the data is expected to change only
3980 infrequently. Typically placed in device local (GPU) memory, where
3981 applicable. On backends where host visible staging buffers are used for
3982 uploading, the staging buffers are kept around for this type, unlike with
3983 Immutable, so subsequent uploads do not suffer in performance. Frequent
3984 updates, especially updates in consecutive frames, should be avoided.
3985
3986 \value Dynamic Indicates that the data is expected to change frequently.
3987 Not recommended for large buffers. Typically backed by host visible memory
3988 in 2 copies in order to allow for changing without stalling the graphics
3989 pipeline. The double buffering is managed transparently to the applications
3990 and is not exposed in the API here in any form. This is the recommended,
3991 and, with some backends, the only possible, type for buffers with
3992 UniformBuffer usage.
3993 */
3994
3995/*!
3996 \enum QRhiBuffer::UsageFlag
3997 Flag values to specify how the buffer is going to be used.
3998
3999 \value VertexBuffer Vertex buffer. This allows the QRhiBuffer to be used in
4000 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
4001
4002 \value IndexBuffer Index buffer. This allows the QRhiBuffer to be used in
4003 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
4004
4005 \value UniformBuffer Uniform buffer (also called constant buffer). This
4006 allows the QRhiBuffer to be used in combination with
4007 \l{QRhiShaderResourceBinding::UniformBuffer}{UniformBuffer}. When
4008 \l{QRhi::NonDynamicUniformBuffers}{NonDynamicUniformBuffers} is reported as
4009 not supported, this usage can only be combined with the type Dynamic.
4010
4011 \value StorageBuffer Storage buffer. This allows the QRhiBuffer to be used
4012 in combination with \l{QRhiShaderResourceBinding::BufferLoad}{BufferLoad},
4013 \l{QRhiShaderResourceBinding::BufferStore}{BufferStore}, or
4014 \l{QRhiShaderResourceBinding::BufferLoadStore}{BufferLoadStore}. This usage
4015 can only be combined with the types Immutable or Static, and is only
4016 available when the \l{QRhi::Compute}{Compute feature} is reported as
4017 supported.
4018
4019 \value [since 6.12] IndirectBuffer Indirect draw buffer. This allows the
4020 QRhiBuffer to be used in \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
4021 and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}.
4022 This usage can be combined with types Immutable or Static. Combining it with
4023 Dynamic is unsupported with D3D11, where create() will fail. This usage may
4024 also be combined with StorageBuffer on backends that support
4025 \l{QRhi::Compute}{compute shaders}, allowing indirect draw commands to be
4026 generated by compute shaders and consumed by indirect draw calls.
4027 */
4028
4029/*!
4030 \class QRhiBuffer::NativeBuffer
4031 \inmodule QtGuiPrivate
4032 \inheaderfile rhi/qrhi.h
4033 \brief Contains information about the underlying native resources of a buffer.
4034 */
4035
4036/*!
4037 \variable QRhiBuffer::NativeBuffer::objects
4038 \brief an array with pointers to the native object handles.
4039
4040 With OpenGL, the native handle is a GLuint value, so the elements in the \c
4041 objects array are pointers to a GLuint. With Vulkan, the native handle is a
4042 VkBuffer, so the elements of the array are pointers to a VkBuffer. With
4043 Direct3D 11 and Metal the elements are pointers to a ID3D11Buffer or
4044 MTLBuffer pointer, respectively. With Direct3D 12, the elements are
4045 pointers to a ID3D12Resource.
4046
4047 \note Pay attention to the fact that the elements are always pointers to
4048 the native buffer handle type, even if the native type itself is a pointer.
4049 (so the elements are \c{VkBuffer *} on Vulkan, even though VkBuffer itself
4050 is a pointer on 64-bit architectures).
4051 */
4052
4053/*!
4054 \variable QRhiBuffer::NativeBuffer::slotCount
4055 \brief Specifies the number of valid elements in the objects array.
4056
4057 The value can be 0, 1, 2, or 3 in practice. 0 indicates that the QRhiBuffer
4058 is not backed by any native buffer objects. This can happen with
4059 QRhiBuffers with the usage UniformBuffer when the underlying API does not
4060 support (or the backend chooses not to use) native uniform buffers. 1 is
4061 commonly used for Immutable and Static types (but some backends may
4062 differ). 2 or 3 is typical when the type is Dynamic (but some backends may
4063 differ).
4064
4065 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4066 */
4067
4068/*!
4069 \internal
4070 */
4071QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, quint32 size_)
4072 : QRhiResource(rhi),
4073 m_type(type_), m_usage(usage_), m_size(size_)
4074{
4075}
4076
4077/*!
4078 \return the resource type.
4079 */
4080QRhiResource::Type QRhiBuffer::resourceType() const
4081{
4082 return Buffer;
4083}
4084
4085/*!
4086 \fn virtual bool QRhiBuffer::create() = 0
4087
4088 Creates the corresponding native graphics resources. If there are already
4089 resources present due to an earlier create() with no corresponding
4090 destroy(), then destroy() is called implicitly first.
4091
4092 \return \c true when successful, \c false when a graphics operation failed.
4093 Regardless of the return value, calling destroy() is always safe.
4094 */
4095
4096/*!
4097 \fn QRhiBuffer::Type QRhiBuffer::type() const
4098 \return the buffer type.
4099 */
4100
4101/*!
4102 \fn void QRhiBuffer::setType(Type t)
4103 Sets the buffer's type to \a t.
4104 */
4105
4106/*!
4107 \fn QRhiBuffer::UsageFlags QRhiBuffer::usage() const
4108 \return the buffer's usage flags.
4109 */
4110
4111/*!
4112 \fn void QRhiBuffer::setUsage(UsageFlags u)
4113 Sets the buffer's usage flags to \a u.
4114 */
4115
4116/*!
4117 \fn quint32 QRhiBuffer::size() const
4118
4119 \return the buffer's size in bytes.
4120
4121 This is always the value that was passed to setSize() or QRhi::newBuffer().
4122 Internally, the native buffers may be bigger if that is required by the
4123 underlying graphics API.
4124 */
4125
4126/*!
4127 \fn void QRhiBuffer::setSize(quint32 sz)
4128
4129 Sets the size of the buffer in bytes. The size is normally specified in
4130 QRhi::newBuffer() so this function is only used when the size has to be
4131 changed. As with other setters, the size only takes effect when calling
4132 create(), and for already created buffers this involves releasing the previous
4133 native resource and creating new ones under the hood.
4134
4135 Backends may choose to allocate buffers bigger than \a sz in order to
4136 fulfill alignment requirements. This is hidden from the applications and
4137 size() will always report the size requested in \a sz.
4138 */
4139
4140/*!
4141 \return the underlying native resources for this buffer. The returned value
4142 will be empty if exposing the underlying native resources is not supported by
4143 the backend.
4144
4145 A QRhiBuffer may be backed by multiple native buffer objects, depending on
4146 the type() and the QRhi backend in use. When this is the case, all of them
4147 are returned in the objects array in the returned struct, with slotCount
4148 specifying the number of native buffer objects. While
4149 \l{QRhi::beginFrame()}{recording a frame}, QRhi::currentFrameSlot() can be
4150 used to determine which of the native buffers QRhi is using for operations
4151 that read or write from this QRhiBuffer within the frame being recorded.
4152
4153 In some cases a QRhiBuffer will not be backed by a native buffer object at
4154 all. In this case slotCount will be set to 0 and no valid native objects
4155 are returned. This is not an error, and is perfectly valid when a given
4156 backend does not use native buffers for QRhiBuffers with certain types or
4157 usages.
4158
4159 \note Be aware that QRhi backends may employ various buffer update
4160 strategies. Unlike textures, where uploading image data always means
4161 recording a buffer-to-image (or similar) copy command on the command
4162 buffer, buffers, in particular Dynamic and UniformBuffer ones, can operate
4163 in many different ways. For example, a QRhiBuffer with usage type
4164 UniformBuffer may not even be backed by a native buffer object at all if
4165 uniform buffers are not used or supported by a given backend and graphics
4166 API. There are also differences to how data is written to the buffer and
4167 the type of backing memory used. For buffers backed by host visible memory,
4168 calling this function guarantees that pending host writes are executed for
4169 all the returned native buffers.
4170
4171 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4172 */
4173QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
4174{
4175 return { {}, 0 };
4176}
4177
4178/*!
4179 \return a pointer to a memory block with the host visible buffer data.
4180
4181 This is a shortcut for medium-to-large dynamic uniform buffers that have
4182 their \b entire contents (or at least all regions that are read by the
4183 shaders in the current frame) changed \b{in every frame} and the
4184 QRhiResourceUpdateBatch-based update mechanism is seen too heavy due to the
4185 amount of data copying involved.
4186
4187 The call to this function must be eventually followed by a call to
4188 endFullDynamicUniformBufferUpdateForCurrentFrame(), before recording any
4189 render or compute pass that relies on this buffer.
4190
4191 \warning Updating data via this method is not compatible with
4192 QRhiResourceUpdateBatch-based updates and readbacks. Unexpected behavior
4193 may occur when attempting to combine the two update models for the same
4194 buffer. Similarly, the data updated this direct way may not be visible to
4195 \l{QRhiResourceUpdateBatch::readBackBuffer()}{readBackBuffer operations},
4196 depending on the backend.
4197
4198 \warning When updating buffer data via this method, the update must be done
4199 in every frame, otherwise backends that perform double or triple buffering
4200 of resources may end up in unexpected behavior.
4201
4202 \warning Partial updates are not possible with this approach since some
4203 backends may choose a strategy where the previous contents of the buffer is
4204 lost upon calling this function. Data must be written to all regions that
4205 are read by shaders in the frame currently being prepared.
4206
4207 \warning This function can only be called when recording a frame, so
4208 between QRhi::beginFrame() and QRhi::endFrame().
4209
4210 \warning This function can only be called on Dynamic buffers.
4211 */
4212char *QRhiBuffer::beginFullDynamicBufferUpdateForCurrentFrame()
4213{
4214 return nullptr;
4215}
4216
4217/*!
4218 To be called when the entire contents of the buffer data has been updated
4219 in the memory block returned from
4220 beginFullDynamicBufferUpdateForCurrentFrame().
4221 */
4222void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
4223{
4224}
4225
4226/*!
4227 \internal
4228 */
4229void QRhiBuffer::fullDynamicBufferUpdateForCurrentFrame(const void *data, quint32 size)
4230{
4231 char *p = beginFullDynamicBufferUpdateForCurrentFrame();
4232 if (p) {
4233 memcpy(p, data, size > 0 ? size : m_size);
4234 endFullDynamicBufferUpdateForCurrentFrame();
4235 }
4236}
4237
4238/*!
4239 \class QRhiRenderBuffer
4240 \inmodule QtGuiPrivate
4241 \inheaderfile rhi/qrhi.h
4242 \since 6.6
4243 \brief Renderbuffer resource.
4244
4245 Renderbuffers cannot be sampled or read but have some benefits over
4246 textures in some cases:
4247
4248 A \l DepthStencil renderbuffer may be lazily allocated and be backed by
4249 transient memory with some APIs. On some platforms this may mean the
4250 depth/stencil buffer uses no physical backing at all.
4251
4252 \l Color renderbuffers are useful since QRhi::MultisampleRenderBuffer may be
4253 supported even when QRhi::MultisampleTexture is not.
4254
4255 How the renderbuffer is implemented by a backend is not exposed to the
4256 applications. In some cases it may be backed by ordinary textures, while in
4257 others there may be a different kind of native resource used.
4258
4259 Renderbuffers that are used as (and are only used as) depth-stencil buffers
4260 in combination with a QRhiSwapChain's color buffers should have the
4261 UsedWithSwapChainOnly flag set. This serves a double purpose: such buffers,
4262 depending on the backend and the underlying APIs, be more efficient, and
4263 QRhi provides automatic sizing behavior to match the color buffers, which
4264 means calling setPixelSize() and create() are not necessary for such
4265 renderbuffers.
4266
4267 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4268 for details.
4269 */
4270
4271/*!
4272 \enum QRhiRenderBuffer::Type
4273 Specifies the type of the renderbuffer
4274
4275 \value DepthStencil Combined depth/stencil
4276 \value Color Color
4277 */
4278
4279/*!
4280 \struct QRhiRenderBuffer::NativeRenderBuffer
4281 \inmodule QtGuiPrivate
4282 \inheaderfile rhi/qrhi.h
4283 \brief Wraps a native renderbuffer object.
4284 */
4285
4286/*!
4287 \variable QRhiRenderBuffer::NativeRenderBuffer::object
4288 \brief 64-bit integer containing the native object handle.
4289
4290 Used with QRhiRenderBuffer::createFrom().
4291
4292 With OpenGL the native handle is a GLuint value. \c object is expected to
4293 be a valid OpenGL renderbuffer object ID.
4294 */
4295
4296/*!
4297 \enum QRhiRenderBuffer::Flag
4298 Flag values for flags() and setFlags()
4299
4300 \value UsedWithSwapChainOnly For DepthStencil renderbuffers this indicates
4301 that the renderbuffer is only used in combination with a QRhiSwapChain, and
4302 never in any other way. This provides automatic sizing and resource
4303 rebuilding, so calling setPixelSize() or create() is not needed whenever
4304 this flag is set. This flag value may also trigger backend-specific
4305 behavior, for example with OpenGL, where a separate windowing system
4306 interface API is in use (EGL, GLX, etc.), the flag is especially important
4307 as it avoids creating any actual renderbuffer resource as there is already
4308 a windowing system provided depth/stencil buffer as requested by
4309 QSurfaceFormat.
4310 */
4311
4312/*!
4313 \internal
4314 */
4315QRhiRenderBuffer::QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
4316 int sampleCount_, Flags flags_,
4317 QRhiTexture::Format backingFormatHint_)
4318 : QRhiResource(rhi),
4319 m_type(type_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_),
4320 m_backingFormatHint(backingFormatHint_)
4321{
4322}
4323
4324/*!
4325 \return the resource type.
4326 */
4327QRhiResource::Type QRhiRenderBuffer::resourceType() const
4328{
4329 return RenderBuffer;
4330}
4331
4332/*!
4333 \fn virtual bool QRhiRenderBuffer::create() = 0
4334
4335 Creates the corresponding native graphics resources. If there are already
4336 resources present due to an earlier create() with no corresponding
4337 destroy(), then destroy() is called implicitly first.
4338
4339 \return \c true when successful, \c false when a graphics operation failed.
4340 Regardless of the return value, calling destroy() is always safe.
4341 */
4342
4343/*!
4344 Similar to create() except that no new native renderbuffer objects are
4345 created. Instead, the native renderbuffer object specified by \a src is
4346 used.
4347
4348 This allows importing an existing renderbuffer object (which must belong to
4349 the same device or sharing context, depending on the graphics API) from an
4350 external graphics engine.
4351
4352 \note This is currently applicable to OpenGL only. This function exists
4353 solely to allow importing a renderbuffer object that is bound to some
4354 special, external object, such as an EGLImageKHR. Once the application
4355 performed the glEGLImageTargetRenderbufferStorageOES call, the renderbuffer
4356 object can be passed to this function to create a wrapping
4357 QRhiRenderBuffer, which in turn can be passed in as a color attachment to
4358 a QRhiTextureRenderTarget to enable rendering to the EGLImage.
4359
4360 \note pixelSize(), sampleCount(), and flags() must still be set correctly.
4361 Passing incorrect sizes and other values to QRhi::newRenderBuffer() and
4362 then following it with a createFrom() expecting that the native
4363 renderbuffer object alone is sufficient to deduce such values is \b wrong
4364 and will lead to problems.
4365
4366 \note QRhiRenderBuffer does not take ownership of the native object, and
4367 destroy() will not release that object.
4368
4369 \note This function is only implemented when the QRhi::RenderBufferImport
4370 feature is reported as \l{QRhi::isFeatureSupported()}{supported}. Otherwise,
4371 the function does nothing and the return value is \c false.
4372
4373 \return \c true when successful, \c false when not supported.
4374 */
4375bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
4376{
4377 Q_UNUSED(src);
4378 return false;
4379}
4380
4381/*!
4382 \fn QRhiRenderBuffer::Type QRhiRenderBuffer::type() const
4383 \return the renderbuffer type.
4384 */
4385
4386/*!
4387 \fn void QRhiRenderBuffer::setType(Type t)
4388 Sets the type to \a t.
4389 */
4390
4391/*!
4392 \fn QSize QRhiRenderBuffer::pixelSize() const
4393 \return the pixel size.
4394 */
4395
4396/*!
4397 \fn void QRhiRenderBuffer::setPixelSize(const QSize &sz)
4398 Sets the size (in pixels) to \a sz.
4399 */
4400
4401/*!
4402 \fn int QRhiRenderBuffer::sampleCount() const
4403 \return the sample count. 1 means no multisample antialiasing.
4404 */
4405
4406/*!
4407 \fn void QRhiRenderBuffer::setSampleCount(int s)
4408 Sets the sample count to \a s.
4409 */
4410
4411/*!
4412 \fn QRhiRenderBuffer::Flags QRhiRenderBuffer::flags() const
4413 \return the flags.
4414 */
4415
4416/*!
4417 \fn void QRhiRenderBuffer::setFlags(Flags f)
4418 Sets the flags to \a f.
4419 */
4420
4421/*!
4422 \fn virtual QRhiTexture::Format QRhiRenderBuffer::backingFormat() const = 0
4423
4424 \internal
4425 */
4426
4427/*!
4428 \class QRhiTexture
4429 \inmodule QtGuiPrivate
4430 \inheaderfile rhi/qrhi.h
4431 \since 6.6
4432 \brief Texture resource.
4433
4434 A QRhiTexture encapsulates a native texture object, such as a \c VkImage or
4435 \c MTLTexture.
4436
4437 A QRhiTexture instance is always created by calling
4438 \l{QRhi::newTexture()}{the QRhi's newTexture() function}. This creates no
4439 native graphics resources. To do that, call create() after setting the
4440 appropriate options, such as the format and size, although in most cases
4441 these are already set based on the arguments passed to
4442 \l{QRhi::newTexture()}{newTexture()}.
4443
4444 Setting the \l{QRhiTexture::Flags}{flags} correctly is essential, otherwise
4445 various errors can occur depending on the underlying QRhi backend and
4446 graphics API. For example, when a texture will be rendered into from a
4447 render pass via QRhiTextureRenderTarget, the texture must be created with
4448 the \l RenderTarget flag set. Similarly, when the texture is going to be
4449 \l{QRhiResourceUpdateBatch::readBackTexture()}{read back}, the \l
4450 UsedAsTransferSource flag must be set upfront. Mipmapped textures must have
4451 the MipMapped flag set. And so on. It is not possible to change the flags
4452 once create() has succeeded. To release the existing and create a new
4453 native texture object with the changed settings, call the setters and call
4454 create() again. This then might be a potentially expensive operation.
4455
4456 \section2 Example usage
4457
4458 To create a 2D texture with a size of 512x512 pixels and set its contents to all green:
4459
4460 \code
4461 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512));
4462 if (!texture->create()) { error(); }
4463 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4464 QImage image(512, 512, QImage::Format_RGBA8888);
4465 image.fill(Qt::green);
4466 batch->uploadTexture(texture, image);
4467 // ...
4468 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4469 \endcode
4470
4471 \section2 Common patterns
4472
4473 A call to create() destroys any existing native resources if create() was
4474 successfully called before. If those native resources are still in use by
4475 an in-flight frame (i.e., there's a chance they are still read by the GPU),
4476 the destroying of those resources is deferred automatically. Thus a very
4477 common and convenient pattern to safely change the size of an already
4478 existing texture is the following. In practice this drops and creates a
4479 whole new native texture resource underneath, so it is not necessarily a
4480 cheap operation, but is more convenient and still faster than the
4481 alternatives, because by not destroying the \c texture object itself, all
4482 references to it stay valid in other data structures (e.g., in any
4483 QShaderResourceBinding the QRhiTexture is referenced from).
4484
4485 \code
4486 // determine newSize, e.g. based on the swapchain's output size or other factors
4487 if (texture->pixelSize() != newSize) {
4488 texture->setPixelSize(newSize);
4489 if (!texture->create()) { error(); }
4490 }
4491 // continue using texture, fill it with new data
4492 \endcode
4493
4494 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4495 for details.
4496
4497 \sa QRhiResourceUpdateBatch, QRhi, QRhiTextureRenderTarget
4498 */
4499
4500/*!
4501 \enum QRhiTexture::Flag
4502
4503 Flag values to specify how the texture is going to be used. Not honoring
4504 the flags set before create() and attempting to use the texture in ways that
4505 was not declared upfront can lead to unspecified behavior or decreased
4506 performance depending on the backend and the underlying graphics API.
4507
4508 \value RenderTarget The texture going to be used in combination with
4509 QRhiTextureRenderTarget.
4510
4511 \value CubeMap The texture is a cubemap. Such textures have 6 layers, one
4512 for each face in the order of +X, -X, +Y, -Y, +Z, -Z. Cubemap textures
4513 cannot be multisample.
4514
4515 \value MipMapped The texture has mipmaps. The appropriate mip count is
4516 calculated automatically and can also be retrieved via
4517 QRhi::mipLevelsForSize(). The images for the mip levels have to be
4518 provided in the texture uploaded or generated via
4519 QRhiResourceUpdateBatch::generateMips(). Multisample textures cannot have
4520 mipmaps.
4521
4522 \value sRGB Use an sRGB format.
4523
4524 \value UsedAsTransferSource The texture is used as the source of a texture
4525 copy or readback, meaning the texture is given as the source in
4526 QRhiResourceUpdateBatch::copyTexture() or
4527 QRhiResourceUpdateBatch::readBackTexture().
4528
4529 \value UsedWithGenerateMips The texture is going to be used with
4530 QRhiResourceUpdateBatch::generateMips().
4531
4532 \value UsedWithLoadStore The texture is going to be used with image
4533 load/store operations, for example, in a compute shader.
4534
4535 \value UsedAsCompressedAtlas The texture has a compressed format and the
4536 dimensions of subresource uploads may not match the texture size.
4537
4538 \value ExternalOES The texture should use the GL_TEXTURE_EXTERNAL_OES
4539 target with OpenGL. This flag is ignored with other graphics APIs.
4540
4541 \value ThreeDimensional The texture is a 3D texture. Such textures should
4542 be created with the QRhi::newTexture() overload taking a depth in addition
4543 to width and height. A 3D texture can have mipmaps but cannot be
4544 multisample. When rendering into, or uploading data to a 3D texture, the \c
4545 layer specified in the render target's color attachment or the upload
4546 description refers to a single slice in range [0..depth-1]. The underlying
4547 graphics API may not support 3D textures at run time. Support is indicated
4548 by the QRhi::ThreeDimensionalTextures feature.
4549
4550 \value TextureRectangleGL The texture should use the GL_TEXTURE_RECTANGLE
4551 target with OpenGL. This flag is ignored with other graphics APIs. Just
4552 like ExternalOES, this flag is useful when working with platform APIs where
4553 native OpenGL texture objects received from the platform are wrapped in a
4554 QRhiTexture, and the platform can only provide textures for a non-2D
4555 texture target.
4556
4557 \value TextureArray The texture is a texture array, i.e. a single texture
4558 object that is a homogeneous array of 2D textures. Texture arrays are
4559 created with QRhi::newTextureArray(). The underlying graphics API may not
4560 support texture array objects at run time. Support is indicated by the
4561 QRhi::TextureArrays feature. When rendering into, or uploading data to a
4562 texture array, the \c layer specified in the render target's color
4563 attachment or the upload description selects a single element in the array.
4564
4565 \value OneDimensional The texture is a 1D texture. Such textures can be
4566 created by passing a 0 height and depth to QRhi::newTexture(). Note that
4567 there can be limitations on one dimensional textures depending on the
4568 underlying graphics API. For example, rendering to them or using them with
4569 mipmap-based filtering may be unsupported. This is indicated by the
4570 QRhi::OneDimensionalTextures and QRhi::OneDimensionalTextureMipmaps
4571 feature flags.
4572
4573 \value UsedAsShadingRateMap
4574 */
4575
4576/*!
4577 \enum QRhiTexture::Format
4578
4579 Specifies the texture format. See also QRhi::isTextureFormatSupported() and
4580 note that flags() can modify the format when QRhiTexture::sRGB is set.
4581
4582 \value UnknownFormat Not a valid format. This cannot be passed to setFormat().
4583
4584 \value RGBA8 Four components, unsigned normalized 8-bit per component. Always supported. (32 bits total)
4585
4586 \value BGRA8 Four components, unsigned normalized 8-bit per component. (32 bits total)
4587
4588 \value R8 One component, unsigned normalized 8-bit. (8 bits total)
4589
4590 \value RG8 Two components, unsigned normalized 8-bit. (16 bits total)
4591
4592 \value R16 One component, unsigned normalized 16-bit. (16 bits total)
4593
4594 \value RG16 Two components, unsigned normalized 16-bit. (32 bits total)
4595
4596 \value RED_OR_ALPHA8 Either same as R8, or is a similar format with the component swizzled to alpha,
4597 depending on \l{QRhi::RedOrAlpha8IsRed}{RedOrAlpha8IsRed}. (8 bits total)
4598
4599 \value RGBA16F Four components, 16-bit float. (64 bits total)
4600
4601 \value RGBA32F Four components, 32-bit float. (128 bits total)
4602
4603 \value R16F One component, 16-bit float. (16 bits total)
4604
4605 \value R32F One component, 32-bit float. (32 bits total)
4606
4607 \value RGB10A2 Four components, unsigned normalized 10 bit R, G, and B,
4608 2-bit alpha. This is a packed format so native endianness applies. Note
4609 that there is no BGR10A2. This is because RGB10A2 maps to
4610 DXGI_FORMAT_R10G10B10A2_UNORM with D3D, MTLPixelFormatRGB10A2Unorm with
4611 Metal, VK_FORMAT_A2B10G10R10_UNORM_PACK32 with Vulkan, and
4612 GL_RGB10_A2/GL_RGB/GL_UNSIGNED_INT_2_10_10_10_REV on OpenGL (ES). This is
4613 the only universally supported RGB30 option. The corresponding QImage
4614 formats are QImage::Format_BGR30 and QImage::Format_A2BGR30_Premultiplied.
4615 (32 bits total)
4616
4617 \value D16 16-bit depth (normalized unsigned integer)
4618
4619 \value D24 24-bit depth (normalized unsigned integer)
4620
4621 \value D24S8 24-bit depth (normalized unsigned integer), 8 bit stencil
4622
4623 \value D32F 32-bit depth (32-bit float)
4624
4625 \value [since 6.9] D32FS8 32-bit depth (32-bit float), 8 bits of stencil, 24 bits unused
4626 (64 bits total)
4627
4628 \value BC1
4629 \value BC2
4630 \value BC3
4631 \value BC4
4632 \value BC5
4633 \value BC6H
4634 \value BC7
4635
4636 \value ETC2_RGB8
4637 \value ETC2_RGB8A1
4638 \value ETC2_RGBA8
4639
4640 \value ASTC_4x4
4641 \value ASTC_5x4
4642 \value ASTC_5x5
4643 \value ASTC_6x5
4644 \value ASTC_6x6
4645 \value ASTC_8x5
4646 \value ASTC_8x6
4647 \value ASTC_8x8
4648 \value ASTC_10x5
4649 \value ASTC_10x6
4650 \value ASTC_10x8
4651 \value ASTC_10x10
4652 \value ASTC_12x10
4653 \value ASTC_12x12
4654
4655 \value [since 6.9] R8UI One component, unsigned 8-bit. (8 bits total)
4656 \value [since 6.9] R32UI One component, unsigned 32-bit. (32 bits total)
4657 \value [since 6.9] RG32UI Two components, unsigned 32-bit. (64 bits total)
4658 \value [since 6.9] RGBA32UI Four components, unsigned 32-bit. (128 bits total)
4659
4660 \value [since 6.10] R8SI One component, signed 8-bit. (8 bits total)
4661 \value [since 6.10] R32SI One component, signed 32-bit. (32 bits total)
4662 \value [since 6.10] RG32SI Two components, signed 32-bit. (64 bits total)
4663 \value [since 6.10] RGBA32SI Four components, signed 32-bit. (128 bits total)
4664 */
4665
4666// When adding new texture formats, update void tst_QRhi::textureFormats_data().
4667
4668/*!
4669 \struct QRhiTexture::NativeTexture
4670 \inmodule QtGuiPrivate
4671 \inheaderfile rhi/qrhi.h
4672 \brief Contains information about the underlying native resources of a texture.
4673 */
4674
4675/*!
4676 \variable QRhiTexture::NativeTexture::object
4677 \brief 64-bit integer containing the native object handle.
4678
4679 With OpenGL, the native handle is a GLuint value, so \c object can then be
4680 cast to a GLuint. With Vulkan, the native handle is a VkImage, so \c object
4681 can be cast to a VkImage. With Direct3D 11 and Metal \c object contains a
4682 ID3D11Texture2D or MTLTexture pointer, respectively. With Direct3D 12
4683 \c object contains a ID3D12Resource pointer.
4684 */
4685
4686/*!
4687 \variable QRhiTexture::NativeTexture::layout
4688 \brief Specifies the current image layout for APIs like Vulkan.
4689
4690 For Vulkan, \c layout contains a \c VkImageLayout value.
4691 */
4692
4693/*!
4694 \internal
4695 */
4696QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
4697 int arraySize_, int sampleCount_, Flags flags_)
4698 : QRhiResource(rhi),
4699 m_format(format_), m_pixelSize(pixelSize_), m_depth(depth_),
4700 m_arraySize(arraySize_), m_sampleCount(sampleCount_), m_flags(flags_)
4701{
4702}
4703
4704/*!
4705 \return the resource type.
4706 */
4707QRhiResource::Type QRhiTexture::resourceType() const
4708{
4709 return Texture;
4710}
4711
4712/*!
4713 \fn virtual bool QRhiTexture::create() = 0
4714
4715 Creates the corresponding native graphics resources. If there are already
4716 resources present due to an earlier create() with no corresponding
4717 destroy(), then destroy() is called implicitly first.
4718
4719 \return \c true when successful, \c false when a graphics operation failed.
4720 Regardless of the return value, calling destroy() is always safe.
4721 */
4722
4723/*!
4724 \return the underlying native resources for this texture. The returned value
4725 will be empty if exposing the underlying native resources is not supported by
4726 the backend.
4727
4728 \sa createFrom()
4729 */
4730QRhiTexture::NativeTexture QRhiTexture::nativeTexture()
4731{
4732 return {};
4733}
4734
4735/*!
4736 Similar to create(), except that no new native textures are created.
4737 Instead, the native texture resources specified by \a src is used.
4738
4739 This allows importing an existing native texture object (which must belong
4740 to the same device or sharing context, depending on the graphics API) from
4741 an external graphics engine.
4742
4743 \return true if the specified existing native texture object has been
4744 successfully wrapped as a non-owning QRhiTexture.
4745
4746 \note format(), pixelSize(), sampleCount(), and flags() must still be set
4747 correctly. Passing incorrect sizes and other values to QRhi::newTexture()
4748 and then following it with a createFrom() expecting that the native texture
4749 object alone is sufficient to deduce such values is \b wrong and will lead
4750 to problems.
4751
4752 \note QRhiTexture does not take ownership of the texture object. destroy()
4753 does not free the object or any associated memory.
4754
4755 The opposite of this operation, exposing a QRhiTexture-created native
4756 texture object to a foreign engine, is possible via nativeTexture().
4757
4758 \note When importing a 3D texture, or a texture array object, or, with
4759 OpenGL ES, an external texture, it is then especially important to set the
4760 corresponding flags (ThreeDimensional, TextureArray, ExternalOES) via
4761 setFlags() before calling this function.
4762*/
4763bool QRhiTexture::createFrom(QRhiTexture::NativeTexture src)
4764{
4765 Q_UNUSED(src);
4766 return false;
4767}
4768
4769/*!
4770 With some graphics APIs, such as Vulkan, integrating custom rendering code
4771 that uses the graphics API directly needs special care when it comes to
4772 image layouts. This function allows communicating the expected \a layout the
4773 image backing the QRhiTexture is in after the native rendering commands.
4774
4775 For example, consider rendering into a QRhiTexture's VkImage directly with
4776 Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and
4777 QRhiCommandBuffer::endExternal(), followed by using the image for texture
4778 sampling in a QRhi-based render pass. To avoid potentially incorrect image
4779 layout transitions, this function can be used to indicate what the image
4780 layout will be once the commands recorded in said code block complete.
4781
4782 Calling this function makes sense only after
4783 QRhiCommandBuffer::endExternal() and before a subsequent
4784 QRhiCommandBuffer::beginPass().
4785
4786 This function has no effect with QRhi backends where the underlying
4787 graphics API does not expose a concept of image layouts.
4788
4789 \note With Vulkan \a layout is a \c VkImageLayout. With Direct 3D 12 \a
4790 layout is a value composed of the bits from \c D3D12_RESOURCE_STATES.
4791 */
4792void QRhiTexture::setNativeLayout(int layout)
4793{
4794 Q_UNUSED(layout);
4795}
4796
4797/*!
4798 \fn QRhiTexture::Format QRhiTexture::format() const
4799 \return the texture format.
4800 */
4801
4802/*!
4803 \fn void QRhiTexture::setFormat(QRhiTexture::Format fmt)
4804
4805 Sets the requested texture format to \a fmt.
4806
4807 \note The value set is only taken into account upon the next call to
4808 create(), i.e. when the underlying graphics resource are (re)created.
4809 Setting a new value is futile otherwise and must be avoided since it can
4810 lead to inconsistent state.
4811 */
4812
4813/*!
4814 \fn QSize QRhiTexture::pixelSize() const
4815 \return the size in pixels.
4816 */
4817
4818/*!
4819 \fn void QRhiTexture::setPixelSize(const QSize &sz)
4820
4821 Sets the texture size, specified in pixels, to \a sz.
4822
4823 \note The value set is only taken into account upon the next call to
4824 create(), i.e. when the underlying graphics resource are (re)created.
4825 Setting a new value is futile otherwise and must be avoided since it can
4826 lead to inconsistent state. The same applies to all other setters as well.
4827 */
4828
4829/*!
4830 \fn int QRhiTexture::depth() const
4831 \return the depth for 3D textures.
4832 */
4833
4834/*!
4835 \fn void QRhiTexture::setDepth(int depth)
4836 Sets the \a depth for a 3D texture.
4837 */
4838
4839/*!
4840 \fn int QRhiTexture::arraySize() const
4841 \return the texture array size.
4842 */
4843
4844/*!
4845 \fn void QRhiTexture::setArraySize(int arraySize)
4846 Sets the texture \a arraySize.
4847 */
4848
4849/*!
4850 \fn int QRhiTexture::arrayRangeStart() const
4851
4852 \return the first array layer when setArrayRange() was called.
4853
4854 \sa setArrayRange()
4855 */
4856
4857/*!
4858 \fn int QRhiTexture::arrayRangeLength() const
4859
4860 \return the exposed array range size when setArrayRange() was called.
4861
4862 \sa setArrayRange()
4863*/
4864
4865/*!
4866 \fn void QRhiTexture::setArrayRange(int startIndex, int count)
4867
4868 Normally all array layers are exposed and it is up to the shader to select
4869 the layer via the third coordinate passed to the \c{texture()} GLSL
4870 function when sampling the \c sampler2DArray. When QRhi::TextureArrayRange
4871 is reported as supported, calling setArrayRange() before create() or
4872 createFrom() requests selecting only the specified range, \a count elements
4873 starting from \a startIndex. The shader logic can then be written with this
4874 in mind.
4875
4876 \sa QRhi::TextureArrayRange
4877 */
4878
4879/*!
4880 \fn Flags QRhiTexture::flags() const
4881 \return the texture flags.
4882 */
4883
4884/*!
4885 \fn void QRhiTexture::setFlags(Flags f)
4886 Sets the texture flags to \a f.
4887 */
4888
4889/*!
4890 \fn int QRhiTexture::sampleCount() const
4891 \return the sample count. 1 means no multisample antialiasing.
4892 */
4893
4894/*!
4895 \fn void QRhiTexture::setSampleCount(int s)
4896 Sets the sample count to \a s.
4897 */
4898
4899/*!
4900 \struct QRhiTexture::ViewFormat
4901 \inmodule QtGuiPrivate
4902 \inheaderfile rhi/qrhi.h
4903 \since 6.8
4904 \brief Specifies the view format for reading or writing from or to the texture.
4905
4906 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4907 for details.
4908 */
4909
4910/*!
4911 \variable QRhiTexture::ViewFormat::format
4912 */
4913
4914/*!
4915 \variable QRhiTexture::ViewFormat::srgb
4916 */
4917
4918/*!
4919 \fn QRhiTexture::ViewFormat QRhiTexture::readViewFormat() const
4920 \since 6.8
4921 \return the view format used when sampling the texture. When not called, the view
4922 format is assumed to be the same as format().
4923 */
4924
4925/*!
4926 \fn void QRhiTexture::setReadViewFormat(const ViewFormat &fmt)
4927 \since 6.8
4928
4929 Sets the shader resource view format (or the format of the view used for
4930 sampling the texture) to \a fmt. By default the same format (and sRGB-ness)
4931 is used as the texture itself, and in most cases this function does not need
4932 to be called.
4933
4934 This setting is only taken into account when the \l QRhi::TextureViewFormat
4935 feature is reported as supported.
4936
4937 \note This functionality is provided to allow "casting" between
4938 non-sRGB and sRGB in order to get the shader reads perform, or not perform,
4939 the implicit sRGB conversions. Other types of casting may or may not be
4940 functional.
4941 */
4942
4943/*!
4944 \fn QRhiTexture::ViewFormat QRhiTexture::writeViewFormat() const
4945 \since 6.8
4946 \return the view format used when writing to the texture and when using it
4947 with image load/store. When not called, the view format is assumed to be the
4948 same as format().
4949 */
4950
4951/*!
4952 \fn void QRhiTexture::setWriteViewFormat(const ViewFormat &fmt)
4953 \since 6.8
4954
4955 Sets the render target view format to \a fmt. By default the same format
4956 (and sRGB-ness) is used as the texture itself, and in most cases this
4957 function does not need to be called.
4958
4959 One common use case for providing a write view format is working with
4960 externally provided textures that, outside of our control, use an sRGB
4961 format with 3D APIs such as Vulkan or Direct 3D, but the rendering engine is
4962 already prepared to handle linearization and conversion to sRGB at the end
4963 of its shading pipeline. In this case what is wanted when rendering into
4964 such a texture is a render target view (e.g. VkImageView) that has the same,
4965 but non-sRGB format. (if e.g. from an OpenXR implementation one gets a
4966 VK_FORMAT_R8G8B8A8_SRGB texture, it is likely that rendering into it should
4967 be done using a VK_FORMAT_R8G8B8A8_UNORM view, if that is what the rendering
4968 engine's pipeline requires; in this example one would call this function
4969 with a ViewFormat that has a format of QRhiTexture::RGBA8 and \c srgb set to
4970 \c false).
4971
4972 This setting is only taken into account when the \l QRhi::TextureViewFormat
4973 feature is reported as supported.
4974
4975 \note This functionality is provided to allow "casting" between
4976 non-sRGB and sRGB in order to get the shader write not perform, or perform,
4977 the implicit sRGB conversions. Other types of casting may or may not be
4978 functional.
4979 */
4980
4981/*!
4982 \class QRhiSampler
4983 \inmodule QtGuiPrivate
4984 \inheaderfile rhi/qrhi.h
4985 \since 6.6
4986 \brief Sampler resource.
4987
4988 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4989 for details.
4990 */
4991
4992/*!
4993 \enum QRhiSampler::Filter
4994 Specifies the minification, magnification, or mipmap filtering
4995
4996 \value None Applicable only for mipmapMode(), indicates no mipmaps to be used
4997 \value Nearest
4998 \value Linear
4999 */
5000
5001/*!
5002 \enum QRhiSampler::AddressMode
5003 Specifies the addressing mode
5004
5005 \value Repeat
5006 \value ClampToEdge
5007 \value Mirror
5008 */
5009
5010/*!
5011 \enum QRhiSampler::CompareOp
5012 Specifies the texture comparison function.
5013
5014 \value Never (default)
5015 \value Less
5016 \value Equal
5017 \value LessOrEqual
5018 \value Greater
5019 \value NotEqual
5020 \value GreaterOrEqual
5021 \value Always
5022 */
5023
5024/*!
5025 \internal
5026 */
5027QRhiSampler::QRhiSampler(QRhiImplementation *rhi,
5028 Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
5029 AddressMode u_, AddressMode v_, AddressMode w_)
5030 : QRhiResource(rhi),
5031 m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_),
5032 m_addressU(u_), m_addressV(v_), m_addressW(w_),
5033 m_compareOp(QRhiSampler::Never)
5034{
5035}
5036
5037/*!
5038 \return the resource type.
5039 */
5040QRhiResource::Type QRhiSampler::resourceType() const
5041{
5042 return Sampler;
5043}
5044
5045/*!
5046 \fn QRhiSampler::Filter QRhiSampler::magFilter() const
5047 \return the magnification filter mode.
5048 */
5049
5050/*!
5051 \fn void QRhiSampler::setMagFilter(Filter f)
5052 Sets the magnification filter mode to \a f.
5053 */
5054
5055/*!
5056 \fn QRhiSampler::Filter QRhiSampler::minFilter() const
5057 \return the minification filter mode.
5058 */
5059
5060/*!
5061 \fn void QRhiSampler::setMinFilter(Filter f)
5062 Sets the minification filter mode to \a f.
5063 */
5064
5065/*!
5066 \fn QRhiSampler::Filter QRhiSampler::mipmapMode() const
5067 \return the mipmap filter mode.
5068 */
5069
5070/*!
5071 \fn void QRhiSampler::setMipmapMode(Filter f)
5072
5073 Sets the mipmap filter mode to \a f.
5074
5075 Leave this set to None when the texture has no mip levels, or when the mip
5076 levels are not to be taken into account.
5077 */
5078
5079/*!
5080 \fn QRhiSampler::AddressMode QRhiSampler::addressU() const
5081 \return the horizontal wrap mode.
5082 */
5083
5084/*!
5085 \fn void QRhiSampler::setAddressU(AddressMode mode)
5086 Sets the horizontal wrap \a mode.
5087 */
5088
5089/*!
5090 \fn QRhiSampler::AddressMode QRhiSampler::addressV() const
5091 \return the vertical wrap mode.
5092 */
5093
5094/*!
5095 \fn void QRhiSampler::setAddressV(AddressMode mode)
5096 Sets the vertical wrap \a mode.
5097 */
5098
5099/*!
5100 \fn QRhiSampler::AddressMode QRhiSampler::addressW() const
5101 \return the depth wrap mode.
5102 */
5103
5104/*!
5105 \fn void QRhiSampler::setAddressW(AddressMode mode)
5106 Sets the depth wrap \a mode.
5107 */
5108
5109/*!
5110 \fn QRhiSampler::CompareOp QRhiSampler::textureCompareOp() const
5111 \return the texture comparison function.
5112 */
5113
5114/*!
5115 \fn void QRhiSampler::setTextureCompareOp(CompareOp op)
5116 Sets the texture comparison function \a op.
5117 */
5118
5119/*!
5120 \class QRhiShadingRateMap
5121 \inmodule QtGuiPrivate
5122 \inheaderfile rhi/qrhi.h
5123 \since 6.9
5124 \brief An object that wraps a texture or another kind of native 3D API object.
5125
5126 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5127 for details.
5128
5129 For an introduction to Variable Rate Shading (VRS), see
5130 \l{https://learn.microsoft.com/en-us/windows/win32/direct3d12/vrs}. Qt
5131 supports a subset of the VRS features offered by Direct 3D 12 and Vulkan. In
5132 addition, Metal's somewhat different mechanism is supported by making it
5133 possible to set up a QRhiShadingRateMap with an existing
5134 MTLRasterizationRateMap object.
5135 */
5136
5137/*!
5138 \struct QRhiShadingRateMap::NativeShadingRateMap
5139 \inmodule QtGuiPrivate
5140 \inheaderfile rhi/qrhi.h
5141 \since 6.9
5142 \brief Wraps a native shading rate map.
5143
5144 An example is MTLRasterizationRateMap with Metal. Other 3D APIs that use
5145 textures for image-based VRS do not use this struct since those can function
5146 via the QRhiTexture-based overload of QRhiShadingRateMap::createFrom().
5147 */
5148
5149/*!
5150 \variable QRhiShadingRateMap::NativeShadingRateMap::object
5151 \brief 64-bit integer containing the native object handle.
5152
5153 Used with QRhiShadingRateMap::createFrom(). For example, with Metal,
5154 \c object is expected to be an id<MTLRasterizationRateMap>.
5155 */
5156
5157/*!
5158 \internal
5159 */
5160QRhiShadingRateMap::QRhiShadingRateMap(QRhiImplementation *rhi)
5161 : QRhiResource(rhi)
5162{
5163}
5164
5165/*!
5166 \return the resource type.
5167 */
5168QRhiResource::Type QRhiShadingRateMap::resourceType() const
5169{
5170 return ShadingRateMap;
5171}
5172
5173/*!
5174 Sets up the shading rate map to use a native 3D API shading rate object
5175 \a src.
5176
5177 \return \c true when successful, \c false when not supported.
5178
5179 \note This is functional only when the QRhi::VariableRateShadingMap feature
5180 is reported as supported, while QRhi::VariableRateShadingMapWithTexture
5181 feature is not. Currently this is true for Metal, assuming variable rate
5182 shading is supported by the GPU.
5183
5184 \note With Metal, the \c object field of \a src is expected to contain an
5185 id<MTLRasterizationRateMap>. Note that Qt does not perform anything else
5186 apart from passing the MTLRasterizationRateMap on to the
5187 MTLRenderPassDescriptor. If any special scaling is required, it is up to the
5188 application (or the XR compositor) to perform that.
5189 */
5190bool QRhiShadingRateMap::createFrom(NativeShadingRateMap src)
5191{
5192 Q_UNUSED(src);
5193 return false;
5194}
5195
5196/*!
5197 Sets up the shading rate map to use the texture \a src as the
5198 image containing the per-tile shading rates.
5199
5200 \return \c true when successful, \c false when not supported.
5201
5202 The QRhiShadingRateMap does not take ownership of \a src.
5203
5204 \note This is functional only when the
5205 QRhi::VariableRateShadingMapWithTexture feature is reported as supported. In
5206 practice may be supported on Vulkan and Direct 3D 12 when using modern
5207 graphics cards. It will never be supported on OpenGL or Metal, for example.
5208
5209 \note \a src must have a format of QRhiTexture::R8UI.
5210
5211 \note \a src must have a width of \c{ceil(render_target_pixel_width /
5212 (float)tile_width)} and a height of \c{ceil(render_target_pixel_height /
5213 (float)tile_height)}. It is up to the application to ensure the size of the
5214 texture is as expected, using the above formula, at all times. The tile size
5215 can be queried via \l QRhi::resourceLimit() and
5216 QRhi::ShadingRateImageTileSize.
5217
5218 Each byte (texel) in the texture corresponds to the shading rate value for
5219 one tile. 0 indicates 1x1, while a value of 10 indicates 4x4. See
5220 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shading_rate}{D3D12_SHADING_RATE}
5221 for other possible values.
5222 */
5223bool QRhiShadingRateMap::createFrom(QRhiTexture *src)
5224{
5225 Q_UNUSED(src);
5226 return false;
5227}
5228
5229/*!
5230 \class QRhiRenderPassDescriptor
5231 \inmodule QtGuiPrivate
5232 \inheaderfile rhi/qrhi.h
5233 \since 6.6
5234 \brief Render pass resource.
5235
5236 A render pass, if such a concept exists in the underlying graphics API, is
5237 a collection of attachments (color, depth, stencil) and describes how those
5238 attachments are used.
5239
5240 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5241 for details.
5242 */
5243
5244/*!
5245 \internal
5246 */
5247QRhiRenderPassDescriptor::QRhiRenderPassDescriptor(QRhiImplementation *rhi)
5248 : QRhiResource(rhi)
5249{
5250}
5251
5252/*!
5253 \return the resource type.
5254 */
5255QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
5256{
5257 return RenderPassDescriptor;
5258}
5259
5260/*!
5261 \fn virtual bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const = 0
5262
5263 \return true if the \a other QRhiRenderPassDescriptor is compatible with
5264 this one, meaning \c this and \a other can be used interchangeably in
5265 QRhiGraphicsPipeline::setRenderPassDescriptor().
5266
5267 The concept of the compatibility of renderpass descriptors is similar to
5268 the \l{QRhiShaderResourceBindings::isLayoutCompatible}{layout
5269 compatibility} of QRhiShaderResourceBindings instances. They allow better
5270 reuse of QRhiGraphicsPipeline instances: for example, a
5271 QRhiGraphicsPipeline instance cache is expected to use these functions to
5272 look for a matching pipeline, instead of just comparing pointers, thus
5273 allowing a different QRhiRenderPassDescriptor and
5274 QRhiShaderResourceBindings to be used in combination with the pipeline, as
5275 long as they are compatible.
5276
5277 The exact details of compatibility depend on the underlying graphics API.
5278 Two renderpass descriptors
5279 \l{QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()}{created}
5280 from the same QRhiTextureRenderTarget are always compatible.
5281
5282 Similarly to QRhiShaderResourceBindings, compatibility can also be tested
5283 without having two existing objects available. Extracting the opaque blob by
5284 calling serializedFormat() allows testing for compatibility by comparing the
5285 returned vector to another QRhiRenderPassDescriptor's
5286 serializedFormat(). This has benefits in certain situations, because it
5287 allows testing the compatibility of a QRhiRenderPassDescriptor with a
5288 QRhiGraphicsPipeline even when the QRhiRenderPassDescriptor the pipeline was
5289 originally built with is no longer available (but the data returned from its
5290 serializedFormat() still is).
5291
5292 \sa newCompatibleRenderPassDescriptor(), serializedFormat()
5293 */
5294
5295/*!
5296 \fn virtual QRhiRenderPassDescriptor *QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor() const = 0
5297
5298 \return a new QRhiRenderPassDescriptor that is
5299 \l{isCompatible()}{compatible} with this one.
5300
5301 This function allows cloning a QRhiRenderPassDescriptor. The returned
5302 object is ready to be used, and the ownership is transferred to the caller.
5303 Cloning a QRhiRenderPassDescriptor object can become useful in situations
5304 where the object is stored in data structures related to graphics pipelines
5305 (in order to allow creating new pipelines which in turn requires a
5306 renderpass descriptor object), and the lifetime of the renderpass
5307 descriptor created from a render target may be shorter than the pipelines.
5308 (for example, because the engine manages and destroys renderpasses together
5309 with the textures and render targets it was created from) In such a
5310 situation, it can be beneficial to store a cloned version in the data
5311 structures, and thus transferring ownership as well.
5312
5313 \sa isCompatible()
5314 */
5315
5316/*!
5317 \fn virtual QVector<quint32> QRhiRenderPassDescriptor::serializedFormat() const = 0
5318
5319 \return a vector of integers containing an opaque blob describing the data
5320 relevant for \l{isCompatible()}{compatibility}.
5321
5322 Given two QRhiRenderPassDescriptor objects \c rp1 and \c rp2, if the data
5323 returned from this function is identical, then \c{rp1->isCompatible(rp2)},
5324 and vice versa hold true as well.
5325
5326 \note The returned data is meant to be used for storing in memory and
5327 comparisons during the lifetime of the QRhi the object belongs to. It is not
5328 meant for storing on disk, reusing between processes, or using with multiple
5329 QRhi instances with potentially different backends.
5330
5331 \note Calling this function is expected to be a cheap operation since the
5332 backends are not supposed to calculate the data in this function, but rather
5333 return an already calculated series of data.
5334
5335 When creating reusable components as part of a library, where graphics
5336 pipelines are created and maintained while targeting a QRhiRenderTarget (be
5337 it a swapchain or a texture) managed by the client of the library, the
5338 components must be able to deal with a changing QRhiRenderPassDescriptor.
5339 For example, because the render target changes and so invalidates the
5340 previously QRhiRenderPassDescriptor (with regards to the new render target
5341 at least) due to having a potentially different color format and attachments
5342 now. Or because \l{QRhiShadingRateMap}{variable rate shading} is taken into
5343 use dynamically. A simple pattern that helps dealing with this is performing
5344 the following check on every frame, to recognize the case when the pipeline
5345 needs to be associated with a new QRhiRenderPassDescriptor, because
5346 something is different about the render target now, compared to earlier
5347 frames:
5348
5349 \code
5350 QRhiRenderPassDescriptor *rp = m_renderTarget->renderPassDescriptor();
5351 if (m_pipeline && rp->serializedFormat() != m_renderPassFormat) {
5352 m_pipeline->setRenderPassDescriptor(rp);
5353 m_renderPassFormat = rp->serializedFormat();
5354 m_pipeline->create();
5355 }
5356 // remember to store m_renderPassFormat also when creating m_pipeline the first time
5357 \endcode
5358
5359 \sa isCompatible()
5360 */
5361
5362/*!
5363 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
5364 QRhiVulkanRenderPassNativeHandles. The returned value is \nullptr when exposing
5365 the underlying native resources is not supported by the backend.
5366
5367 \sa QRhiVulkanRenderPassNativeHandles
5368 */
5369const QRhiNativeHandles *QRhiRenderPassDescriptor::nativeHandles()
5370{
5371 return nullptr;
5372}
5373
5374/*!
5375 \class QRhiRenderTarget
5376 \inmodule QtGuiPrivate
5377 \inheaderfile rhi/qrhi.h
5378 \since 6.6
5379 \brief Represents an onscreen (swapchain) or offscreen (texture) render target.
5380
5381 Applications do not create an instance of this class directly. Rather, it
5382 is the subclass QRhiTextureRenderTarget that is instantiable by clients of
5383 the API via \l{QRhi::newTextureRenderTarget()}{newTextureRenderTarget()}.
5384 The other subclass is QRhiSwapChainRenderTarget, which is the type
5385 QRhiSwapChain returns when calling
5386 \l{QRhiSwapChain::currentFrameRenderTarget()}{currentFrameRenderTarget()}.
5387
5388 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5389 for details.
5390
5391 \sa QRhiSwapChainRenderTarget, QRhiTextureRenderTarget
5392 */
5393
5394/*!
5395 \internal
5396 */
5397QRhiRenderTarget::QRhiRenderTarget(QRhiImplementation *rhi)
5398 : QRhiResource(rhi)
5399{
5400}
5401
5402/*!
5403 \fn virtual QSize QRhiRenderTarget::pixelSize() const = 0
5404
5405 \return the size in pixels.
5406
5407 Valid only after create() has been called successfully. Until then the
5408 result is a default-constructed QSize.
5409
5410 With QRhiTextureRenderTarget the returned size is the size of the
5411 associated attachments at the time of create(), in practice the size of the
5412 first color attachment, or the depth/stencil buffer if there are no color
5413 attachments. If the associated textures or renderbuffers are resized and
5414 rebuilt afterwards, then pixelSize() performs an implicit call to create()
5415 in order to rebuild the underlying data structures. This implicit check is
5416 similar to what QRhiCommandBuffer::beginPass() does, and ensures that the
5417 returned size is always up-to-date.
5418 */
5419
5420/*!
5421 \fn virtual float QRhiRenderTarget::devicePixelRatio() const = 0
5422
5423 \return the device pixel ratio. For QRhiTextureRenderTarget this is always
5424 1. For targets retrieved from a QRhiSwapChain the value reflects the
5425 \l{QWindow::devicePixelRatio()}{device pixel ratio} of the targeted
5426 QWindow.
5427 */
5428
5429/*!
5430 \fn virtual int QRhiRenderTarget::sampleCount() const = 0
5431
5432 \return the sample count or 1 if multisample antialiasing is not relevant for
5433 this render target.
5434 */
5435
5436/*!
5437 \fn QRhiRenderPassDescriptor *QRhiRenderTarget::renderPassDescriptor() const
5438
5439 \return the associated QRhiRenderPassDescriptor.
5440 */
5441
5442/*!
5443 \fn void QRhiRenderTarget::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
5444
5445 Sets the QRhiRenderPassDescriptor \a desc for use with this render target.
5446 */
5447
5448/*!
5449 \internal
5450 */
5451QRhiSwapChainRenderTarget::QRhiSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain_)
5452 : QRhiRenderTarget(rhi),
5453 m_swapchain(swapchain_)
5454{
5455}
5456
5457/*!
5458 \class QRhiSwapChainRenderTarget
5459 \inmodule QtGuiPrivate
5460 \inheaderfile rhi/qrhi.h
5461 \since 6.6
5462 \brief Swapchain render target resource.
5463
5464 When targeting the color buffers of a swapchain, active render target is a
5465 QRhiSwapChainRenderTarget. This is what
5466 QRhiSwapChain::currentFrameRenderTarget() returns.
5467
5468 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5469 for details.
5470
5471 \sa QRhiSwapChain
5472 */
5473
5474/*!
5475 \return the resource type.
5476 */
5477QRhiResource::Type QRhiSwapChainRenderTarget::resourceType() const
5478{
5479 return SwapChainRenderTarget;
5480}
5481
5482/*!
5483 \fn QRhiSwapChain *QRhiSwapChainRenderTarget::swapChain() const
5484
5485 \return the swapchain object.
5486 */
5487
5488/*!
5489 \class QRhiTextureRenderTarget
5490 \inmodule QtGuiPrivate
5491 \inheaderfile rhi/qrhi.h
5492 \since 6.6
5493 \brief Texture render target resource.
5494
5495 A texture render target allows rendering into one or more textures,
5496 optionally with a depth texture or depth/stencil renderbuffer.
5497
5498 For multisample rendering the common approach is to use a renderbuffer as
5499 the color attachment and set the non-multisample destination texture as the
5500 \c{resolve texture}. For more information, read the detailed description of
5501 the \l QRhiColorAttachment class.
5502
5503 \note Textures used in combination with QRhiTextureRenderTarget must be
5504 created with the QRhiTexture::RenderTarget flag.
5505
5506 The simplest example of creating a render target with a texture as its
5507 single color attachment:
5508
5509 \code
5510 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
5511 texture->create();
5512 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture });
5513 rp = rt->newCompatibleRenderPassDescriptor();
5514 rt->setRenderPassDescriptor(rp);
5515 rt->create();
5516 // rt can now be used with beginPass()
5517 \endcode
5518
5519 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5520 for details.
5521 */
5522
5523/*!
5524 \enum QRhiTextureRenderTarget::Flag
5525
5526 Flag values describing the load/store behavior for the render target. The
5527 load/store behavior may be baked into native resources under the hood,
5528 depending on the backend, and therefore it needs to be known upfront and
5529 cannot be changed without rebuilding (and so releasing and creating new
5530 native resources).
5531
5532 \value PreserveColorContents Indicates that the contents of the color
5533 attachments is to be loaded when starting a render pass, instead of
5534 clearing. This is potentially more expensive, especially on mobile (tiled)
5535 GPUs, but allows preserving the existing contents between passes. When doing
5536 multisample rendering with a resolve texture set, setting this flag also
5537 requests the multisample color data to be stored (written out) to the
5538 multisample texture or render buffer. (for non-multisample rendering the
5539 color data is always stored, but for MSAA storing the multisample data
5540 decreases efficiency for certain GPU architectures, hence defaulting to not
5541 writing it out) Note however that this is non-portable: in some cases there
5542 is no intermediate multisample texture on the graphics API level, e.g. when
5543 using OpenGL ES's \c{GL_EXT_multisampled_render_to_texture} as it is all
5544 implicit, handled by the OpenGL ES implementation. In that case,
5545 PreserveColorContents will likely have no effect. Therefore, avoid relying
5546 on this flag when using multisample rendering and the color attachment is
5547 using a multisample QRhiTexture (not QRhiRenderBuffer).
5548
5549 \value PreserveDepthStencilContents Indicates that the contents of the
5550 depth texture is to be loaded when starting a render pass, instead
5551 clearing. Only applicable when a texture is used as the depth buffer
5552 (QRhiTextureRenderTargetDescription::depthTexture() is set) because
5553 depth/stencil renderbuffers may not have any physical backing and data may
5554 not be written out in the first place.
5555
5556 \value DoNotStoreDepthStencilContents Indicates that the contents of the
5557 depth texture does not need to be written out. Relevant only when a
5558 QRhiTexture, not QRhiRenderBuffer, is used as the depth-stencil buffer,
5559 because for QRhiRenderBuffer this is implicit. When a depthResolveTexture is
5560 set, the flag is not relevant, because the behavior is then as if the flag
5561 was set. This enum value is introduced in Qt 6.8.
5562 */
5563
5564/*!
5565 \internal
5566 */
5567QRhiTextureRenderTarget::QRhiTextureRenderTarget(QRhiImplementation *rhi,
5568 const QRhiTextureRenderTargetDescription &desc_,
5569 Flags flags_)
5570 : QRhiRenderTarget(rhi),
5571 m_desc(desc_),
5572 m_flags(flags_)
5573{
5574}
5575
5576/*!
5577 \return the resource type.
5578 */
5579QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
5580{
5581 return TextureRenderTarget;
5582}
5583
5584/*!
5585 \fn virtual QRhiRenderPassDescriptor *QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() = 0
5586
5587 \return a new QRhiRenderPassDescriptor that is compatible with this render
5588 target.
5589
5590 The returned value is used in two ways: it can be passed to
5591 setRenderPassDescriptor() and
5592 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
5593 describes the attachments (color, depth/stencil) and the load/store
5594 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
5595 be used in combination with a render target that has a
5596 \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
5597 QRhiRenderPassDescriptor set.
5598
5599 Two QRhiTextureRenderTarget instances can share the same render pass
5600 descriptor as long as they have the same number and type of attachments.
5601 The associated QRhiTexture or QRhiRenderBuffer instances are not part of
5602 the render pass descriptor so those can differ in the two
5603 QRhiTextureRenderTarget instances.
5604
5605 \note resources, such as QRhiTexture instances, referenced in description()
5606 must already have create() called on them.
5607
5608 \sa create()
5609 */
5610
5611/*!
5612 \fn virtual bool QRhiTextureRenderTarget::create() = 0
5613
5614 Creates the corresponding native graphics resources. If there are already
5615 resources present due to an earlier create() with no corresponding
5616 destroy(), then destroy() is called implicitly first.
5617
5618 \note renderPassDescriptor() must be set before calling create(). To obtain
5619 a QRhiRenderPassDescriptor compatible with the render target, call
5620 newCompatibleRenderPassDescriptor() before create() but after setting all
5621 other parameters, such as description() and flags(). To save resources,
5622 reuse the same QRhiRenderPassDescriptor with multiple
5623 QRhiTextureRenderTarget instances, whenever possible. Sharing the same
5624 render pass descriptor is only possible when the render targets have the
5625 same number and type of attachments (the actual textures can differ) and
5626 the same flags.
5627
5628 \note resources, such as QRhiTexture instances, referenced in description()
5629 must already have create() called on them.
5630
5631 \return \c true when successful, \c false when a graphics operation failed.
5632 Regardless of the return value, calling destroy() is always safe.
5633 */
5634
5635/*!
5636 \fn QRhiTextureRenderTargetDescription QRhiTextureRenderTarget::description() const
5637 \return the render target description.
5638 */
5639
5640/*!
5641 \fn void QRhiTextureRenderTarget::setDescription(const QRhiTextureRenderTargetDescription &desc)
5642 Sets the render target description \a desc.
5643 */
5644
5645/*!
5646 \fn QRhiTextureRenderTarget::Flags QRhiTextureRenderTarget::flags() const
5647 \return the currently set flags.
5648 */
5649
5650/*!
5651 \fn void QRhiTextureRenderTarget::setFlags(Flags f)
5652 Sets the flags to \a f.
5653 */
5654
5655/*!
5656 \class QRhiShaderResourceBindings
5657 \inmodule QtGuiPrivate
5658 \inheaderfile rhi/qrhi.h
5659 \since 6.6
5660 \brief Encapsulates resources for making buffer, texture, sampler resources visible to shaders.
5661
5662 A QRhiShaderResourceBindings is a collection of QRhiShaderResourceBinding
5663 objects, each of which describe a single binding.
5664
5665 Take a fragment shader with the following interface:
5666
5667 \badcode
5668 layout(std140, binding = 0) uniform buf {
5669 mat4 mvp;
5670 int flip;
5671 } ubuf;
5672
5673 layout(binding = 1) uniform sampler2D tex;
5674 \endcode
5675
5676 To make resources visible to the shader, the following
5677 QRhiShaderResourceBindings could be created and then passed to
5678 QRhiGraphicsPipeline::setShaderResourceBindings():
5679
5680 \code
5681 QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings();
5682 srb->setBindings({
5683 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf),
5684 QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler)
5685 });
5686 srb->create();
5687 // ...
5688 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
5689 // ...
5690 ps->setShaderResourceBindings(srb);
5691 ps->create();
5692 // ...
5693 cb->setGraphicsPipeline(ps);
5694 cb->setShaderResources(); // binds srb
5695 \endcode
5696
5697 This assumes that \c ubuf is a QRhiBuffer, \c texture is a QRhiTexture,
5698 while \a sampler is a QRhiSampler. The example also assumes that the
5699 uniform block is present in the vertex shader as well so the same buffer is
5700 made visible to the vertex stage too.
5701
5702 \section3 Advanced usage
5703
5704 Building on the above example, let's assume that a pass now needs to use
5705 the exact same pipeline and shaders with a different texture. Creating a
5706 whole separate QRhiGraphicsPipeline just for this would be an overkill.
5707 This is why QRhiCommandBuffer::setShaderResources() allows specifying a \a
5708 srb argument. As long as the layouts (so the number of bindings and the
5709 binding points) match between two QRhiShaderResourceBindings, they can both
5710 be used with the same pipeline, assuming the pipeline was created with one of
5711 them in the first place. See isLayoutCompatible() for more details.
5712
5713 \code
5714 QRhiShaderResourceBindings *srb2 = rhi->newShaderResourceBindings();
5715 // ...
5716 cb->setGraphicsPipeline(ps);
5717 cb->setShaderResources(srb2); // binds srb2
5718 \endcode
5719
5720 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5721 for details.
5722 */
5723
5724/*!
5725 \typedef QRhiShaderResourceBindingSet
5726 \relates QRhi
5727 \since 6.7
5728
5729 Synonym for QRhiShaderResourceBindings.
5730*/
5731
5732/*!
5733 \internal
5734 */
5735QRhiShaderResourceBindings::QRhiShaderResourceBindings(QRhiImplementation *rhi)
5736 : QRhiResource(rhi)
5737{
5738 m_layoutDesc.reserve(BINDING_PREALLOC * QRhiShaderResourceBinding::LAYOUT_DESC_ENTRIES_PER_BINDING);
5739}
5740
5741/*!
5742 \return the resource type.
5743 */
5744QRhiResource::Type QRhiShaderResourceBindings::resourceType() const
5745{
5746 return ShaderResourceBindings;
5747}
5748
5749/*!
5750 \return \c true if the layout is compatible with \a other. The layout does
5751 not include the actual resource (such as, buffer or texture) and related
5752 parameters (such as, offset or size). It does include the binding point,
5753 pipeline stage, and resource type, however. The number and order of the
5754 bindings must also match in order to be compatible.
5755
5756 When there is a QRhiGraphicsPipeline created with this
5757 QRhiShaderResourceBindings, and the function returns \c true, \a other can
5758 then safely be passed to QRhiCommandBuffer::setShaderResources(), and so
5759 be used with the pipeline in place of this QRhiShaderResourceBindings.
5760
5761 \note This function must only be called after a successful create(), because
5762 it relies on data generated during the baking of the underlying data
5763 structures. This way the function can implement a comparison approach that
5764 is more efficient than iterating through two binding lists and calling
5765 QRhiShaderResourceBinding::isLayoutCompatible() on each pair. This becomes
5766 relevant especially when this function is called at a high frequency.
5767
5768 \sa serializedLayoutDescription()
5769 */
5770bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBindings *other) const
5771{
5772 if (other == this)
5773 return true;
5774
5775 if (!other)
5776 return false;
5777
5778 // This can become a hot code path. Therefore we do not iterate and call
5779 // isLayoutCompatible() on m_bindings, but rather check a pre-calculated
5780 // hash code and then, if the hash matched, do a uint array comparison
5781 // (that's still more cache friendly).
5782
5783 return m_layoutDescHash == other->m_layoutDescHash
5784 && m_layoutDesc == other->m_layoutDesc;
5785}
5786
5787/*!
5788 \fn QVector<quint32> QRhiShaderResourceBindings::serializedLayoutDescription() const
5789
5790 \return a vector of integers containing an opaque blob describing the layout
5791 of the binding list, i.e. the data relevant for
5792 \l{isLayoutCompatible()}{layout compatibility tests}.
5793
5794 Given two objects \c srb1 and \c srb2, if the data returned from this
5795 function is identical, then \c{srb1->isLayoutCompatible(srb2)}, and vice
5796 versa hold true as well.
5797
5798 \note The returned data is meant to be used for storing in memory and
5799 comparisons during the lifetime of the QRhi the object belongs to. It is not
5800 meant for storing on disk, reusing between processes, or using with multiple
5801 QRhi instances with potentially different backends.
5802
5803 \sa isLayoutCompatible()
5804 */
5805
5806void QRhiImplementation::updateLayoutDesc(QRhiShaderResourceBindings *srb)
5807{
5808 srb->m_layoutDescHash = 0;
5809 srb->m_layoutDesc.clear();
5810 auto layoutDescAppender = std::back_inserter(srb->m_layoutDesc);
5811 for (const QRhiShaderResourceBinding &b : std::as_const(srb->m_bindings)) {
5812 const QRhiShaderResourceBinding::Data *d = &b.d;
5813 srb->m_layoutDescHash ^= uint(d->binding) ^ uint(d->stage) ^ uint(d->type)
5814 ^ uint(d->arraySize());
5815 layoutDescAppender = d->serialize(layoutDescAppender);
5816 }
5817}
5818
5819/*!
5820 \fn virtual bool QRhiShaderResourceBindings::create() = 0
5821
5822 Creates the corresponding resource binding set. Depending on the underlying
5823 graphics API, this may involve creating native graphics resources, and
5824 therefore it should not be assumed that this is a cheap operation.
5825
5826 If create() has been called before with no corresponding destroy(), then
5827 destroy() is called implicitly first.
5828
5829 \return \c true when successful, \c false when failed.
5830 Regardless of the return value, calling destroy() is always safe.
5831 */
5832
5833/*!
5834 \fn void QRhiShaderResourceBindings::setBindings(std::initializer_list<QRhiShaderResourceBinding> list)
5835 Sets the \a list of bindings.
5836 */
5837
5838/*!
5839 \fn template<typename InputIterator> void QRhiShaderResourceBindings::setBindings(InputIterator first, InputIterator last)
5840 Sets the list of bindings from the iterators \a first and \a last.
5841 */
5842
5843/*!
5844 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cbeginBindings() const
5845 \return a const iterator pointing to the first item in the binding list.
5846 */
5847
5848/*!
5849 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cendBindings() const
5850 \return a const iterator pointing just after the last item in the binding list.
5851 */
5852
5853/*!
5854 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::bindingAt(qsizetype index) const
5855 \return the binding at the specified \a index.
5856 */
5857
5858/*!
5859 \fn qsizetype QRhiShaderResourceBindings::bindingCount() const
5860 \return the number of bindings.
5861 */
5862
5863/*!
5864 \class QRhiShaderResourceBinding
5865 \inmodule QtGuiPrivate
5866 \inheaderfile rhi/qrhi.h
5867 \since 6.6
5868 \brief Describes the shader resource for a single binding point.
5869
5870 A QRhiShaderResourceBinding cannot be constructed directly. Instead, use the
5871 static functions such as uniformBuffer() or sampledTexture() to get an
5872 instance.
5873
5874 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5875 for details.
5876 */
5877
5878/*!
5879 \enum QRhiShaderResourceBinding::Type
5880 Specifies type of the shader resource bound to a binding point
5881
5882 \value UniformBuffer Uniform buffer
5883
5884 \value SampledTexture Combined image sampler (a texture and sampler pair).
5885 Even when the shading language associated with the underlying 3D API has no
5886 support for this concept (e.g. D3D and HLSL), this is still supported
5887 because the shader translation layer takes care of the appropriate
5888 translation and remapping of binding points or shader registers.
5889
5890 \value Texture Texture (separate)
5891
5892 \value Sampler Sampler (separate)
5893
5894 \value ImageLoad Image load (with GLSL this maps to doing imageLoad() on a
5895 single level - and either one or all layers - of a texture exposed to the
5896 shader as an image object)
5897
5898 \value ImageStore Image store (with GLSL this maps to doing imageStore() or
5899 imageAtomic*() on a single level - and either one or all layers - of a
5900 texture exposed to the shader as an image object)
5901
5902 \value ImageLoadStore Image load and store
5903
5904 \value BufferLoad Storage buffer load (with GLSL this maps to reading from
5905 a shader storage buffer)
5906
5907 \value BufferStore Storage buffer store (with GLSL this maps to writing to
5908 a shader storage buffer)
5909
5910 \value BufferLoadStore Storage buffer load and store
5911 */
5912
5913/*!
5914 \enum QRhiShaderResourceBinding::StageFlag
5915 Flag values to indicate which stages the shader resource is visible in
5916
5917 \value VertexStage Vertex stage
5918 \value TessellationControlStage Tessellation control (hull shader) stage
5919 \value TessellationEvaluationStage Tessellation evaluation (domain shader) stage
5920 \value FragmentStage Fragment (pixel shader) stage
5921 \value ComputeStage Compute stage
5922 \value GeometryStage Geometry stage
5923 */
5924
5925/*!
5926 \return \c true if the layout is compatible with \a other. The layout does not
5927 include the actual resource (such as, buffer or texture) and related
5928 parameters (such as, offset or size).
5929
5930 For example, \c a and \c b below are not equal, but are compatible layout-wise:
5931
5932 \code
5933 auto a = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buffer);
5934 auto b = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, someOtherBuffer, 256);
5935 \endcode
5936 */
5937bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBinding &other) const
5938{
5939 // everything that goes into a VkDescriptorSetLayoutBinding must match
5940 return d.binding == other.d.binding
5941 && d.stage == other.d.stage
5942 && d.type == other.d.type
5943 && d.arraySize() == other.d.arraySize();
5944}
5945
5946/*!
5947 \return a shader resource binding for the given binding number, pipeline
5948 stages, and buffer specified by \a binding, \a stage, and \a buf.
5949
5950 \note When \a buf is not null, it must have been created with
5951 QRhiBuffer::UniformBuffer.
5952
5953 \note \a buf can be null. It is valid to create a
5954 QRhiShaderResourceBindings with unspecified resources, but such an object
5955 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
5956 suitable for creating pipelines. Such a pipeline must then always be used
5957 together with another, layout compatible QRhiShaderResourceBindings with
5958 resources present passed to QRhiCommandBuffer::setShaderResources().
5959
5960 \note If the size of \a buf exceeds the limit reported for
5961 QRhi::MaxUniformBufferRange, unexpected errors may occur.
5962 */
5963QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
5964 int binding, StageFlags stage, QRhiBuffer *buf)
5965{
5966 QRhiShaderResourceBinding b;
5967 b.d.binding = binding;
5968 b.d.stage = stage;
5969 b.d.type = UniformBuffer;
5970 b.d.u.ubuf.buf = buf;
5971 b.d.u.ubuf.offset = 0;
5972 b.d.u.ubuf.maybeSize = 0; // entire buffer
5973 b.d.u.ubuf.hasDynamicOffset = false;
5974 return b;
5975}
5976
5977/*!
5978 \return a shader resource binding for the given binding number, pipeline
5979 stages, and buffer specified by \a binding, \a stage, and \a buf. This
5980 overload binds a region only, as specified by \a offset and \a size.
5981
5982 \note It is up to the user to ensure the offset is aligned to
5983 QRhi::ubufAlignment().
5984
5985 \note \a size must be greater than 0.
5986
5987 \note When \a buf is not null, it must have been created with
5988 QRhiBuffer::UniformBuffer.
5989
5990 \note \a buf can be null. It is valid to create a
5991 QRhiShaderResourceBindings with unspecified resources, but such an object
5992 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
5993 suitable for creating pipelines. Such a pipeline must then always be used
5994 together with another, layout compatible QRhiShaderResourceBindings with
5995 resources present passed to QRhiCommandBuffer::setShaderResources().
5996
5997 \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
5998 unexpected errors may occur.
5999 */
6000QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
6001 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6002{
6003 Q_ASSERT(size > 0);
6004 QRhiShaderResourceBinding b;
6005 b.d.binding = binding;
6006 b.d.stage = stage;
6007 b.d.type = UniformBuffer;
6008 b.d.u.ubuf.buf = buf;
6009 b.d.u.ubuf.offset = offset;
6010 b.d.u.ubuf.maybeSize = size;
6011 b.d.u.ubuf.hasDynamicOffset = false;
6012 return b;
6013}
6014
6015/*!
6016 \return a shader resource binding for the given binding number, pipeline
6017 stages, and buffer specified by \a binding, \a stage, and \a buf. The
6018 uniform buffer is assumed to have dynamic offset. The dynamic offset can be
6019 specified in QRhiCommandBuffer::setShaderResources(), thus allowing using
6020 varying offset values without creating new bindings for the buffer. The
6021 size of the bound region is specified by \a size. Like with non-dynamic
6022 offsets, \c{offset + size} cannot exceed the size of \a buf.
6023
6024 \note When \a buf is not null, it must have been created with
6025 QRhiBuffer::UniformBuffer.
6026
6027 \note \a buf can be null. It is valid to create a
6028 QRhiShaderResourceBindings with unspecified resources, but such an object
6029 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6030 suitable for creating pipelines. Such a pipeline must then always be used
6031 together with another, layout compatible QRhiShaderResourceBindings with
6032 resources present passed to QRhiCommandBuffer::setShaderResources().
6033
6034 \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
6035 unexpected errors may occur.
6036 */
6037QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(
6038 int binding, StageFlags stage, QRhiBuffer *buf, quint32 size)
6039{
6040 Q_ASSERT(size > 0);
6041 QRhiShaderResourceBinding b;
6042 b.d.binding = binding;
6043 b.d.stage = stage;
6044 b.d.type = UniformBuffer;
6045 b.d.u.ubuf.buf = buf;
6046 b.d.u.ubuf.offset = 0;
6047 b.d.u.ubuf.maybeSize = size;
6048 b.d.u.ubuf.hasDynamicOffset = true;
6049 return b;
6050}
6051
6052/*!
6053 \return a shader resource binding for the given binding number, pipeline
6054 stages, texture, and sampler specified by \a binding, \a stage, \a tex,
6055 \a sampler.
6056
6057 \note This function is equivalent to calling sampledTextures() with a
6058 \c count of 1.
6059
6060 \note \a tex and \a sampler can be null. It is valid to create a
6061 QRhiShaderResourceBindings with unspecified resources, but such an object
6062 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6063 suitable for creating pipelines. Such a pipeline must then always be used
6064 together with another, layout compatible QRhiShaderResourceBindings with
6065 resources present passed to QRhiCommandBuffer::setShaderResources().
6066
6067 \note A shader may not be able to consume more than 16 textures/samplers,
6068 depending on the underlying graphics API. This hard limit must be kept in
6069 mind in renderer design. This does not apply to texture arrays which
6070 consume a single binding point (shader register) and can contain 256-2048
6071 textures, depending on the underlying graphics API. Arrays of textures (see
6072 sampledTextures()) are however no different in this regard than using the
6073 same number of individual textures.
6074
6075 \sa sampledTextures()
6076 */
6077QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
6078 int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
6079{
6080 QRhiShaderResourceBinding b;
6081 b.d.binding = binding;
6082 b.d.stage = stage;
6083 b.d.type = SampledTexture;
6084 b.d.u.stex.count = 1;
6085 b.d.u.stex.texSamplers[0] = { tex, sampler };
6086 return b;
6087}
6088
6089/*!
6090 \return a shader resource binding for the given binding number, pipeline
6091 stages, and the array of texture-sampler pairs specified by \a binding, \a
6092 stage, \a count, and \a texSamplers.
6093
6094 \note \a count must be at least 1, and not larger than 16.
6095
6096 \note When \a count is 1, this function is equivalent to sampledTexture().
6097
6098 This function is relevant when arrays of combined image samplers are
6099 involved. For example, in GLSL \c{layout(binding = 5) uniform sampler2D
6100 shadowMaps[8];} declares an array of combined image samplers. The
6101 application is then expected provide a QRhiShaderResourceBinding for
6102 binding point 5, set up by calling this function with \a count set to 8 and
6103 a valid texture and sampler for each element of the array.
6104
6105 \warning All elements of the array must be specified. With the above
6106 example, the only valid, portable approach is calling this function with a
6107 \a count of 8. Additionally, all QRhiTexture and QRhiSampler instances must
6108 be valid, meaning nullptr is not an accepted value. This is due to some of
6109 the underlying APIs, such as, Vulkan, that require a valid image and
6110 sampler object for each element in descriptor arrays. Applications are
6111 advised to provide "dummy" samplers and textures if some array elements are
6112 not relevant (due to not being accessed in the shader).
6113
6114 \note \a texSamplers can be null. It is valid to create a
6115 QRhiShaderResourceBindings with unspecified resources, but such an object
6116 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6117 suitable for creating pipelines. Such a pipeline must then always be used
6118 together with another, layout compatible QRhiShaderResourceBindings with
6119 resources present passed to QRhiCommandBuffer::setShaderResources().
6120
6121 \sa sampledTexture()
6122 */
6123QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTextures(
6124 int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers)
6125{
6126 Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
6127 QRhiShaderResourceBinding b;
6128 b.d.binding = binding;
6129 b.d.stage = stage;
6130 b.d.type = SampledTexture;
6131 b.d.u.stex.count = count;
6132 for (int i = 0; i < count; ++i) {
6133 if (texSamplers)
6134 b.d.u.stex.texSamplers[i] = texSamplers[i];
6135 else
6136 b.d.u.stex.texSamplers[i] = { nullptr, nullptr };
6137 }
6138 return b;
6139}
6140
6141/*!
6142 \return a shader resource binding for the given binding number, pipeline
6143 stages, and texture specified by \a binding, \a stage, \a tex.
6144
6145 \note This function is equivalent to calling textures() with a
6146 \c count of 1.
6147
6148 \note \a tex can be null. It is valid to create a
6149 QRhiShaderResourceBindings with unspecified resources, but such an object
6150 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6151 suitable for creating pipelines. Such a pipeline must then always be used
6152 together with another, layout compatible QRhiShaderResourceBindings with
6153 resources present passed to QRhiCommandBuffer::setShaderResources().
6154
6155 This creates a binding for a separate texture (image) object, whereas
6156 sampledTexture() is suitable for combined image samplers. In
6157 Vulkan-compatible GLSL code separate textures are declared as \c texture2D
6158 as opposed to \c sampler2D: \c{layout(binding = 1) uniform texture2D tex;}
6159
6160 \note A shader may not be able to consume more than 16 textures, depending
6161 on the underlying graphics API. This hard limit must be kept in mind in
6162 renderer design. This does not apply to texture arrays which consume a
6163 single binding point (shader register) and can contain 256-2048 textures,
6164 depending on the underlying graphics API. Arrays of textures (see
6165 sampledTextures()) are however no different in this regard than using the
6166 same number of individual textures.
6167
6168 \sa textures(), sampler()
6169 */
6170QRhiShaderResourceBinding QRhiShaderResourceBinding::texture(int binding, StageFlags stage, QRhiTexture *tex)
6171{
6172 QRhiShaderResourceBinding b;
6173 b.d.binding = binding;
6174 b.d.stage = stage;
6175 b.d.type = Texture;
6176 b.d.u.stex.count = 1;
6177 b.d.u.stex.texSamplers[0] = { tex, nullptr };
6178 return b;
6179}
6180
6181/*!
6182 \return a shader resource binding for the given binding number, pipeline
6183 stages, and the array of (separate) textures specified by \a binding, \a
6184 stage, \a count, and \a tex.
6185
6186 \note \a count must be at least 1, and not larger than 16.
6187
6188 \note When \a count is 1, this function is equivalent to texture().
6189
6190 \warning All elements of the array must be specified.
6191
6192 \note \a tex can be null. It is valid to create a
6193 QRhiShaderResourceBindings with unspecified resources, but such an object
6194 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6195 suitable for creating pipelines. Such a pipeline must then always be used
6196 together with another, layout compatible QRhiShaderResourceBindings with
6197 resources present passed to QRhiCommandBuffer::setShaderResources().
6198
6199 \sa texture(), sampler()
6200 */
6201QRhiShaderResourceBinding QRhiShaderResourceBinding::textures(int binding, StageFlags stage, int count, QRhiTexture **tex)
6202{
6203 Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
6204 QRhiShaderResourceBinding b;
6205 b.d.binding = binding;
6206 b.d.stage = stage;
6207 b.d.type = Texture;
6208 b.d.u.stex.count = count;
6209 for (int i = 0; i < count; ++i) {
6210 if (tex)
6211 b.d.u.stex.texSamplers[i] = { tex[i], nullptr };
6212 else
6213 b.d.u.stex.texSamplers[i] = { nullptr, nullptr };
6214 }
6215 return b;
6216}
6217
6218/*!
6219 \return a shader resource binding for the given binding number, pipeline
6220 stages, and sampler specified by \a binding, \a stage, \a sampler.
6221
6222 \note \a sampler can be null. It is valid to create a
6223 QRhiShaderResourceBindings with unspecified resources, but such an object
6224 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6225 suitable for creating pipelines. Such a pipeline must then always be used
6226 together with another, layout compatible QRhiShaderResourceBindings with
6227 resources present passed to QRhiCommandBuffer::setShaderResources().
6228
6229 Arrays of separate samplers are not supported.
6230
6231 This creates a binding for a separate sampler object, whereas
6232 sampledTexture() is suitable for combined image samplers. In
6233 Vulkan-compatible GLSL code separate samplers are declared as \c sampler
6234 as opposed to \c sampler2D: \c{layout(binding = 2) uniform sampler samp;}
6235
6236 With both a \c texture2D and \c sampler present, they can be used together
6237 to sample the texture: \c{fragColor = texture(sampler2D(tex, samp),
6238 texcoord);}.
6239
6240 \note A shader may not be able to consume more than 16 samplers, depending
6241 on the underlying graphics API. This hard limit must be kept in mind in
6242 renderer design.
6243
6244 \sa texture()
6245 */
6246QRhiShaderResourceBinding QRhiShaderResourceBinding::sampler(int binding, StageFlags stage, QRhiSampler *sampler)
6247{
6248 QRhiShaderResourceBinding b;
6249 b.d.binding = binding;
6250 b.d.stage = stage;
6251 b.d.type = Sampler;
6252 b.d.u.stex.count = 1;
6253 b.d.u.stex.texSamplers[0] = { nullptr, sampler };
6254 return b;
6255}
6256
6257/*!
6258 \return a shader resource binding for a read-only storage image with the
6259 given \a binding number and pipeline \a stage. The image load operations
6260 will have access to all layers of the specified \a level. (so if the texture
6261 is a cubemap, the shader must use imageCube instead of image2D)
6262
6263 \note When \a tex is not null, it must have been created with
6264 QRhiTexture::UsedWithLoadStore.
6265
6266 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6267 with unspecified resources, but such an object cannot be used with
6268 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6269 pipelines. Such a pipeline must then always be used together with another,
6270 layout compatible QRhiShaderResourceBindings with resources present passed
6271 to QRhiCommandBuffer::setShaderResources().
6272
6273 \note Image load/store is only available within the compute and fragment stages.
6274 */
6275QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoad(
6276 int binding, StageFlags stage, QRhiTexture *tex, int level)
6277{
6278 QRhiShaderResourceBinding b;
6279 b.d.binding = binding;
6280 b.d.stage = stage;
6281 b.d.type = ImageLoad;
6282 b.d.u.simage.tex = tex;
6283 b.d.u.simage.level = level;
6284 return b;
6285}
6286
6287/*!
6288 \return a shader resource binding for a write-only storage image with the
6289 given \a binding number and pipeline \a stage. The image store operations
6290 will have access to all layers of the specified \a level. (so if the texture
6291 is a cubemap, the shader must use imageCube instead of image2D)
6292
6293 \note When \a tex is not null, it must have been created with
6294 QRhiTexture::UsedWithLoadStore.
6295
6296 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6297 with unspecified resources, but such an object cannot be used with
6298 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6299 pipelines. Such a pipeline must then always be used together with another,
6300 layout compatible QRhiShaderResourceBindings with resources present passed
6301 to QRhiCommandBuffer::setShaderResources().
6302
6303 \note Image load/store is only available within the compute and fragment stages.
6304 */
6305QRhiShaderResourceBinding QRhiShaderResourceBinding::imageStore(
6306 int binding, StageFlags stage, QRhiTexture *tex, int level)
6307{
6308 QRhiShaderResourceBinding b;
6309 b.d.binding = binding;
6310 b.d.stage = stage;
6311 b.d.type = ImageStore;
6312 b.d.u.simage.tex = tex;
6313 b.d.u.simage.level = level;
6314 return b;
6315}
6316
6317/*!
6318 \return a shader resource binding for a read/write storage image with the
6319 given \a binding number and pipeline \a stage. The image load/store operations
6320 will have access to all layers of the specified \a level. (so if the texture
6321 is a cubemap, the shader must use imageCube instead of image2D)
6322
6323 \note When \a tex is not null, it must have been created with
6324 QRhiTexture::UsedWithLoadStore.
6325
6326 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6327 with unspecified resources, but such an object cannot be used with
6328 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6329 pipelines. Such a pipeline must then always be used together with another,
6330 layout compatible QRhiShaderResourceBindings with resources present passed
6331 to QRhiCommandBuffer::setShaderResources().
6332
6333 \note Image load/store is only available within the compute and fragment stages.
6334 */
6335QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoadStore(
6336 int binding, StageFlags stage, QRhiTexture *tex, int level)
6337{
6338 QRhiShaderResourceBinding b;
6339 b.d.binding = binding;
6340 b.d.stage = stage;
6341 b.d.type = ImageLoadStore;
6342 b.d.u.simage.tex = tex;
6343 b.d.u.simage.level = level;
6344 return b;
6345}
6346
6347/*!
6348 \return a shader resource binding for a read-only storage buffer with the
6349 given \a binding number and pipeline \a stage.
6350
6351 \note When \a buf is not null, must have been created with
6352 QRhiBuffer::StorageBuffer.
6353
6354 \note \a buf can be null. It is valid to create a
6355 QRhiShaderResourceBindings with unspecified resources, but such an object
6356 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6357 suitable for creating pipelines. Such a pipeline must then always be used
6358 together with another, layout compatible QRhiShaderResourceBindings with
6359 resources present passed to QRhiCommandBuffer::setShaderResources().
6360
6361 \note Buffer load/store is only guaranteed to be available within a compute
6362 pipeline. While some backends may support using these resources in a
6363 graphics pipeline as well, this is not universally supported, and even when
6364 it is, unexpected problems may arise when it comes to barriers and
6365 synchronization. Therefore, avoid using such resources with shaders other
6366 than compute.
6367 */
6368QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6369 int binding, StageFlags stage, QRhiBuffer *buf)
6370{
6371 QRhiShaderResourceBinding b;
6372 b.d.binding = binding;
6373 b.d.stage = stage;
6374 b.d.type = BufferLoad;
6375 b.d.u.sbuf.buf = buf;
6376 b.d.u.sbuf.offset = 0;
6377 b.d.u.sbuf.maybeSize = 0; // entire buffer
6378 return b;
6379}
6380
6381/*!
6382 \return a shader resource binding for a read-only storage buffer with the
6383 given \a binding number and pipeline \a stage. This overload binds a region
6384 only, as specified by \a offset and \a size.
6385
6386 \note When \a buf is not null, must have been created with
6387 QRhiBuffer::StorageBuffer.
6388
6389 \note \a buf can be null. It is valid to create a
6390 QRhiShaderResourceBindings with unspecified resources, but such an object
6391 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6392 suitable for creating pipelines. Such a pipeline must then always be used
6393 together with another, layout compatible QRhiShaderResourceBindings with
6394 resources present passed to QRhiCommandBuffer::setShaderResources().
6395
6396 \note Buffer load/store is only guaranteed to be available within a compute
6397 pipeline. While some backends may support using these resources in a
6398 graphics pipeline as well, this is not universally supported, and even when
6399 it is, unexpected problems may arise when it comes to barriers and
6400 synchronization. Therefore, avoid using such resources with shaders other
6401 than compute.
6402 */
6403QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6404 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6405{
6406 Q_ASSERT(size > 0);
6407 QRhiShaderResourceBinding b;
6408 b.d.binding = binding;
6409 b.d.stage = stage;
6410 b.d.type = BufferLoad;
6411 b.d.u.sbuf.buf = buf;
6412 b.d.u.sbuf.offset = offset;
6413 b.d.u.sbuf.maybeSize = size;
6414 return b;
6415}
6416
6417/*!
6418 \return a shader resource binding for a write-only storage buffer with the
6419 given \a binding number and pipeline \a stage.
6420
6421 \note When \a buf is not null, must have been created with
6422 QRhiBuffer::StorageBuffer.
6423
6424 \note \a buf can be null. It is valid to create a
6425 QRhiShaderResourceBindings with unspecified resources, but such an object
6426 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6427 suitable for creating pipelines. Such a pipeline must then always be used
6428 together with another, layout compatible QRhiShaderResourceBindings with
6429 resources present passed to QRhiCommandBuffer::setShaderResources().
6430
6431 \note Buffer load/store is only guaranteed to be available within a compute
6432 pipeline. While some backends may support using these resources in a
6433 graphics pipeline as well, this is not universally supported, and even when
6434 it is, unexpected problems may arise when it comes to barriers and
6435 synchronization. Therefore, avoid using such resources with shaders other
6436 than compute.
6437 */
6438QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6439 int binding, StageFlags stage, QRhiBuffer *buf)
6440{
6441 QRhiShaderResourceBinding b;
6442 b.d.binding = binding;
6443 b.d.stage = stage;
6444 b.d.type = BufferStore;
6445 b.d.u.sbuf.buf = buf;
6446 b.d.u.sbuf.offset = 0;
6447 b.d.u.sbuf.maybeSize = 0; // entire buffer
6448 return b;
6449}
6450
6451/*!
6452 \return a shader resource binding for a write-only storage buffer with the
6453 given \a binding number and pipeline \a stage. This overload binds a region
6454 only, as specified by \a offset and \a size.
6455
6456 \note When \a buf is not null, must have been created with
6457 QRhiBuffer::StorageBuffer.
6458
6459 \note \a buf can be null. It is valid to create a
6460 QRhiShaderResourceBindings with unspecified resources, but such an object
6461 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6462 suitable for creating pipelines. Such a pipeline must then always be used
6463 together with another, layout compatible QRhiShaderResourceBindings with
6464 resources present passed to QRhiCommandBuffer::setShaderResources().
6465
6466 \note Buffer load/store is only guaranteed to be available within a compute
6467 pipeline. While some backends may support using these resources in a
6468 graphics pipeline as well, this is not universally supported, and even when
6469 it is, unexpected problems may arise when it comes to barriers and
6470 synchronization. Therefore, avoid using such resources with shaders other
6471 than compute.
6472 */
6473QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6474 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6475{
6476 Q_ASSERT(size > 0);
6477 QRhiShaderResourceBinding b;
6478 b.d.binding = binding;
6479 b.d.stage = stage;
6480 b.d.type = BufferStore;
6481 b.d.u.sbuf.buf = buf;
6482 b.d.u.sbuf.offset = offset;
6483 b.d.u.sbuf.maybeSize = size;
6484 return b;
6485}
6486
6487/*!
6488 \return a shader resource binding for a read-write storage buffer with the
6489 given \a binding number and pipeline \a stage.
6490
6491 \note When \a buf is not null, must have been created with
6492 QRhiBuffer::StorageBuffer.
6493
6494 \note \a buf can be null. It is valid to create a
6495 QRhiShaderResourceBindings with unspecified resources, but such an object
6496 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6497 suitable for creating pipelines. Such a pipeline must then always be used
6498 together with another, layout compatible QRhiShaderResourceBindings with
6499 resources present passed to QRhiCommandBuffer::setShaderResources().
6500
6501 \note Buffer load/store is only guaranteed to be available within a compute
6502 pipeline. While some backends may support using these resources in a
6503 graphics pipeline as well, this is not universally supported, and even when
6504 it is, unexpected problems may arise when it comes to barriers and
6505 synchronization. Therefore, avoid using such resources with shaders other
6506 than compute.
6507 */
6508QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6509 int binding, StageFlags stage, QRhiBuffer *buf)
6510{
6511 QRhiShaderResourceBinding b;
6512 b.d.binding = binding;
6513 b.d.stage = stage;
6514 b.d.type = BufferLoadStore;
6515 b.d.u.sbuf.buf = buf;
6516 b.d.u.sbuf.offset = 0;
6517 b.d.u.sbuf.maybeSize = 0; // entire buffer
6518 return b;
6519}
6520
6521/*!
6522 \return a shader resource binding for a read-write storage buffer with the
6523 given \a binding number and pipeline \a stage. This overload binds a region
6524 only, as specified by \a offset and \a size.
6525
6526 \note When \a buf is not null, must have been created with
6527 QRhiBuffer::StorageBuffer.
6528
6529 \note \a buf can be null. It is valid to create a
6530 QRhiShaderResourceBindings with unspecified resources, but such an object
6531 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6532 suitable for creating pipelines. Such a pipeline must then always be used
6533 together with another, layout compatible QRhiShaderResourceBindings with
6534 resources present passed to QRhiCommandBuffer::setShaderResources().
6535
6536 \note Buffer load/store is only guaranteed to be available within a compute
6537 pipeline. While some backends may support using these resources in a
6538 graphics pipeline as well, this is not universally supported, and even when
6539 it is, unexpected problems may arise when it comes to barriers and
6540 synchronization. Therefore, avoid using such resources with shaders other
6541 than compute.
6542 */
6543QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6544 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6545{
6546 Q_ASSERT(size > 0);
6547 QRhiShaderResourceBinding b;
6548 b.d.binding = binding;
6549 b.d.stage = stage;
6550 b.d.type = BufferLoadStore;
6551 b.d.u.sbuf.buf = buf;
6552 b.d.u.sbuf.offset = offset;
6553 b.d.u.sbuf.maybeSize = size;
6554 return b;
6555}
6556
6557/*!
6558 \return \c true if the contents of the two QRhiShaderResourceBinding
6559 objects \a a and \a b are equal. This includes the resources (buffer,
6560 texture) and related parameters (offset, size) as well. To only compare
6561 layouts (binding point, pipeline stage, resource type), use
6562 \l{QRhiShaderResourceBinding::isLayoutCompatible()}{isLayoutCompatible()}
6563 instead.
6564
6565 \relates QRhiShaderResourceBinding
6566 */
6567bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6568{
6569 const QRhiShaderResourceBinding::Data *da = QRhiImplementation::shaderResourceBindingData(a);
6570 const QRhiShaderResourceBinding::Data *db = QRhiImplementation::shaderResourceBindingData(b);
6571
6572 if (da == db)
6573 return true;
6574
6575
6576 if (da->binding != db->binding
6577 || da->stage != db->stage
6578 || da->type != db->type)
6579 {
6580 return false;
6581 }
6582
6583 switch (da->type) {
6584 case QRhiShaderResourceBinding::UniformBuffer:
6585 if (da->u.ubuf.buf != db->u.ubuf.buf
6586 || da->u.ubuf.offset != db->u.ubuf.offset
6587 || da->u.ubuf.maybeSize != db->u.ubuf.maybeSize)
6588 {
6589 return false;
6590 }
6591 break;
6592 case QRhiShaderResourceBinding::SampledTexture:
6593 if (da->u.stex.count != db->u.stex.count)
6594 return false;
6595 for (int i = 0; i < da->u.stex.count; ++i) {
6596 if (da->u.stex.texSamplers[i].tex != db->u.stex.texSamplers[i].tex
6597 || da->u.stex.texSamplers[i].sampler != db->u.stex.texSamplers[i].sampler)
6598 {
6599 return false;
6600 }
6601 }
6602 break;
6603 case QRhiShaderResourceBinding::Texture:
6604 if (da->u.stex.count != db->u.stex.count)
6605 return false;
6606 for (int i = 0; i < da->u.stex.count; ++i) {
6607 if (da->u.stex.texSamplers[i].tex != db->u.stex.texSamplers[i].tex)
6608 return false;
6609 }
6610 break;
6611 case QRhiShaderResourceBinding::Sampler:
6612 if (da->u.stex.texSamplers[0].sampler != db->u.stex.texSamplers[0].sampler)
6613 return false;
6614 break;
6615 case QRhiShaderResourceBinding::ImageLoad:
6616 case QRhiShaderResourceBinding::ImageStore:
6617 case QRhiShaderResourceBinding::ImageLoadStore:
6618 if (da->u.simage.tex != db->u.simage.tex
6619 || da->u.simage.level != db->u.simage.level)
6620 {
6621 return false;
6622 }
6623 break;
6624 case QRhiShaderResourceBinding::BufferLoad:
6625 case QRhiShaderResourceBinding::BufferStore:
6626 case QRhiShaderResourceBinding::BufferLoadStore:
6627 if (da->u.sbuf.buf != db->u.sbuf.buf
6628 || da->u.sbuf.offset != db->u.sbuf.offset
6629 || da->u.sbuf.maybeSize != db->u.sbuf.maybeSize)
6630 {
6631 return false;
6632 }
6633 break;
6634 default:
6635 Q_UNREACHABLE_RETURN(false);
6636 }
6637
6638 return true;
6639}
6640
6641/*!
6642 \return \c false if all the bindings in the two QRhiShaderResourceBinding
6643 objects \a a and \a b are equal; otherwise returns \c true.
6644
6645 \relates QRhiShaderResourceBinding
6646 */
6647bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6648{
6649 return !(a == b);
6650}
6651
6652/*!
6653 \fn size_t qHash(const QRhiShaderResourceBinding &key, size_t seed)
6654 \qhashold{QRhiShaderResourceBinding}
6655 */
6656size_t qHash(const QRhiShaderResourceBinding &b, size_t seed) noexcept
6657{
6658 const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6659 QtPrivate::QHashCombineWithSeed hash(seed);
6660 seed = hash(seed, d->binding);
6661 seed = hash(seed, d->stage);
6662 seed = hash(seed, d->type);
6663 switch (d->type) {
6664 case QRhiShaderResourceBinding::UniformBuffer:
6665 seed = hash(seed, reinterpret_cast<quintptr>(d->u.ubuf.buf));
6666 break;
6667 case QRhiShaderResourceBinding::SampledTexture:
6668 seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].tex));
6669 seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].sampler));
6670 break;
6671 case QRhiShaderResourceBinding::Texture:
6672 seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].tex));
6673 break;
6674 case QRhiShaderResourceBinding::Sampler:
6675 seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].sampler));
6676 break;
6677 case QRhiShaderResourceBinding::ImageLoad:
6678 case QRhiShaderResourceBinding::ImageStore:
6679 case QRhiShaderResourceBinding::ImageLoadStore:
6680 seed = hash(seed, reinterpret_cast<quintptr>(d->u.simage.tex));
6681 break;
6682 case QRhiShaderResourceBinding::BufferLoad:
6683 case QRhiShaderResourceBinding::BufferStore:
6684 case QRhiShaderResourceBinding::BufferLoadStore:
6685 seed = hash(seed, reinterpret_cast<quintptr>(d->u.sbuf.buf));
6686 break;
6687 }
6688 return seed;
6689}
6690
6691#ifndef QT_NO_DEBUG_STREAM
6692QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
6693{
6694 QDebugStateSaver saver(dbg);
6695 const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6696 dbg.nospace() << "QRhiShaderResourceBinding("
6697 << "binding=" << d->binding
6698 << " stage=" << d->stage
6699 << " type=" << d->type;
6700 switch (d->type) {
6701 case QRhiShaderResourceBinding::UniformBuffer:
6702 dbg.nospace() << " UniformBuffer("
6703 << "buffer=" << d->u.ubuf.buf
6704 << " offset=" << d->u.ubuf.offset
6705 << " maybeSize=" << d->u.ubuf.maybeSize
6706 << ')';
6707 break;
6708 case QRhiShaderResourceBinding::SampledTexture:
6709 dbg.nospace() << " SampledTextures("
6710 << "count=" << d->u.stex.count;
6711 for (int i = 0; i < d->u.stex.count; ++i) {
6712 dbg.nospace() << " texture=" << d->u.stex.texSamplers[i].tex
6713 << " sampler=" << d->u.stex.texSamplers[i].sampler;
6714 }
6715 dbg.nospace() << ')';
6716 break;
6717 case QRhiShaderResourceBinding::Texture:
6718 dbg.nospace() << " Textures("
6719 << "count=" << d->u.stex.count;
6720 for (int i = 0; i < d->u.stex.count; ++i)
6721 dbg.nospace() << " texture=" << d->u.stex.texSamplers[i].tex;
6722 dbg.nospace() << ')';
6723 break;
6724 case QRhiShaderResourceBinding::Sampler:
6725 dbg.nospace() << " Sampler("
6726 << " sampler=" << d->u.stex.texSamplers[0].sampler
6727 << ')';
6728 break;
6729 case QRhiShaderResourceBinding::ImageLoad:
6730 dbg.nospace() << " ImageLoad("
6731 << "texture=" << d->u.simage.tex
6732 << " level=" << d->u.simage.level
6733 << ')';
6734 break;
6735 case QRhiShaderResourceBinding::ImageStore:
6736 dbg.nospace() << " ImageStore("
6737 << "texture=" << d->u.simage.tex
6738 << " level=" << d->u.simage.level
6739 << ')';
6740 break;
6741 case QRhiShaderResourceBinding::ImageLoadStore:
6742 dbg.nospace() << " ImageLoadStore("
6743 << "texture=" << d->u.simage.tex
6744 << " level=" << d->u.simage.level
6745 << ')';
6746 break;
6747 case QRhiShaderResourceBinding::BufferLoad:
6748 dbg.nospace() << " BufferLoad("
6749 << "buffer=" << d->u.sbuf.buf
6750 << " offset=" << d->u.sbuf.offset
6751 << " maybeSize=" << d->u.sbuf.maybeSize
6752 << ')';
6753 break;
6754 case QRhiShaderResourceBinding::BufferStore:
6755 dbg.nospace() << " BufferStore("
6756 << "buffer=" << d->u.sbuf.buf
6757 << " offset=" << d->u.sbuf.offset
6758 << " maybeSize=" << d->u.sbuf.maybeSize
6759 << ')';
6760 break;
6761 case QRhiShaderResourceBinding::BufferLoadStore:
6762 dbg.nospace() << " BufferLoadStore("
6763 << "buffer=" << d->u.sbuf.buf
6764 << " offset=" << d->u.sbuf.offset
6765 << " maybeSize=" << d->u.sbuf.maybeSize
6766 << ')';
6767 break;
6768 default:
6769 dbg.nospace() << " UNKNOWN()";
6770 break;
6771 }
6772 dbg.nospace() << ')';
6773 return dbg;
6774}
6775#endif
6776
6777#ifndef QT_NO_DEBUG_STREAM
6778QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
6779{
6780 QDebugStateSaver saver(dbg);
6781 dbg.nospace() << "QRhiShaderResourceBindings("
6782 << srb.m_bindings
6783 << ')';
6784 return dbg;
6785}
6786#endif
6787
6788/*!
6789 \class QRhiGraphicsPipeline
6790 \inmodule QtGuiPrivate
6791 \inheaderfile rhi/qrhi.h
6792 \since 6.6
6793 \brief Graphics pipeline state resource.
6794
6795 Represents a graphics pipeline. What exactly this map to in the underlying
6796 native graphics API, varies. Where there is a concept of pipeline objects,
6797 for example with Vulkan, the QRhi backend will create such an object upon
6798 calling create(). Elsewhere, for example with OpenGL, the
6799 QRhiGraphicsPipeline may merely collect the various state, and create()'s
6800 main task is to set up the corresponding shader program, but deferring
6801 looking at any of the requested state to a later point.
6802
6803 As with all QRhiResource subclasses, the two-phased initialization pattern
6804 applies: setting any values via the setters, for example setDepthTest(), is
6805 only effective after calling create(). Avoid changing any values once the
6806 QRhiGraphicsPipeline has been initialized via create(). To change some
6807 state, set the new value and call create() again. However, that will
6808 effectively release all underlying native resources and create new ones. As
6809 a result, it may be a heavy, expensive operation. Rather, prefer creating
6810 multiple pipelines with the different states, and
6811 \l{QRhiCommandBuffer::setGraphicsPipeline()}{switch between them} when
6812 recording the render pass.
6813
6814 \note Setting the shader stages is mandatory. There must be at least one
6815 stage, and there must be a vertex stage.
6816
6817 \note Setting the shader resource bindings is mandatory. The referenced
6818 QRhiShaderResourceBindings must already have create() called on it by the
6819 time create() is called. Associating with a QRhiShaderResourceBindings that
6820 has no bindings is also valid, as long as no shader in any stage expects any
6821 resources. Using a QRhiShaderResourceBindings object that does not specify
6822 any actual resources (i.e., the buffers, textures, etc. for the binding
6823 points are set to \nullptr) is valid as well, as long as a
6824 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
6825 QRhiShaderResourceBindings, that specifies resources for all the bindings,
6826 is going to be set via
6827 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} when
6828 recording the render pass.
6829
6830 \note Setting the render pass descriptor is mandatory. To obtain a
6831 QRhiRenderPassDescriptor that can be passed to setRenderPassDescriptor(),
6832 use either QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() or
6833 QRhiSwapChain::newCompatibleRenderPassDescriptor().
6834
6835 \note Setting the vertex input layout is mandatory.
6836
6837 \note sampleCount() defaults to 1 and must match the sample count of the
6838 render target's color and depth stencil attachments.
6839
6840 \note The depth test, depth write, and stencil test are disabled by
6841 default. The face culling mode defaults to no culling.
6842
6843 \note stencilReadMask() and stencilWriteMask() apply to both faces. They
6844 both default to 0xFF.
6845
6846 \section2 Example usage
6847
6848 All settings of a graphics pipeline have defaults which might be suitable
6849 to many applications. Therefore a minimal example of creating a graphics
6850 pipeline could be the following. This assumes that the vertex shader takes
6851 a single \c{vec3 position} input at the input location 0. With the
6852 QRhiShaderResourceBindings and QRhiRenderPassDescriptor objects, plus the
6853 QShader collections for the vertex and fragment stages, a pipeline could be
6854 created like this:
6855
6856 \code
6857 QRhiShaderResourceBindings *srb;
6858 QRhiRenderPassDescriptor *rpDesc;
6859 QShader vs, fs;
6860 // ...
6861
6862 QRhiVertexInputLayout inputLayout;
6863 inputLayout.setBindings({ { 3 * sizeof(float) } });
6864 inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float3, 0 } });
6865
6866 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
6867 ps->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
6868 ps->setVertexInputLayout(inputLayout);
6869 ps->setShaderResourceBindings(srb);
6870 ps->setRenderPassDescriptor(rpDesc);
6871 if (!ps->create()) { error(); }
6872 \endcode
6873
6874 The above code creates a pipeline object that uses the defaults for many
6875 settings and states. For example, it will use a \l Triangles topology, no
6876 backface culling, blending is disabled but color write is enabled for all
6877 four channels, depth test/write are disabled, stencil operations are
6878 disabled.
6879
6880 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
6881 for details.
6882
6883 \sa QRhiCommandBuffer, QRhi
6884 */
6885
6886/*!
6887 \enum QRhiGraphicsPipeline::Flag
6888
6889 Flag values for describing the dynamic state of the pipeline, and other
6890 options. The viewport is always dynamic.
6891
6892 \value UsesBlendConstants Indicates that a blend color constant will be set
6893 via QRhiCommandBuffer::setBlendConstants()
6894
6895 \value UsesStencilRef Indicates that a stencil reference value will be set
6896 via QRhiCommandBuffer::setStencilRef()
6897
6898 \value UsesScissor Indicates that a scissor rectangle will be set via
6899 QRhiCommandBuffer::setScissor()
6900
6901 \value CompileShadersWithDebugInfo Requests compiling shaders with debug
6902 information enabled. This is relevant only when runtime shader compilation
6903 from source code is involved, and only when the underlying infrastructure
6904 supports this. With concrete examples, this is not relevant with Vulkan and
6905 SPIR-V, because the GLSL-to-SPIR-V compilation does not happen at run
6906 time. On the other hand, consider Direct3D and HLSL, where there are
6907 multiple options: when the QShader packages ship with pre-compiled bytecode
6908 (\c DXBC), debug information is to be requested through the tool that
6909 generates the \c{.qsb} file, similarly to the case of Vulkan and
6910 SPIR-V. However, when having HLSL source code in the pre- or
6911 runtime-generated QShader packages, the first phase of compilation (HLSL
6912 source to intermediate format) happens at run time too, with this flag taken
6913 into account. Debug information is relevant in particular with tools like
6914 RenderDoc since it allows seeing the original source code when investigating
6915 the pipeline and when performing vertex or fragment shader debugging.
6916
6917 \value UsesShadingRate Indicates that a per-draw (per-pipeline) shading rate
6918 value will be set via QRhiCommandBuffer::setShadingRate(). Not specifying
6919 this flag and still calling setShadingRate() may lead to varying, unexpected
6920 results depending on the underlying graphics API.
6921
6922 \value [since 6.12] UsesIndirectDraws Indicates that this pipeline will be used with
6923 indirect draw calls (QRhiCommandBuffer::drawIndirect() or
6924 QRhiCommandBuffer::drawIndexedIndirect()). Setting this flag allows the
6925 Metal backend to use Indirect Command Buffers (ICB) for GPU-driven
6926 rendering, which significantly reduces CPU overhead for large draw counts.
6927 Not setting this flag when using indirect draws is still functional but may
6928 result in less optimal performance on Metal. This flag has no effect on
6929 other backends.
6930 */
6931
6932/*!
6933 \enum QRhiGraphicsPipeline::Topology
6934 Specifies the primitive topology
6935
6936 \value Triangles (default)
6937 \value TriangleStrip
6938 \value TriangleFan (only available if QRhi::TriangleFanTopology is supported)
6939 \value Lines
6940 \value LineStrip
6941 \value Points
6942
6943 \value Patches (only available if QRhi::Tessellation is supported, and
6944 requires the tessellation stages to be present in the pipeline)
6945 */
6946
6947/*!
6948 \enum QRhiGraphicsPipeline::CullMode
6949 Specifies the culling mode
6950
6951 \value None No culling (default)
6952 \value Front Cull front faces
6953 \value Back Cull back faces
6954 */
6955
6956/*!
6957 \enum QRhiGraphicsPipeline::FrontFace
6958 Specifies the front face winding order
6959
6960 \value CCW Counter clockwise (default)
6961 \value CW Clockwise
6962 */
6963
6964/*!
6965 \enum QRhiGraphicsPipeline::ColorMaskComponent
6966 Flag values for specifying the color write mask
6967
6968 \value R
6969 \value G
6970 \value B
6971 \value A
6972 */
6973
6974/*!
6975 \enum QRhiGraphicsPipeline::BlendFactor
6976 Specifies the blend factor
6977
6978 \value Zero
6979 \value One
6980 \value SrcColor
6981 \value OneMinusSrcColor
6982 \value DstColor
6983 \value OneMinusDstColor
6984 \value SrcAlpha
6985 \value OneMinusSrcAlpha
6986 \value DstAlpha
6987 \value OneMinusDstAlpha
6988 \value ConstantColor
6989 \value OneMinusConstantColor
6990 \value ConstantAlpha
6991 \value OneMinusConstantAlpha
6992 \value SrcAlphaSaturate
6993 \value Src1Color
6994 \value OneMinusSrc1Color
6995 \value Src1Alpha
6996 \value OneMinusSrc1Alpha
6997 */
6998
6999/*!
7000 \enum QRhiGraphicsPipeline::BlendOp
7001 Specifies the blend operation
7002
7003 \value Add
7004 \value Subtract
7005 \value ReverseSubtract
7006 \value Min
7007 \value Max
7008 */
7009
7010/*!
7011 \enum QRhiGraphicsPipeline::CompareOp
7012 Specifies the depth or stencil comparison function
7013
7014 \value Never
7015 \value Less (default for depth)
7016 \value Equal
7017 \value LessOrEqual
7018 \value Greater
7019 \value NotEqual
7020 \value GreaterOrEqual
7021 \value Always (default for stencil)
7022 */
7023
7024/*!
7025 \enum QRhiGraphicsPipeline::StencilOp
7026 Specifies the stencil operation
7027
7028 \value StencilZero
7029 \value Keep (default)
7030 \value Replace
7031 \value IncrementAndClamp
7032 \value DecrementAndClamp
7033 \value Invert
7034 \value IncrementAndWrap
7035 \value DecrementAndWrap
7036 */
7037
7038/*!
7039 \enum QRhiGraphicsPipeline::PolygonMode
7040 \brief Specifies the polygon rasterization mode
7041
7042 Polygon Mode (Triangle Fill Mode in Metal, Fill Mode in D3D) specifies
7043 the fill mode used when rasterizing polygons. Polygons may be drawn as
7044 solids (Fill), or as a wire mesh (Line).
7045
7046 Support for non-fill polygon modes is optional and is indicated by the
7047 QRhi::NonFillPolygonMode feature. With OpenGL ES and some Vulkan
7048 implementations the feature will likely be reported as unsupported, which
7049 then means values other than Fill cannot be used.
7050
7051 \value Fill The interior of the polygon is filled (default)
7052 \value Line Boundary edges of the polygon are drawn as line segments.
7053 */
7054
7055/*!
7056 \struct QRhiGraphicsPipeline::TargetBlend
7057 \inmodule QtGuiPrivate
7058 \inheaderfile rhi/qrhi.h
7059 \since 6.6
7060 \brief Describes the blend state for one color attachment.
7061
7062 Defaults to color write enabled, blending disabled. The blend values are
7063 set up for pre-multiplied alpha (One, OneMinusSrcAlpha, One,
7064 OneMinusSrcAlpha) by default. This means that to get the alpha blending
7065 mode Qt Quick uses, it is enough to set the \c enable flag to true while
7066 leaving other values at their defaults.
7067
7068 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7069 for details.
7070 */
7071
7072/*!
7073 \variable QRhiGraphicsPipeline::TargetBlend::colorWrite
7074 */
7075
7076/*!
7077 \variable QRhiGraphicsPipeline::TargetBlend::enable
7078 */
7079
7080/*!
7081 \variable QRhiGraphicsPipeline::TargetBlend::srcColor
7082 */
7083
7084/*!
7085 \variable QRhiGraphicsPipeline::TargetBlend::dstColor
7086 */
7087
7088/*!
7089 \variable QRhiGraphicsPipeline::TargetBlend::opColor
7090 */
7091
7092/*!
7093 \variable QRhiGraphicsPipeline::TargetBlend::srcAlpha
7094 */
7095
7096/*!
7097 \variable QRhiGraphicsPipeline::TargetBlend::dstAlpha
7098 */
7099
7100/*!
7101 \variable QRhiGraphicsPipeline::TargetBlend::opAlpha
7102 */
7103
7104/*!
7105 \struct QRhiGraphicsPipeline::StencilOpState
7106 \inmodule QtGuiPrivate
7107 \inheaderfile rhi/qrhi.h
7108 \since 6.6
7109 \brief Describes the stencil operation state.
7110
7111 The default-constructed StencilOpState has the following set:
7112 \list
7113 \li failOp - \l Keep
7114 \li depthFailOp - \l Keep
7115 \li passOp - \l Keep
7116 \li compareOp \l Always
7117 \endlist
7118
7119 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7120 for details.
7121 */
7122
7123/*!
7124 \variable QRhiGraphicsPipeline::StencilOpState::failOp
7125 */
7126
7127/*!
7128 \variable QRhiGraphicsPipeline::StencilOpState::depthFailOp
7129 */
7130
7131/*!
7132 \variable QRhiGraphicsPipeline::StencilOpState::passOp
7133 */
7134
7135/*!
7136 \variable QRhiGraphicsPipeline::StencilOpState::compareOp
7137 */
7138
7139/*!
7140 \internal
7141 */
7142QRhiGraphicsPipeline::QRhiGraphicsPipeline(QRhiImplementation *rhi)
7143 : QRhiResource(rhi)
7144{
7145}
7146
7147/*!
7148 \return the resource type.
7149 */
7150QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
7151{
7152 return GraphicsPipeline;
7153}
7154
7155/*!
7156 \fn virtual bool QRhiGraphicsPipeline::create() = 0
7157
7158 Creates the corresponding native graphics resources. If there are already
7159 resources present due to an earlier create() with no corresponding
7160 destroy(), then destroy() is called implicitly first.
7161
7162 \return \c true when successful, \c false when a graphics operation failed.
7163 Regardless of the return value, calling destroy() is always safe.
7164
7165 \note This may be, depending on the underlying graphics API, an expensive
7166 operation, especially when shaders get compiled/optimized from source or
7167 from an intermediate bytecode format to the GPU's own instruction set.
7168 Where applicable, the QRhi backend automatically sets up the relevant
7169 non-persistent facilities to accelerate this, for example the Vulkan
7170 backend automatically creates a \c VkPipelineCache to improve data reuse
7171 during the lifetime of the application.
7172
7173 \note Drivers may also employ various persistent (disk-based) caching
7174 strategies for shader and pipeline data, which is hidden to and is outside
7175 of Qt's control. In some cases, depending on the graphics API and the QRhi
7176 backend, there are facilities within QRhi for manually managing such a
7177 cache, allowing the retrieval of a serializable blob that can then be
7178 reloaded in the future runs of the application to ensure faster pipeline
7179 creation times. See QRhi::pipelineCacheData() and
7180 QRhi::setPipelineCacheData() for details. Note also that when working with
7181 a QRhi instance managed by a higher level Qt framework, such as Qt Quick,
7182 it is possible that such disk-based caching is taken care of automatically,
7183 for example QQuickWindow uses a disk-based pipeline cache by default (which
7184 comes in addition to any driver-level caching).
7185 */
7186
7187/*!
7188 \fn QRhiGraphicsPipeline::Flags QRhiGraphicsPipeline::flags() const
7189 \return the currently set flags.
7190 */
7191
7192/*!
7193 \fn void QRhiGraphicsPipeline::setFlags(Flags f)
7194 Sets the flags \a f.
7195 */
7196
7197/*!
7198 \fn QRhiGraphicsPipeline::Topology QRhiGraphicsPipeline::topology() const
7199 \return the currently set primitive topology.
7200 */
7201
7202/*!
7203 \fn void QRhiGraphicsPipeline::setTopology(Topology t)
7204 Sets the primitive topology \a t.
7205 */
7206
7207/*!
7208 \fn QRhiGraphicsPipeline::CullMode QRhiGraphicsPipeline::cullMode() const
7209 \return the currently set face culling mode.
7210 */
7211
7212/*!
7213 \fn void QRhiGraphicsPipeline::setCullMode(CullMode mode)
7214 Sets the specified face culling \a mode.
7215 */
7216
7217/*!
7218 \fn QRhiGraphicsPipeline::FrontFace QRhiGraphicsPipeline::frontFace() const
7219 \return the currently set front face mode.
7220 */
7221
7222/*!
7223 \fn void QRhiGraphicsPipeline::setFrontFace(FrontFace f)
7224 Sets the front face mode \a f.
7225 */
7226
7227/*!
7228 \fn void QRhiGraphicsPipeline::setTargetBlends(std::initializer_list<TargetBlend> list)
7229
7230 Sets the \a list of render target blend settings. This is a list because
7231 when multiple render targets are used (i.e., a QRhiTextureRenderTarget with
7232 more than one QRhiColorAttachment), there needs to be a TargetBlend
7233 structure per render target (color attachment).
7234
7235 By default there is one default-constructed TargetBlend set.
7236
7237 \sa QRhi::MaxColorAttachments
7238 */
7239
7240/*!
7241 \fn template<typename InputIterator> void QRhiGraphicsPipeline::setTargetBlends(InputIterator first, InputIterator last)
7242 Sets the list of render target blend settings from the iterators \a first and \a last.
7243 */
7244
7245/*!
7246 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cbeginTargetBlends() const
7247 \return a const iterator pointing to the first item in the render target blend setting list.
7248 */
7249
7250/*!
7251 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cendTargetBlends() const
7252 \return a const iterator pointing just after the last item in the render target blend setting list.
7253 */
7254
7255/*!
7256 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::targetBlendAt(qsizetype index) const
7257 \return the render target blend setting at the specified \a index.
7258 */
7259
7260/*!
7261 \fn qsizetype QRhiGraphicsPipeline::targetBlendCount() const
7262 \return the number of render target blend settings.
7263 */
7264
7265/*!
7266 \fn bool QRhiGraphicsPipeline::hasDepthTest() const
7267 \return true if depth testing is enabled.
7268 */
7269
7270/*!
7271 \fn void QRhiGraphicsPipeline::setDepthTest(bool enable)
7272
7273 Enables or disables depth testing based on \a enable. Both depth test and
7274 the writing out of depth data are disabled by default.
7275
7276 \sa setDepthWrite()
7277 */
7278
7279/*!
7280 \fn bool QRhiGraphicsPipeline::hasDepthWrite() const
7281 \return true if depth write is enabled.
7282 */
7283
7284/*!
7285 \fn void QRhiGraphicsPipeline::setDepthWrite(bool enable)
7286
7287 Controls the writing out of depth data into the depth buffer based on
7288 \a enable. By default this is disabled. Depth write is typically enabled
7289 together with the depth test.
7290
7291 \note Enabling depth write without having depth testing enabled may not
7292 lead to the desired result, and should be avoided.
7293
7294 \sa setDepthTest()
7295 */
7296
7297/*!
7298 \fn bool QRhiGraphicsPipeline::hasDepthClamp() const
7299 \return true if depth clamp is enabled.
7300
7301 \since 6.11
7302 */
7303
7304/*!
7305 \fn void QRhiGraphicsPipeline::setDepthClamp(bool enable)
7306
7307 Enables depth clamping when \a enable is true. When depth clamping is
7308 enabled, primitives that would otherwise be clipped by the near or far
7309 clip plane are rasterized and their depth values are clamped to the
7310 depth range. When disabled (the default), such primitives are clipped.
7311
7312 \note This setting is ignored when the QRhi::DepthClamp feature is
7313 reported as unsupported.
7314
7315 \since 6.11
7316 */
7317
7318/*!
7319 \fn QRhiGraphicsPipeline::CompareOp QRhiGraphicsPipeline::depthOp() const
7320 \return the depth comparison function.
7321 */
7322
7323/*!
7324 \fn void QRhiGraphicsPipeline::setDepthOp(CompareOp op)
7325 Sets the depth comparison function \a op.
7326 */
7327
7328/*!
7329 \fn bool QRhiGraphicsPipeline::hasStencilTest() const
7330 \return true if stencil testing is enabled.
7331 */
7332
7333/*!
7334 \fn void QRhiGraphicsPipeline::setStencilTest(bool enable)
7335 Enables or disables stencil tests based on \a enable.
7336 By default this is disabled.
7337 */
7338
7339/*!
7340 \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilFront() const
7341 \return the current stencil test state for front faces.
7342 */
7343
7344/*!
7345 \fn void QRhiGraphicsPipeline::setStencilFront(const StencilOpState &state)
7346 Sets the stencil test \a state for front faces.
7347 */
7348
7349/*!
7350 \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilBack() const
7351 \return the current stencil test state for back faces.
7352 */
7353
7354/*!
7355 \fn void QRhiGraphicsPipeline::setStencilBack(const StencilOpState &state)
7356 Sets the stencil test \a state for back faces.
7357 */
7358
7359/*!
7360 \fn quint32 QRhiGraphicsPipeline::stencilReadMask() const
7361 \return the currrent stencil read mask.
7362 */
7363
7364/*!
7365 \fn void QRhiGraphicsPipeline::setStencilReadMask(quint32 mask)
7366 Sets the stencil read \a mask. The default value is 0xFF.
7367 */
7368
7369/*!
7370 \fn quint32 QRhiGraphicsPipeline::stencilWriteMask() const
7371 \return the current stencil write mask.
7372 */
7373
7374/*!
7375 \fn void QRhiGraphicsPipeline::setStencilWriteMask(quint32 mask)
7376 Sets the stencil write \a mask. The default value is 0xFF.
7377 */
7378
7379/*!
7380 \fn int QRhiGraphicsPipeline::sampleCount() const
7381 \return the currently set sample count. 1 means no multisample antialiasing.
7382 */
7383
7384/*!
7385 \fn void QRhiGraphicsPipeline::setSampleCount(int s)
7386
7387 Sets the sample count. Typical values for \a s are 1, 4, or 8. The pipeline
7388 must always be compatible with the render target, i.e. the sample counts
7389 must match.
7390
7391 \sa QRhi::supportedSampleCounts()
7392 */
7393
7394/*!
7395 \fn float QRhiGraphicsPipeline::lineWidth() const
7396 \return the currently set line width. The default is 1.0f.
7397 */
7398
7399/*!
7400 \fn void QRhiGraphicsPipeline::setLineWidth(float width)
7401
7402 Sets the line \a width. If the QRhi::WideLines feature is reported as
7403 unsupported at runtime, values other than 1.0f are ignored.
7404 */
7405
7406/*!
7407 \fn int QRhiGraphicsPipeline::depthBias() const
7408 \return the currently set depth bias.
7409 */
7410
7411/*!
7412 \fn void QRhiGraphicsPipeline::setDepthBias(int bias)
7413 Sets the depth \a bias. The default value is 0.
7414 */
7415
7416/*!
7417 \fn float QRhiGraphicsPipeline::slopeScaledDepthBias() const
7418 \return the currently set slope scaled depth bias.
7419 */
7420
7421/*!
7422 \fn void QRhiGraphicsPipeline::setSlopeScaledDepthBias(float bias)
7423 Sets the slope scaled depth \a bias. The default value is 0.
7424 */
7425
7426/*!
7427 \fn void QRhiGraphicsPipeline::setShaderStages(std::initializer_list<QRhiShaderStage> list)
7428 Sets the \a list of shader stages.
7429 */
7430
7431/*!
7432 \fn template<typename InputIterator> void QRhiGraphicsPipeline::setShaderStages(InputIterator first, InputIterator last)
7433 Sets the list of shader stages from the iterators \a first and \a last.
7434 */
7435
7436/*!
7437 \fn const QRhiShaderStage *QRhiGraphicsPipeline::cbeginShaderStages() const
7438 \return a const iterator pointing to the first item in the shader stage list.
7439 */
7440
7441/*!
7442 \fn const QRhiShaderStage *QRhiGraphicsPipeline::cendShaderStages() const
7443 \return a const iterator pointing just after the last item in the shader stage list.
7444 */
7445
7446/*!
7447 \fn const QRhiShaderStage *QRhiGraphicsPipeline::shaderStageAt(qsizetype index) const
7448 \return the shader stage at the specified \a index.
7449 */
7450
7451/*!
7452 \fn qsizetype QRhiGraphicsPipeline::shaderStageCount() const
7453 \return the number of shader stages in this pipeline.
7454 */
7455
7456/*!
7457 \fn QRhiVertexInputLayout QRhiGraphicsPipeline::vertexInputLayout() const
7458 \return the currently set vertex input layout specification.
7459 */
7460
7461/*!
7462 \fn void QRhiGraphicsPipeline::setVertexInputLayout(const QRhiVertexInputLayout &layout)
7463 Specifies the vertex input \a layout.
7464 */
7465
7466/*!
7467 \fn QRhiShaderResourceBindings *QRhiGraphicsPipeline::shaderResourceBindings() const
7468 \return the currently associated QRhiShaderResourceBindings object.
7469 */
7470
7471/*!
7472 \fn void QRhiGraphicsPipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
7473
7474 Associates with \a srb describing the resource binding layout and the
7475 resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional,
7476 because only the layout matters during pipeline creation. Therefore, the \a
7477 srb passed in here can leave the actual buffer or texture objects
7478 unspecified (\nullptr) as long as there is another,
7479 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
7480 QRhiShaderResourceBindings bound via
7481 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
7482 recording the draw calls.
7483 */
7484
7485/*!
7486 \fn QRhiRenderPassDescriptor *QRhiGraphicsPipeline::renderPassDescriptor() const
7487 \return the currently set QRhiRenderPassDescriptor.
7488 */
7489
7490/*!
7491 \fn void QRhiGraphicsPipeline::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
7492 Associates with the specified QRhiRenderPassDescriptor \a desc.
7493 */
7494
7495/*!
7496 \fn int QRhiGraphicsPipeline::patchControlPointCount() const
7497 \return the currently set patch control point count.
7498 */
7499
7500/*!
7501 \fn void QRhiGraphicsPipeline::setPatchControlPointCount(int count)
7502
7503 Sets the number of patch control points to \a count. The default value is
7504 3. This is used only when the topology is set to \l Patches.
7505 */
7506
7507/*!
7508 \fn QRhiGraphicsPipeline::PolygonMode QRhiGraphicsPipeline::polygonMode() const
7509 \return the polygon mode.
7510 */
7511
7512/*!
7513 \fn void QRhiGraphicsPipeline::setPolygonMode(PolygonMode mode)
7514 Sets the polygon \a mode. The default is Fill.
7515
7516 \sa QRhi::NonFillPolygonMode
7517 */
7518
7519/*!
7520 \fn int QRhiGraphicsPipeline::multiViewCount() const
7521 \return the view count. The default is 0, indicating no multiview rendering.
7522 \since 6.7
7523 */
7524
7525/*!
7526 \fn void QRhiGraphicsPipeline::setMultiViewCount(int count)
7527 Sets the view \a count for multiview rendering. The default is 0,
7528 indicating no multiview rendering.
7529 \a count must be 2 or larger to trigger multiview rendering.
7530
7531 Multiview is only available when the \l{QRhi::MultiView}{MultiView feature}
7532 is reported as supported. The render target must be a 2D texture array, and
7533 the color attachment for the render target must have the same \a count set.
7534
7535 See QRhiColorAttachment::setMultiViewCount() for further details on
7536 multiview rendering.
7537
7538 \since 6.7
7539 \sa QRhi::MultiView, QRhiColorAttachment::setMultiViewCount()
7540 */
7541
7542/*!
7543 \class QRhiSwapChain
7544 \inmodule QtGuiPrivate
7545 \inheaderfile rhi/qrhi.h
7546 \since 6.6
7547 \brief Swapchain resource.
7548
7549 A swapchain enables presenting rendering results to a surface. A swapchain
7550 is typically backed by a set of color buffers. Of these, one is displayed
7551 at a time.
7552
7553 Below is a typical pattern for creating and managing a swapchain and some
7554 associated resources in order to render onto a QWindow:
7555
7556 \code
7557 void init()
7558 {
7559 sc = rhi->newSwapChain();
7560 ds = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
7561 QSize(), // no need to set the size here due to UsedWithSwapChainOnly
7562 1,
7563 QRhiRenderBuffer::UsedWithSwapChainOnly);
7564 sc->setWindow(window);
7565 sc->setDepthStencil(ds);
7566 rp = sc->newCompatibleRenderPassDescriptor();
7567 sc->setRenderPassDescriptor(rp);
7568 resizeSwapChain();
7569 }
7570
7571 void resizeSwapChain()
7572 {
7573 hasSwapChain = sc->createOrResize();
7574 }
7575
7576 void render()
7577 {
7578 if (!hasSwapChain || notExposed)
7579 return;
7580
7581 if (sc->currentPixelSize() != sc->surfacePixelSize() || newlyExposed) {
7582 resizeSwapChain();
7583 if (!hasSwapChain)
7584 return;
7585 newlyExposed = false;
7586 }
7587
7588 rhi->beginFrame(sc);
7589 // ...
7590 rhi->endFrame(sc);
7591 }
7592 \endcode
7593
7594 Avoid relying on QWindow resize events to resize swapchains, especially
7595 considering that surface sizes may not always fully match the QWindow
7596 reported dimensions. The safe, cross-platform approach is to do the check
7597 via surfacePixelSize() whenever starting a new frame.
7598
7599 Releasing the swapchain must happen while the QWindow and the underlying
7600 native window is fully up and running. Building on the previous example:
7601
7602 \code
7603 void releaseSwapChain()
7604 {
7605 if (hasSwapChain) {
7606 sc->destroy();
7607 hasSwapChain = false;
7608 }
7609 }
7610
7611 // assuming Window is our QWindow subclass
7612 bool Window::event(QEvent *e)
7613 {
7614 switch (e->type()) {
7615 case QEvent::UpdateRequest: // for QWindow::requestUpdate()
7616 render();
7617 break;
7618 case QEvent::PlatformSurface:
7619 if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
7620 releaseSwapChain();
7621 break;
7622 default:
7623 break;
7624 }
7625 return QWindow::event(e);
7626 }
7627 \endcode
7628
7629 Initializing the swapchain and starting to render the first frame cannot
7630 start at any time. The safe, cross-platform approach is to rely on expose
7631 events. QExposeEvent is a loosely specified event that is sent whenever a
7632 window gets mapped, obscured, and resized, depending on the platform.
7633
7634 \code
7635 void Window::exposeEvent(QExposeEvent *)
7636 {
7637 // initialize and start rendering when the window becomes usable for graphics purposes
7638 if (isExposed() && !running) {
7639 running = true;
7640 init();
7641 }
7642
7643 // stop pushing frames when not exposed or size becomes 0
7644 if ((!isExposed() || (hasSwapChain && sc->surfacePixelSize().isEmpty())) && running)
7645 notExposed = true;
7646
7647 // continue when exposed again and the surface has a valid size
7648 if (isExposed() && running && notExposed && !sc->surfacePixelSize().isEmpty()) {
7649 notExposed = false;
7650 newlyExposed = true;
7651 }
7652
7653 if (isExposed() && !sc->surfacePixelSize().isEmpty())
7654 render();
7655 }
7656 \endcode
7657
7658 Once the rendering has started, a simple way to request a new frame is
7659 QWindow::requestUpdate(). While on some platforms this is merely a small
7660 timer, on others it has a specific implementation: for instance on macOS or
7661 iOS it may be backed by
7662 \l{https://developer.apple.com/documentation/corevideo/cvdisplaylink?language=objc}{CVDisplayLink}.
7663 The example above is already prepared for update requests by handling
7664 QEvent::UpdateRequest.
7665
7666 While acting as a QRhiRenderTarget, QRhiSwapChain also manages a
7667 QRhiCommandBuffer. Calling QRhi::endFrame() submits the recorded commands
7668 and also enqueues a \c present request. The default behavior is to do this
7669 with a swap interval of 1, meaning synchronizing to the display's vertical
7670 refresh is enabled. Thus the rendering thread calling beginFrame() and
7671 endFrame() will get throttled to vsync. On some backends this can be
7672 disabled by passing QRhiSwapChain:NoVSync in flags().
7673
7674 Multisampling (MSAA) is handled transparently to the applications when
7675 requested via setSampleCount(). Where applicable, QRhiSwapChain will take
7676 care of creating additional color buffers and issuing a multisample resolve
7677 command at the end of a frame. For OpenGL, it is necessary to request the
7678 appropriate sample count also via QSurfaceFormat, by calling
7679 QSurfaceFormat::setDefaultFormat() before initializing the QRhi.
7680
7681 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7682 for details.
7683 */
7684
7685/*!
7686 \enum QRhiSwapChain::Flag
7687 Flag values to describe swapchain properties
7688
7689 \value SurfaceHasPreMulAlpha Indicates that the target surface has
7690 transparency with premultiplied alpha. For example, this is what Qt Quick
7691 uses when the alpha channel is enabled on the target QWindow, because the
7692 scenegraph rendrerer always outputs fragments with alpha multiplied into
7693 the red, green, and blue values. To ensure identical behavior across
7694 platforms, always set QSurfaceFormat::alphaBufferSize() to a non-zero value
7695 on the target QWindow whenever this flag is set on the swapchain.
7696
7697 \value SurfaceHasNonPreMulAlpha Indicates the target surface has
7698 transparency with non-premultiplied alpha. Be aware that this may not be
7699 supported on some systems, if the system compositor always expects content
7700 with premultiplied alpha. In that case the behavior with this flag set is
7701 expected to be equivalent to SurfaceHasPreMulAlpha.
7702
7703 \value sRGB Requests to pick an sRGB format for the swapchain's color
7704 buffers and/or render target views, where applicable. Note that this
7705 implies that sRGB framebuffer update and blending will get enabled for all
7706 content targeting this swapchain, and opting out is not possible. For
7707 OpenGL, set \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the
7708 QSurfaceFormat of the QWindow in addition. Applicable only when the
7709 swapchain format is set to QRhiSwapChain::SDR.
7710
7711 \value UsedAsTransferSource Indicates the swapchain will be used as the
7712 source of a readback in QRhiResourceUpdateBatch::readBackTexture().
7713
7714 \value NoVSync Requests disabling waiting for vertical sync, also avoiding
7715 throttling the rendering thread. The behavior is backend specific and
7716 applicable only where it is possible to control this. Some may ignore the
7717 request altogether. For OpenGL, try instead setting the swap interval to 0
7718 on the QWindow via QSurfaceFormat::setSwapInterval().
7719
7720 \value MinimalBufferCount Requests creating the swapchain with the minimum
7721 number of buffers, which is in practice 2, unless the graphics
7722 implementation has a higher minimum number than that. Only applicable with
7723 backends where such control is available via the graphics API, for example,
7724 Vulkan. By default it is up to the backend to decide what number of buffers
7725 it requests (in practice this is almost always either 2 or 3), and it is
7726 not the applications' concern. However, on Vulkan for instance the backend
7727 will likely prefer the higher number (3), for example to avoid odd
7728 performance issues with some Vulkan implementations on mobile devices. It
7729 could be that on some platforms it can prove to be beneficial to force the
7730 lower buffer count (2), so this flag allows forcing that. Note that all
7731 this has no effect on the number of frames kept in flight, so the CPU
7732 (QRhi) will still prepare frames at most \c{N - 1} frames ahead of the GPU,
7733 even when the swapchain image buffer count larger than \c N. (\c{N} =
7734 QRhi::FramesInFlight and typically 2).
7735 */
7736
7737/*!
7738 \enum QRhiSwapChain::Format
7739 Describes the swapchain format. The default format is SDR.
7740
7741 This enum is used with
7742 \l{QRhiSwapChain::isFormatSupported()}{isFormatSupported()} to check
7743 upfront if creating the swapchain with the given format is supported by the
7744 platform and the window's associated screen, and with
7745 \l{QRhiSwapChain::setFormat()}{setFormat()}
7746 to set the requested format in the swapchain before calling
7747 \l{QRhiSwapChain::createOrResize()}{createOrResize()} for the first time.
7748
7749 \value SDR 8-bit RGBA or BGRA, depending on the backend and platform. With
7750 OpenGL ES in particular, it could happen that the platform provides less
7751 than 8 bits (e.g. due to EGL and the QSurfaceFormat choosing a 565 or 444
7752 format - this is outside the control of QRhi). Standard dynamic range. May
7753 be combined with setting the QRhiSwapChain::sRGB flag.
7754
7755 \value HDRExtendedSrgbLinear 16-bit float RGBA, high dynamic range,
7756 extended linear sRGB (scRGB) color space. This involves Rec. 709 primaries
7757 (same as SDR/sRGB) and linear colors. Conversion to the display's native
7758 color space (such as, HDR10) is performed by the windowing system. On
7759 Windows this is the canonical color space of the system compositor, and is
7760 the recommended format for HDR swapchains in general on desktop platforms.
7761
7762 \value HDR10 10-bit unsigned int RGB or BGR with 2 bit alpha, high dynamic
7763 range, HDR10 (Rec. 2020) color space with an ST2084 PQ transfer function.
7764
7765 \value HDRExtendedDisplayP3Linear 16-bit float RGBA, high dynamic range,
7766 extended linear Display P3 color space. The primary choice for HDR on
7767 platforms such as iOS and VisionOS.
7768 */
7769
7770/*!
7771 \internal
7772 */
7773QRhiSwapChain::QRhiSwapChain(QRhiImplementation *rhi)
7774 : QRhiResource(rhi)
7775{
7776}
7777
7778/*!
7779 \return the resource type.
7780 */
7781QRhiResource::Type QRhiSwapChain::resourceType() const
7782{
7783 return SwapChain;
7784}
7785
7786/*!
7787 \fn QSize QRhiSwapChain::currentPixelSize() const
7788
7789 \return the size with which the swapchain was last successfully built. Use
7790 this to decide if createOrResize() needs to be called again: if
7791 \c{currentPixelSize() != surfacePixelSize()} then the swapchain needs to be
7792 resized.
7793
7794 \note Typical rendering logic will call this function to get the output
7795 size when starting to prepare a new frame, and base dependent calculations
7796 (such as, the viewport) on the size returned from this function.
7797
7798 While in many cases the value is the same as \c{QWindow::size() *
7799 QWindow::devicePixelRatio()}, relying on the QWindow-reported size is not
7800 guaranteed to be correct on all platforms and graphics API implementations.
7801 Using this function is therefore strongly recommended whenever there is a
7802 need to identify the dimensions, in pixels, of the output layer or surface.
7803
7804 This also has the added benefit of avoiding potential data races when QRhi
7805 is used on a dedicated rendering thread, because the need to call QWindow
7806 functions, that may then access data updated on the main thread, is
7807 avoided.
7808
7809 \sa surfacePixelSize()
7810 */
7811
7812/*!
7813 \fn virtual QSize QRhiSwapChain::surfacePixelSize() = 0
7814
7815 \return The size of the window's associated surface or layer.
7816
7817 \warning Do not assume this is the same as \c{QWindow::size() *
7818 QWindow::devicePixelRatio()}. With some graphics APIs and windowing system
7819 interfaces (for example, Vulkan) there is a theoretical possibility for a
7820 surface to assume a size different from the associated window. To support
7821 these cases, \b{rendering logic must always base size-derived calculations
7822 (such as, viewports) on the size reported from QRhiSwapChain, and never on
7823 the size queried from QWindow}.
7824
7825 \note \b{Can also be called before createOrResize(), if at least window() is
7826 already set. This in combination with currentPixelSize() allows to detect
7827 when a swapchain needs to be resized.} However, watch out for the fact that
7828 the size of the underlying native object (surface, layer, or similar) is
7829 "live", so whenever this function is called, it returns the latest value
7830 reported by the underlying implementation, without any atomicity guarantee.
7831 Therefore, using this function to determine pixel sizes for graphics
7832 resources that are used in a frame is strongly discouraged. Rely on
7833 currentPixelSize() instead which returns a size that is atomic and will not
7834 change between createOrResize() invocations.
7835
7836 \note For depth-stencil buffers used in combination with the swapchain's
7837 color buffers, it is strongly recommended to rely on the automatic sizing
7838 and rebuilding behavior provided by the
7839 QRhiRenderBuffer:UsedWithSwapChainOnly flag. Avoid querying the surface
7840 size via this function just to get a size that can be passed to
7841 QRhiRenderBuffer::setPixelSize() as that would suffer from the lack of
7842 atomicity as described above.
7843
7844 \sa currentPixelSize()
7845 */
7846
7847/*!
7848 \fn virtual bool QRhiSwapChain::isFormatSupported(Format f) = 0
7849
7850 \return true if the given swapchain format \a f is supported. SDR is always
7851 supported.
7852
7853 \note Can be called independently of createOrResize(), but window() must
7854 already be set. Calling without the window set may lead to unexpected
7855 results depending on the backend and platform (most likely false for any
7856 HDR format), because HDR format support is usually tied to the output
7857 (screen) to which the swapchain's associated window belongs at any given
7858 time. If the result is true for a HDR format, then creating the swapchain
7859 with that format is expected to succeed as long as the window is not moved
7860 to another screen in the meantime.
7861
7862 The main use of this function is to call it before the first
7863 createOrResize() after the window is already set. This allow the QRhi
7864 backends to perform platform or windowing system specific queries to
7865 determine if the window (and the screen it is on) is capable of true HDR
7866 output with the specified format.
7867
7868 When the format is reported as supported, call setFormat() to set the
7869 requested format and call createOrResize(). Be aware of the consequences
7870 however: successfully requesting a HDR format will involve having to deal
7871 with a different color space, possibly doing white level correction for
7872 non-HDR-aware content, adjusting tonemapping methods, adjusting offscreen
7873 render target settings, etc.
7874
7875 \sa setFormat()
7876 */
7877
7878/*!
7879 \fn virtual QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer() = 0
7880
7881 \return a command buffer on which rendering commands and resource updates
7882 can be recorded within a \l{QRhi::beginFrame()}{beginFrame} -
7883 \l{QRhi::endFrame()}{endFrame} block, assuming beginFrame() was called with
7884 this swapchain.
7885
7886 \note The returned object is valid also after endFrame(), up until the next
7887 beginFrame(), but the returned command buffer should not be used to record
7888 any commands then. Rather, it can be used to query data collected during
7889 the frame (or previous frames), for example by calling
7890 \l{QRhiCommandBuffer::lastCompletedGpuTime()}{lastCompletedGpuTime()}.
7891
7892 \note The value must not be cached and reused between frames. The caller
7893 should not hold on to the returned object once
7894 \l{QRhi::beginFrame()}{beginFrame()} is called again. Instead, the command
7895 buffer object should be queried again by calling this function.
7896*/
7897
7898/*!
7899 \fn virtual QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget() = 0
7900
7901 \return a render target that can used with beginPass() in order to render
7902 the swapchain's current backbuffer. Only valid within a
7903 QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called
7904 with this swapchain.
7905
7906 \note the value must not be cached and reused between frames
7907 */
7908
7909/*!
7910 \enum QRhiSwapChain::StereoTargetBuffer
7911 Selects the backbuffer to use with a stereoscopic swapchain.
7912
7913 \value LeftBuffer
7914 \value RightBuffer
7915 */
7916
7917/*!
7918 \return a render target that can be used with beginPass() in order to
7919 render to the swapchain's left or right backbuffer. This overload should be
7920 used only with stereoscopic rendering, that is, when the associated QWindow
7921 is backed by two color buffers, one for each eye, instead of just one.
7922
7923 When stereoscopic rendering is not supported, the return value will be
7924 the default target. It is supported by all hardware backends except for Metal, in
7925 combination with \l QSurfaceFormat::StereoBuffers, assuming it is supported
7926 by the graphics and display driver stack at run time. Metal and Null backends
7927 are going to return the default render target from this overload.
7928
7929 \note the value must not be cached and reused between frames
7930 */
7931QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
7932{
7933 Q_UNUSED(targetBuffer);
7934 return currentFrameRenderTarget();
7935}
7936
7937/*!
7938 \fn virtual bool QRhiSwapChain::createOrResize() = 0
7939
7940 Creates the swapchain if not already done and resizes the swapchain buffers
7941 to match the current size of the targeted surface. Call this whenever the
7942 size of the target surface is different than before.
7943
7944 \note call destroy() only when the swapchain needs to be released
7945 completely, typically upon
7946 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed. To perform resizing, just
7947 call createOrResize().
7948
7949 \return \c true when successful, \c false when a graphics operation failed.
7950 Regardless of the return value, calling destroy() is always safe.
7951 */
7952
7953/*!
7954 \fn QWindow *QRhiSwapChain::window() const
7955 \return the currently set window.
7956 */
7957
7958/*!
7959 \fn void QRhiSwapChain::setWindow(QWindow *window)
7960 Sets the \a window.
7961 */
7962
7963/*!
7964 \fn QRhiSwapChainProxyData QRhiSwapChain::proxyData() const
7965 \return the currently set proxy data.
7966 */
7967
7968/*!
7969 \fn void QRhiSwapChain::setProxyData(const QRhiSwapChainProxyData &d)
7970 Sets the proxy data \a d.
7971
7972 \sa QRhi::updateSwapChainProxyData()
7973 */
7974
7975/*!
7976 \fn QRhiSwapChain::Flags QRhiSwapChain::flags() const
7977 \return the currently set flags.
7978 */
7979
7980/*!
7981 \fn void QRhiSwapChain::setFlags(Flags f)
7982 Sets the flags \a f.
7983 */
7984
7985/*!
7986 \fn QRhiSwapChain::Format QRhiSwapChain::format() const
7987 \return the currently set format.
7988 */
7989
7990/*!
7991 \fn void QRhiSwapChain::setFormat(Format f)
7992 Sets the format \a f.
7993
7994 Avoid setting formats that are reported as unsupported from
7995 isFormatSupported(). Note that support for a given format may depend on the
7996 screen the swapchain's associated window is opened on. On some platforms,
7997 such as Windows and macOS, for HDR output to work it is necessary to have
7998 HDR output enabled in the display settings.
7999
8000 See isFormatSupported(), \l QRhiSwapChainHdrInfo, and \l Format for more
8001 information on high dynamic range output.
8002 */
8003
8004/*!
8005 \fn QRhiRenderBuffer *QRhiSwapChain::depthStencil() const
8006 \return the currently associated renderbuffer for depth-stencil.
8007 */
8008
8009/*!
8010 \fn void QRhiSwapChain::setDepthStencil(QRhiRenderBuffer *ds)
8011 Sets the renderbuffer \a ds for use as a depth-stencil buffer.
8012 */
8013
8014/*!
8015 \fn int QRhiSwapChain::sampleCount() const
8016 \return the currently set sample count. 1 means no multisample antialiasing.
8017 */
8018
8019/*!
8020 \fn void QRhiSwapChain::setSampleCount(int samples)
8021
8022 Sets the sample count. Common values for \a samples are 1 (no MSAA), 4 (4x
8023 MSAA), or 8 (8x MSAA).
8024
8025 \sa QRhi::supportedSampleCounts()
8026 */
8027
8028/*!
8029 \fn QRhiRenderPassDescriptor *QRhiSwapChain::renderPassDescriptor() const
8030 \return the currently associated QRhiRenderPassDescriptor object.
8031 */
8032
8033/*!
8034 \fn void QRhiSwapChain::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
8035 Associates with the QRhiRenderPassDescriptor \a desc.
8036 */
8037
8038/*!
8039 \fn virtual QRhiRenderPassDescriptor *QRhiSwapChain::newCompatibleRenderPassDescriptor() = 0;
8040
8041 \return a new QRhiRenderPassDescriptor that is compatible with this swapchain.
8042
8043 The returned value is used in two ways: it can be passed to
8044 setRenderPassDescriptor() and
8045 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
8046 describes the attachments (color, depth/stencil) and the load/store
8047 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
8048 be used in combination with a swapchain that has a
8049 \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
8050 QRhiRenderPassDescriptor set.
8051
8052 \sa createOrResize()
8053 */
8054
8055/*!
8056 \fn QRhiShadingRateMap *QRhiSwapChain::shadingRateMap() const
8057 \return the currently set QRhiShadingRateMap. By default this is \nullptr.
8058 \since 6.9
8059 */
8060
8061/*!
8062 \fn void QRhiSwapChain::setShadingRateMap(QRhiShadingRateMap *map)
8063
8064 Associates with the specified QRhiShadingRateMap \a map. This is functional
8065 only when the \l QRhi::VariableRateShadingMap feature is reported as
8066 supported.
8067
8068 When QRhiCommandBuffer::setShadingRate() is also called, the higher of the
8069 two shading rates is used for each tile. There is currently no control
8070 offered over the combiner behavior.
8071
8072 \note Setting a shading rate map implies that a different, new
8073 QRhiRenderPassDescriptor is needed and some of the native swapchain objects
8074 must be rebuilt. Therefore, if the swapchain is already set up, call
8075 newCompatibleRenderPassDescriptor() and setRenderPassDescriptor() right
8076 after setShadingRateMap(). Then, createOrResize() must also be called again.
8077 This has rolling consequences, for example for graphics pipelines: those
8078 also need to be associated with the new QRhiRenderPassDescriptor and then
8079 rebuilt. See \l QRhiRenderPassDescriptor::serializedFormat() for some
8080 suggestions on how to deal with this. Remember to set the
8081 QRhiGraphicsPipeline::UsesShadingRate flag for them as well.
8082
8083 \since 6.9
8084 */
8085
8086/*!
8087 \struct QRhiSwapChainHdrInfo
8088 \inmodule QtGuiPrivate
8089 \inheaderfile rhi/qrhi.h
8090 \since 6.6
8091
8092 \brief Describes the high dynamic range related information of the
8093 swapchain's associated output.
8094
8095 To perform HDR-compatible tonemapping, where the target range is not [0,1],
8096 one often needs to know the maximum luminance of the display the
8097 swapchain's window is associated with. While this is often made
8098 user-configurable (think brightness, gamma and similar settings in games),
8099 it can be highly useful to set defaults based on the values reported by the
8100 display itself, thus providing a decent starting point.
8101
8102 There are some problems however: the information is exposed in different
8103 forms on different platforms, whereas with cross-platform graphics APIs
8104 there is often no associated solution at all, because managing such
8105 information is not in the scope of the API (and may rather be retrievable
8106 via other platform-specific means, if any).
8107
8108 With Metal on macOS/iOS, there is no luminance values exposed in the
8109 platform APIs. Instead, the maximum color component value, that would be
8110 1.0 in a non-HDR setup, is provided. The \c limitsType field indicates what
8111 kind of information is available. It is then up to the clients of QRhi to
8112 access the correct data from the \c limits union and use it as they see
8113 fit.
8114
8115 With an API like Vulkan, where there is no way to get such information, the
8116 values are always the built-in defaults.
8117
8118 Therefore, the struct returned from QRhiSwapChain::hdrInfo() contains
8119 either some hard-coded defaults or real values received from an API such as
8120 DXGI (IDXGIOutput6) or Cocoa (NSScreen). When no platform queries are
8121 available (or needs using platform facilities out of scope for QRhi), the
8122 hard-coded defaults are a maximum luminance of 1000 nits and an SDR white
8123 level of 200.
8124
8125 The struct also exposes the presumed luminance behavior of the platform and
8126 its compositor, to indicate what a color component value of 1.0 is treated
8127 as in a HDR color buffer. In some cases it will be necessary to perform
8128 color correction of non-HDR content composited with HDR content. To enable
8129 this, the SDR white level is queried from the system on some platforms
8130 (Windows) and exposed here.
8131
8132 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8133 for details.
8134
8135 \sa QRhiSwapChain::hdrInfo()
8136 */
8137
8138/*!
8139 \enum QRhiSwapChainHdrInfo::LimitsType
8140
8141 \value LuminanceInNits Indicates that the \l limits union has its
8142 \c luminanceInNits struct set
8143
8144 \value ColorComponentValue Indicates that the \l limits union has its
8145 \c colorComponentValue struct set
8146*/
8147
8148/*!
8149 \enum QRhiSwapChainHdrInfo::LuminanceBehavior
8150
8151 \value SceneReferred Indicates that the color value of 1.0 is interpreted
8152 as 80 nits. This is the behavior of HDR-enabled windows with the Windows
8153 compositor. See
8154 \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range}{this
8155 page} for more information on HDR on Windows.
8156
8157 \value DisplayReferred Indicates that the color value of 1.0 is interpreted
8158 as the value of the SDR white. (which can be e.g. 200 nits, but will vary
8159 depending on screen brightness) This is the behavior of HDR-enabled windows
8160 on Apple platforms. See
8161 \l{https://developer.apple.com/documentation/metal/hdr_content/displaying_hdr_content_in_a_metal_layer}{this
8162 page} for more information on Apple's EDR system.
8163*/
8164
8165/*!
8166 \variable QRhiSwapChainHdrInfo::limitsType
8167
8168 With Metal on macOS/iOS, there is no luminance values exposed in the
8169 platform APIs. Instead, the maximum color component value, that would be
8170 1.0 in a non-HDR setup, is provided. This value indicates what kind of
8171 information is available in \l limits.
8172
8173 \sa QRhiSwapChain::hdrInfo()
8174*/
8175
8176/*!
8177 \variable QRhiSwapChainHdrInfo::limits
8178
8179 Contains the actual values queried from the graphics API or the platform.
8180 The type of data is indicated by \l limitsType. This is therefore a union.
8181 There are currently two options:
8182
8183 Luminance values in nits:
8184
8185 \code
8186 struct {
8187 float minLuminance;
8188 float maxLuminance;
8189 } luminanceInNits;
8190 \endcode
8191
8192 On Windows the minimum and maximum luminance depends on the screen
8193 brightness. While not relevant for desktops, on laptops the screen
8194 brightness may change at any time. Increasing brightness implies decreased
8195 maximum luminance. In addition, the results may also be dependent on the
8196 HDR Content Brightness set in Windows Settings' System/Display/HDR view,
8197 if there is such a setting.
8198
8199 Note however that the changes made to the laptop screen's brightness or in
8200 the system settings while the application is running are not necessarily
8201 reflected in the returned values, meaning calling hdrInfo() again may still
8202 return the same luminance range as before for the rest of the process'
8203 lifetime. The exact behavior is up to DXGI and Qt has no control over it.
8204
8205 \note The Windows compositor works in scene-referred mode for HDR content.
8206 A color component value of 1.0 corresponds to a luminance of 80 nits. When
8207 rendering non-HDR content (e.g. 2D UI elements), the correction of the
8208 white level is often necessary. (e.g., outputting the fragment color (1, 1,
8209 1) will likely lead to showing a shade of white that is too dim on-screen)
8210 See \l sdrWhiteLevel.
8211
8212 For macOS/iOS, the current maximum and potential maximum color
8213 component values are provided:
8214
8215 \code
8216 struct {
8217 float maxColorComponentValue;
8218 float maxPotentialColorComponentValue;
8219 } colorComponentValue;
8220 \endcode
8221
8222 The value may depend on the screen brightness, which on laptops means that
8223 the result may change in the next call to hdrInfo() if the brightness was
8224 changed in the meantime. The maximum screen brightness implies a maximum
8225 color value of 1.0.
8226
8227 \note Apple's EDR is display-referred. 1.0 corresponds to a luminance level
8228 of SDR white (e.g. 200 nits), the value of which varies based on the screen
8229 brightness and possibly other settings. The exact luminance value for that,
8230 or the maximum luminance of the display, are not exposed to the
8231 applications.
8232
8233 \note It has been observed that the color component values are not set to
8234 the correct larger-than-1 value right away on startup on some macOS
8235 systems, but the values tend to change during or after the first frame.
8236
8237 \sa QRhiSwapChain::hdrInfo()
8238*/
8239
8240/*!
8241 \variable QRhiSwapChainHdrInfo::luminanceBehavior
8242
8243 Describes the platform's presumed behavior with regards to color values.
8244
8245 \sa sdrWhiteLevel
8246 */
8247
8248/*!
8249 \variable QRhiSwapChainHdrInfo::sdrWhiteLevel
8250
8251 On Windows this is the dynamic SDR white level in nits. The value is
8252 dependent on the screen brightness (on laptops), and the SDR or HDR Content
8253 Brightness settings in the Windows settings' System/Display/HDR view.
8254
8255 To perform white level correction for non-HDR (SDR) content, such as 2D UI
8256 elemenents, multiply the final color with sdrWhiteLevel / 80.0 whenever
8257 \l luminanceBehavior is SceneReferred. (assuming Windows and a linear
8258 extended sRGB (scRGB) color space)
8259
8260 On other platforms the value is always a pre-defined value, 200. This may
8261 not match the system's actual SDR white level, but the value of this
8262 variable is not relevant in practice when the \l luminanceBehavior is
8263 DisplayReferred, because then the color component value of 1.0 refers to
8264 the SDR white by default.
8265
8266 \sa luminanceBehavior
8267*/
8268
8269/*!
8270 \return the HDR information for the associated display.
8271
8272 Do not assume that this is a cheap operation. Depending on the platform,
8273 this function makes various platform queries which may have a performance
8274 impact.
8275
8276 \note Can be called before createOrResize() as long as the window is
8277 \l{setWindow()}{set}.
8278
8279 \note What happens when moving a window with an initialized swapchain
8280 between displays (HDR to HDR with different characteristics, HDR to SDR,
8281 etc.) is not currently well-defined and depends heavily on the windowing
8282 system and compositor, with potentially varying behavior between platforms.
8283 Currently QRhi only guarantees that hdrInfo() returns valid data, if
8284 available, for the display to which the swapchain's associated window
8285 belonged at the time of createOrResize().
8286
8287 \sa QRhiSwapChainHdrInfo
8288 */
8289QRhiSwapChainHdrInfo QRhiSwapChain::hdrInfo()
8290{
8291 QRhiSwapChainHdrInfo info;
8292 info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
8293 info.limits.luminanceInNits.minLuminance = 0.0f;
8294 info.limits.luminanceInNits.maxLuminance = 1000.0f;
8295 info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
8296 info.sdrWhiteLevel = 200.0f;
8297 return info;
8298}
8299
8300#ifndef QT_NO_DEBUG_STREAM
8301QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
8302{
8303 QDebugStateSaver saver(dbg);
8304 dbg.nospace() << "QRhiSwapChainHdrInfo(";
8305 switch (info.limitsType) {
8307 dbg.nospace() << " minLuminance=" << info.limits.luminanceInNits.minLuminance
8308 << " maxLuminance=" << info.limits.luminanceInNits.maxLuminance;
8309 break;
8311 dbg.nospace() << " maxColorComponentValue=" << info.limits.colorComponentValue.maxColorComponentValue;
8312 dbg.nospace() << " maxPotentialColorComponentValue=" << info.limits.colorComponentValue.maxPotentialColorComponentValue;
8313 break;
8314 }
8315 switch (info.luminanceBehavior) {
8317 dbg.nospace() << " scene-referred, SDR white level=" << info.sdrWhiteLevel;
8318 break;
8320 dbg.nospace() << " display-referred";
8321 break;
8322 }
8323 dbg.nospace() << ')';
8324 return dbg;
8325}
8326#endif
8327
8328/*!
8329 \class QRhiComputePipeline
8330 \inmodule QtGuiPrivate
8331 \inheaderfile rhi/qrhi.h
8332 \since 6.6
8333 \brief Compute pipeline state resource.
8334
8335 \note Setting the shader resource bindings is mandatory. The referenced
8336 QRhiShaderResourceBindings must already have created() called on it by the
8337 time create() is called.
8338
8339 \note Setting the shader is mandatory.
8340
8341 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8342 for details.
8343 */
8344
8345/*!
8346 \enum QRhiComputePipeline::Flag
8347
8348 Flag values for describing pipeline options.
8349
8350 \value CompileShadersWithDebugInfo Requests compiling shaders with debug
8351 information enabled, when applicable. See
8352 QRhiGraphicsPipeline::CompileShadersWithDebugInfo for more information.
8353 */
8354
8355/*!
8356 \return the resource type.
8357 */
8358QRhiResource::Type QRhiComputePipeline::resourceType() const
8359{
8360 return ComputePipeline;
8361}
8362
8363/*!
8364 \internal
8365 */
8366QRhiComputePipeline::QRhiComputePipeline(QRhiImplementation *rhi)
8367 : QRhiResource(rhi)
8368{
8369}
8370
8371/*!
8372 \fn QRhiComputePipeline::Flags QRhiComputePipeline::flags() const
8373 \return the currently set flags.
8374 */
8375
8376/*!
8377 \fn void QRhiComputePipeline::setFlags(Flags f)
8378 Sets the flags \a f.
8379 */
8380
8381/*!
8382 \fn QRhiShaderStage QRhiComputePipeline::shaderStage() const
8383 \return the currently set shader.
8384 */
8385
8386/*!
8387 \fn void QRhiComputePipeline::setShaderStage(const QRhiShaderStage &stage)
8388
8389 Sets the shader to use. \a stage can only refer to the
8390 \l{QRhiShaderStage::Compute}{compute stage}.
8391 */
8392
8393/*!
8394 \fn QRhiShaderResourceBindings *QRhiComputePipeline::shaderResourceBindings() const
8395 \return the currently associated QRhiShaderResourceBindings object.
8396 */
8397
8398/*!
8399 \fn void QRhiComputePipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
8400
8401 Associates with \a srb describing the resource binding layout and the
8402 resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional. As
8403 with graphics pipelines, the \a srb passed in here can leave the actual
8404 buffer or texture objects unspecified (\nullptr) as long as there is
8405 another,
8406 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
8407 QRhiShaderResourceBindings bound via
8408 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
8409 recording the dispatch call.
8410 */
8411
8412/*!
8413 \struct QRhiIndirectDrawCommand
8414 \inmodule QtGuiPrivate
8415 \inheaderfile rhi/qrhi.h
8416 \since 6.12
8417 \brief Draw command.
8418
8419 A draw command that can be uploaded to a QRhiBuffer of usage
8420 QRhiBuffer::UsageFlag::IndirectBuffer.
8421
8422 \sa QRhiCommandBuffer::drawIndirect()
8423
8424 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8425 for details.
8426 */
8427
8428/*!
8429 \variable QRhiIndirectDrawCommand::vertexCount
8430*/
8431
8432/*!
8433 \variable QRhiIndirectDrawCommand::instanceCount
8434*/
8435
8436/*!
8437 \variable QRhiIndirectDrawCommand::firstVertex
8438*/
8439
8440/*!
8441 \variable QRhiIndirectDrawCommand::firstInstance
8442*/
8443
8444/*!
8445 \struct QRhiIndexedIndirectDrawCommand
8446 \inmodule QtGuiPrivate
8447 \inheaderfile rhi/qrhi.h
8448 \since 6.12
8449 \brief Indexed draw command.
8450
8451 An indexed draw command that can be uploaded to a QRhiBuffer of usage
8452 QRhiBuffer::UsageFlag::IndirectBuffer.
8453
8454 \sa QRhiCommandBuffer::drawIndexedIndirect()
8455
8456 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8457 for details.
8458 */
8459
8460/*!
8461 \variable QRhiIndexedIndirectDrawCommand::indexCount
8462*/
8463
8464/*!
8465 \variable QRhiIndexedIndirectDrawCommand::instanceCount
8466*/
8467
8468/*!
8469 \variable QRhiIndexedIndirectDrawCommand::firstIndex
8470*/
8471
8472/*!
8473 \variable QRhiIndexedIndirectDrawCommand::vertexOffset
8474*/
8475
8476/*!
8477 \variable QRhiIndexedIndirectDrawCommand::firstInstance
8478*/
8479
8480/*!
8481 \class QRhiCommandBuffer
8482 \inmodule QtGuiPrivate
8483 \inheaderfile rhi/qrhi.h
8484 \since 6.6
8485 \brief Command buffer resource.
8486
8487 Not creatable by applications at the moment. The only ways to obtain a
8488 valid QRhiCommandBuffer are to get it from the targeted swapchain via
8489 QRhiSwapChain::currentFrameCommandBuffer(), or, in case of rendering
8490 completely offscreen, initializing one via QRhi::beginOffscreenFrame().
8491
8492 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8493 for details.
8494 */
8495
8496/*!
8497 \enum QRhiCommandBuffer::IndexFormat
8498 Specifies the index data type
8499
8500 \value IndexUInt16 Unsigned 16-bit (quint16)
8501 \value IndexUInt32 Unsigned 32-bit (quint32)
8502 */
8503
8504/*!
8505 \enum QRhiCommandBuffer::BeginPassFlag
8506 Flag values for QRhi::beginPass()
8507
8508 \value ExternalContent Specifies that there will be a call to
8509 QRhiCommandBuffer::beginExternal() in this pass. Some backends, Vulkan in
8510 particular, will fail if this flag is not set and beginExternal() is still
8511 called.
8512
8513 \value DoNotTrackResourcesForCompute Specifies that there is no need to
8514 track resources used in this pass if the only purpose of such tracking is
8515 to generate barriers for compute. Implies that there are no compute passes
8516 in the frame. This is an optimization hint that may be taken into account
8517 by certain backends, OpenGL in particular, allowing them to skip certain
8518 operations. When this flag is set for a render pass in a frame, calling
8519 \l{QRhiCommandBuffer::beginComputePass()}{beginComputePass()} in that frame
8520 may lead to unexpected behavior, depending on the resource dependencies
8521 between the render and compute passes.
8522 */
8523
8524/*!
8525 \typedef QRhiCommandBuffer::DynamicOffset
8526
8527 Synonym for std::pair<int, quint32>. The first entry is the binding, the second
8528 is the offset in the buffer.
8529*/
8530
8531/*!
8532 \typedef QRhiCommandBuffer::VertexInput
8533
8534 Synonym for std::pair<QRhiBuffer *, quint32>. The second entry is an offset in
8535 the buffer specified by the first.
8536*/
8537
8538/*!
8539 \internal
8540 */
8541QRhiCommandBuffer::QRhiCommandBuffer(QRhiImplementation *rhi)
8542 : QRhiResource(rhi)
8543{
8544}
8545
8546/*!
8547 \return the resource type.
8548 */
8549QRhiResource::Type QRhiCommandBuffer::resourceType() const
8550{
8551 return CommandBuffer;
8552}
8553
8554static const char *resourceTypeStr(const QRhiResource *res)
8555{
8556 switch (res->resourceType()) {
8557 case QRhiResource::Buffer:
8558 return "Buffer";
8559 case QRhiResource::Texture:
8560 return "Texture";
8561 case QRhiResource::Sampler:
8562 return "Sampler";
8563 case QRhiResource::RenderBuffer:
8564 return "RenderBuffer";
8565 case QRhiResource::RenderPassDescriptor:
8566 return "RenderPassDescriptor";
8567 case QRhiResource::SwapChainRenderTarget:
8568 return "SwapChainRenderTarget";
8569 case QRhiResource::TextureRenderTarget:
8570 return "TextureRenderTarget";
8571 case QRhiResource::ShaderResourceBindings:
8572 return "ShaderResourceBindings";
8573 case QRhiResource::GraphicsPipeline:
8574 return "GraphicsPipeline";
8575 case QRhiResource::SwapChain:
8576 return "SwapChain";
8577 case QRhiResource::ComputePipeline:
8578 return "ComputePipeline";
8579 case QRhiResource::CommandBuffer:
8580 return "CommandBuffer";
8581 case QRhiResource::ShadingRateMap:
8582 return "ShadingRateMap";
8583 }
8584
8585 Q_UNREACHABLE_RETURN("");
8586}
8587
8588QRhiImplementation::~QRhiImplementation()
8589{
8590 qDeleteAll(resUpdPool);
8591
8592 // Be nice and show something about leaked stuff. Though we may not get
8593 // this far with some backends where the allocator or the api may check
8594 // and freak out for unfreed graphics objects in the derived dtor already.
8595#ifndef QT_NO_DEBUG
8596 // debug builds: just do it always
8597 static bool leakCheck = true;
8598#else
8599 // release builds: opt-in
8600 static bool leakCheck = qEnvironmentVariableIntValue("QT_RHI_LEAK_CHECK");
8601#endif
8602 if (!resources.isEmpty()) {
8603 if (leakCheck) {
8604 qWarning("QRhi %p going down with %d unreleased resources that own native graphics objects. This is not nice.",
8605 q, int(resources.size()));
8606 }
8607 for (auto it = resources.cbegin(), end = resources.cend(); it != end; ++it) {
8608 QRhiResource *res = it.key();
8609 const bool ownsNativeResources = it.value();
8610 if (leakCheck && ownsNativeResources)
8611 qWarning(" %s resource %p (%s)", resourceTypeStr(res), res, res->m_objectName.constData());
8612
8613 // Null out the resource's rhi pointer. This is why it makes sense to do null
8614 // checks in the destroy() implementations of the various resource types. It
8615 // allows to survive in bad applications that somehow manage to destroy a
8616 // resource of a QRhi after the QRhi itself.
8617 res->m_rhi = nullptr;
8618 }
8619 }
8620}
8621
8622bool QRhiImplementation::isCompressedFormat(QRhiTexture::Format format) const
8623{
8624 return (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
8625 || (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
8626 || (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12);
8627}
8628
8629bool QRhiImplementation::compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
8630 quint32 *bpl, quint32 *byteSize,
8631 QSize *blockDim) const
8632{
8633 int xdim = 4;
8634 int ydim = 4;
8635 quint32 blockSize = 0;
8636
8637 switch (format) {
8638 case QRhiTexture::BC1:
8639 blockSize = 8;
8640 break;
8641 case QRhiTexture::BC2:
8642 blockSize = 16;
8643 break;
8644 case QRhiTexture::BC3:
8645 blockSize = 16;
8646 break;
8647 case QRhiTexture::BC4:
8648 blockSize = 8;
8649 break;
8650 case QRhiTexture::BC5:
8651 blockSize = 16;
8652 break;
8653 case QRhiTexture::BC6H:
8654 blockSize = 16;
8655 break;
8656 case QRhiTexture::BC7:
8657 blockSize = 16;
8658 break;
8659
8660 case QRhiTexture::ETC2_RGB8:
8661 blockSize = 8;
8662 break;
8663 case QRhiTexture::ETC2_RGB8A1:
8664 blockSize = 8;
8665 break;
8666 case QRhiTexture::ETC2_RGBA8:
8667 blockSize = 16;
8668 break;
8669
8670 case QRhiTexture::ASTC_4x4:
8671 blockSize = 16;
8672 break;
8673 case QRhiTexture::ASTC_5x4:
8674 blockSize = 16;
8675 xdim = 5;
8676 break;
8677 case QRhiTexture::ASTC_5x5:
8678 blockSize = 16;
8679 xdim = ydim = 5;
8680 break;
8681 case QRhiTexture::ASTC_6x5:
8682 blockSize = 16;
8683 xdim = 6;
8684 ydim = 5;
8685 break;
8686 case QRhiTexture::ASTC_6x6:
8687 blockSize = 16;
8688 xdim = ydim = 6;
8689 break;
8690 case QRhiTexture::ASTC_8x5:
8691 blockSize = 16;
8692 xdim = 8;
8693 ydim = 5;
8694 break;
8695 case QRhiTexture::ASTC_8x6:
8696 blockSize = 16;
8697 xdim = 8;
8698 ydim = 6;
8699 break;
8700 case QRhiTexture::ASTC_8x8:
8701 blockSize = 16;
8702 xdim = ydim = 8;
8703 break;
8704 case QRhiTexture::ASTC_10x5:
8705 blockSize = 16;
8706 xdim = 10;
8707 ydim = 5;
8708 break;
8709 case QRhiTexture::ASTC_10x6:
8710 blockSize = 16;
8711 xdim = 10;
8712 ydim = 6;
8713 break;
8714 case QRhiTexture::ASTC_10x8:
8715 blockSize = 16;
8716 xdim = 10;
8717 ydim = 8;
8718 break;
8719 case QRhiTexture::ASTC_10x10:
8720 blockSize = 16;
8721 xdim = ydim = 10;
8722 break;
8723 case QRhiTexture::ASTC_12x10:
8724 blockSize = 16;
8725 xdim = 12;
8726 ydim = 10;
8727 break;
8728 case QRhiTexture::ASTC_12x12:
8729 blockSize = 16;
8730 xdim = ydim = 12;
8731 break;
8732
8733 default:
8734 Q_UNREACHABLE();
8735 break;
8736 }
8737
8738 const quint32 wblocks = quint32((qint64(qMax(0, size.width())) + xdim - 1) / xdim);
8739 const quint32 hblocks = quint32((qint64(qMax(0, size.height())) + ydim - 1) / ydim);
8740
8741 if (blockDim)
8742 *blockDim = QSize(xdim, ydim);
8743
8744 // Compute in 64-bit, as safety for extreme geometry that would not fit.
8745 // wblocks and hblocks are at most 2^29 and blockSize at most 16.
8746 const quint64 bytesPerLine = quint64(wblocks) * quint64(blockSize);
8747 const quint64 totalSize = quint64(wblocks) * quint64(hblocks) * quint64(blockSize);
8748 if (bytesPerLine > std::numeric_limits<quint32>::max()
8749 || totalSize > std::numeric_limits<quint32>::max())
8750 {
8751 qWarning("Compressed texture of size %dx%d with format %d has a byte size of %llu "
8752 "which is too large to be handled",
8753 size.width(), size.height(), int(format), totalSize);
8754 if (bpl)
8755 *bpl = 0;
8756 if (byteSize)
8757 *byteSize = 0;
8758 return false;
8759 }
8760
8761 if (bpl)
8762 *bpl = quint32(bytesPerLine);
8763 if (byteSize)
8764 *byteSize = quint32(totalSize);
8765
8766 return true;
8767}
8768
8769bool QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSize &size,
8770 quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const
8771{
8772 if (isCompressedFormat(format))
8773 return compressedFormatInfo(format, size, bpl, byteSize, nullptr);
8774
8775 quint32 bpc = 0;
8776 switch (format) {
8777 case QRhiTexture::RGBA8:
8778 bpc = 4;
8779 break;
8780 case QRhiTexture::BGRA8:
8781 bpc = 4;
8782 break;
8783 case QRhiTexture::R8:
8784 bpc = 1;
8785 break;
8786 case QRhiTexture::RG8:
8787 bpc = 2;
8788 break;
8789 case QRhiTexture::R16:
8790 bpc = 2;
8791 break;
8792 case QRhiTexture::RG16:
8793 bpc = 4;
8794 break;
8795 case QRhiTexture::RED_OR_ALPHA8:
8796 bpc = 1;
8797 break;
8798
8799 case QRhiTexture::RGBA16F:
8800 bpc = 8;
8801 break;
8802 case QRhiTexture::RGBA32F:
8803 bpc = 16;
8804 break;
8805 case QRhiTexture::R16F:
8806 bpc = 2;
8807 break;
8808 case QRhiTexture::R32F:
8809 bpc = 4;
8810 break;
8811
8812 case QRhiTexture::RGB10A2:
8813 bpc = 4;
8814 break;
8815
8816 case QRhiTexture::D16:
8817 bpc = 2;
8818 break;
8819 case QRhiTexture::D24:
8820 case QRhiTexture::D24S8:
8821 case QRhiTexture::D32F:
8822 bpc = 4;
8823 break;
8824
8825 case QRhiTexture::D32FS8:
8826 bpc = 8;
8827 break;
8828
8829 case QRhiTexture::R8SI:
8830 case QRhiTexture::R8UI:
8831 bpc = 1;
8832 break;
8833 case QRhiTexture::R32SI:
8834 case QRhiTexture::R32UI:
8835 bpc = 4;
8836 break;
8837 case QRhiTexture::RG32SI:
8838 case QRhiTexture::RG32UI:
8839 bpc = 8;
8840 break;
8841 case QRhiTexture::RGBA32SI:
8842 case QRhiTexture::RGBA32UI:
8843 bpc = 16;
8844 break;
8845
8846 default:
8847 Q_UNREACHABLE();
8848 break;
8849 }
8850
8851 const quint32 width = uint(qMax(0, size.width()));
8852 const quint32 height = uint(qMax(0, size.height()));
8853
8854 if (bytesPerPixel)
8855 *bytesPerPixel = bpc;
8856
8857 // Compute in 64-bit, as safety for extreme geometry that would not fit.
8858 const quint64 bytesPerLine = quint64(width) * quint64(bpc);
8859 const quint64 pixelCount = quint64(width) * quint64(height);
8860 if (bytesPerLine > std::numeric_limits<quint32>::max()
8861 || pixelCount > std::numeric_limits<quint32>::max() / bpc)
8862 {
8863 qWarning("Texture of size %dx%d with format %d has a byte size "
8864 "which is too large to be handled",
8865 size.width(), size.height(), int(format));
8866 if (bpl)
8867 *bpl = 0;
8868 if (byteSize)
8869 *byteSize = 0;
8870 return false;
8871 }
8872
8873 if (bpl)
8874 *bpl = quint32(bytesPerLine);
8875 if (byteSize)
8876 *byteSize = quint32(pixelCount * quint64(bpc));
8877
8878 return true;
8879}
8880
8881bool QRhiImplementation::isStencilSupportingFormat(QRhiTexture::Format format) const
8882{
8883 switch (format) {
8884 case QRhiTexture::D24S8:
8885 case QRhiTexture::D32FS8:
8886 return true;
8887 default:
8888 break;
8889 }
8890 return false;
8891}
8892
8893bool QRhiImplementation::sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps)
8894{
8895 if (ps->cbeginShaderStages() == ps->cendShaderStages()) {
8896 qWarning("Cannot build a graphics pipeline without any stages");
8897 return false;
8898 }
8899
8900 bool hasVertexStage = false;
8901 for (auto it = ps->cbeginShaderStages(), itEnd = ps->cendShaderStages(); it != itEnd; ++it) {
8902 if (!it->shader().isValid()) {
8903 qWarning("Empty shader passed to graphics pipeline");
8904 return false;
8905 }
8906 if (it->type() == QRhiShaderStage::Vertex)
8907 hasVertexStage = true;
8908 }
8909 if (!hasVertexStage) {
8910 qWarning("Cannot build a graphics pipeline without a vertex stage");
8911 return false;
8912 }
8913
8914 if (!ps->renderPassDescriptor()) {
8915 qWarning("Cannot build a graphics pipeline without a QRhiRenderPassDescriptor");
8916 return false;
8917 }
8918
8919 if (!ps->shaderResourceBindings()) {
8920 qWarning("Cannot build a graphics pipeline without QRhiShaderResourceBindings");
8921 return false;
8922 }
8923
8924 return true;
8925}
8926
8927bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb)
8928{
8929#ifndef QT_NO_DEBUG
8930 bool bindingsOk = true;
8931 const int CHECKED_BINDINGS_COUNT = 64;
8932 bool bindingSeen[CHECKED_BINDINGS_COUNT] = {};
8933 for (auto it = srb->cbeginBindings(), end = srb->cendBindings(); it != end; ++it) {
8934 const int binding = shaderResourceBindingData(*it)->binding;
8935 if (binding >= CHECKED_BINDINGS_COUNT)
8936 continue;
8937 if (binding < 0) {
8938 qWarning("Invalid binding number %d", binding);
8939 bindingsOk = false;
8940 continue;
8941 }
8942 switch (shaderResourceBindingData(*it)->type) {
8943 case QRhiShaderResourceBinding::UniformBuffer:
8944 if (!bindingSeen[binding]) {
8945 bindingSeen[binding] = true;
8946 } else {
8947 qWarning("Uniform buffer duplicates an existing binding number %d", binding);
8948 bindingsOk = false;
8949 }
8950 break;
8951 case QRhiShaderResourceBinding::SampledTexture:
8952 if (!bindingSeen[binding]) {
8953 bindingSeen[binding] = true;
8954 } else {
8955 qWarning("Combined image sampler duplicates an existing binding number %d", binding);
8956 bindingsOk = false;
8957 }
8958 break;
8959 case QRhiShaderResourceBinding::Texture:
8960 if (!bindingSeen[binding]) {
8961 bindingSeen[binding] = true;
8962 } else {
8963 qWarning("Texture duplicates an existing binding number %d", binding);
8964 bindingsOk = false;
8965 }
8966 break;
8967 case QRhiShaderResourceBinding::Sampler:
8968 if (!bindingSeen[binding]) {
8969 bindingSeen[binding] = true;
8970 } else {
8971 qWarning("Sampler duplicates an existing binding number %d", binding);
8972 bindingsOk = false;
8973 }
8974 break;
8975 case QRhiShaderResourceBinding::ImageLoad:
8976 case QRhiShaderResourceBinding::ImageStore:
8977 case QRhiShaderResourceBinding::ImageLoadStore:
8978 if (!bindingSeen[binding]) {
8979 bindingSeen[binding] = true;
8980 } else {
8981 qWarning("Image duplicates an existing binding number %d", binding);
8982 bindingsOk = false;
8983 }
8984 break;
8985 case QRhiShaderResourceBinding::BufferLoad:
8986 case QRhiShaderResourceBinding::BufferStore:
8987 case QRhiShaderResourceBinding::BufferLoadStore:
8988 if (!bindingSeen[binding]) {
8989 bindingSeen[binding] = true;
8990 } else {
8991 qWarning("Buffer duplicates an existing binding number %d", binding);
8992 bindingsOk = false;
8993 }
8994 break;
8995 default:
8996 qWarning("Unknown binding type %d", int(shaderResourceBindingData(*it)->type));
8997 bindingsOk = false;
8998 break;
8999 }
9000 }
9001
9002 if (!bindingsOk) {
9003 qWarning() << *srb;
9004 return false;
9005 }
9006#else
9007 Q_UNUSED(srb);
9008#endif
9009 return true;
9010}
9011
9012bool QRhiImplementation::sanityCheckResourceOwnership(QRhiResource *maybeResource)
9013{
9014 if (maybeResource == nullptr || maybeResource->m_rhi == nullptr)
9015 return true;
9016
9017 if (maybeResource->m_rhi->q != q) {
9018 qWarning("%s %p (%s) belongs to QRhi %p, but client code attempted to use it with QRhi %p. This is wrong.",
9019 resourceTypeStr(maybeResource),
9020 maybeResource,
9021 maybeResource->m_objectName.constData(),
9022 maybeResource->m_rhi->q,
9023 q);
9024 return false;
9025 }
9026
9027 return true;
9028}
9029
9030int QRhiImplementation::effectiveSampleCount(int sampleCount) const
9031{
9032 // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
9033 const int s = qBound(1, sampleCount, 64);
9034 const QList<int> supported = supportedSampleCounts();
9035 int result = 1;
9036
9037 // Stay compatible with Qt 5 in that requesting an unsupported sample count
9038 // is not an error (although we still do a categorized debug print about
9039 // this), and rather a supported value, preferably a close one, not just 1,
9040 // is used instead. This is actually deviating from Qt 5 as that performs a
9041 // clamping only and does not handle cases such as when sample count 2 is
9042 // not supported but 4 is. (OpenGL handles things like that gracefully,
9043 // other APIs may not, so improve this by picking the next largest, or in
9044 // absence of that, the largest value; this with the goal to not reduce
9045 // quality by rather picking a larger-than-requested value than a smaller one)
9046
9047 for (int i = 0, ie = supported.count(); i != ie; ++i) {
9048 // assumes the 'supported' list is sorted
9049 if (supported[i] >= s) {
9050 result = supported[i];
9051 break;
9052 }
9053 }
9054
9055 if (result != s) {
9056 if (result == 1 && !supported.isEmpty())
9057 result = supported.last();
9058 qCDebug(QRHI_LOG_INFO, "Attempted to set unsupported sample count %d, using %d instead",
9059 sampleCount, result);
9060 }
9061
9062 return result;
9063}
9064
9065/*!
9066 \internal
9067 */
9068QRhi::QRhi()
9069{
9070}
9071
9072/*!
9073 Destructor. Destroys the backend and releases resources.
9074 */
9075QRhi::~QRhi()
9076{
9077 if (!d)
9078 return;
9079
9080 d->runCleanup();
9081
9082 qDeleteAll(d->pendingDeleteResources);
9083 d->pendingDeleteResources.clear();
9084
9085 d->destroy();
9086 delete d;
9087}
9088
9089QRhiImplementation *QRhiImplementation::newInstance(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *importDevice)
9090{
9091 QRhiImplementation *d = nullptr;
9092
9093 switch (impl) {
9094 case QRhi::Null:
9095 d = new QRhiNull(static_cast<QRhiNullInitParams *>(params));
9096 break;
9097 case QRhi::Vulkan:
9098#if QT_CONFIG(vulkan)
9099 d = new QRhiVulkan(static_cast<QRhiVulkanInitParams *>(params),
9100 static_cast<QRhiVulkanNativeHandles *>(importDevice));
9101 break;
9102#else
9103 Q_UNUSED(importDevice);
9104 qWarning("This build of Qt has no Vulkan support");
9105 break;
9106#endif
9107 case QRhi::OpenGLES2:
9108#ifndef QT_NO_OPENGL
9109 d = new QRhiGles2(static_cast<QRhiGles2InitParams *>(params),
9110 static_cast<QRhiGles2NativeHandles *>(importDevice));
9111 break;
9112#else
9113 qWarning("This build of Qt has no OpenGL support");
9114 break;
9115#endif
9116 case QRhi::D3D11:
9117#ifdef Q_OS_WIN
9118 d = new QRhiD3D11(static_cast<QRhiD3D11InitParams *>(params),
9119 static_cast<QRhiD3D11NativeHandles *>(importDevice));
9120 break;
9121#else
9122 qWarning("This platform has no Direct3D 11 support");
9123 break;
9124#endif
9125 case QRhi::Metal:
9126#if QT_CONFIG(metal)
9127 d = new QRhiMetal(static_cast<QRhiMetalInitParams *>(params),
9128 static_cast<QRhiMetalNativeHandles *>(importDevice));
9129 break;
9130#else
9131 qWarning("This platform has no Metal support");
9132 break;
9133#endif
9134 case QRhi::D3D12:
9135#ifdef Q_OS_WIN
9136#ifdef QRHI_D3D12_AVAILABLE
9137 d = new QRhiD3D12(static_cast<QRhiD3D12InitParams *>(params),
9138 static_cast<QRhiD3D12NativeHandles *>(importDevice));
9139 break;
9140#else
9141 qWarning("Qt was built without Direct3D 12 support. "
9142 "This is likely due to having ancient SDK headers (such as d3d12.h) in the Qt build environment. "
9143 "Rebuild Qt with an SDK supporting D3D12 features introduced in Windows 10 version 1703, "
9144 "or use an MSVC build as those typically are built with more up-to-date SDKs.");
9145 break;
9146#endif
9147#else
9148 qWarning("This platform has no Direct3D 12 support");
9149 break;
9150#endif
9151 }
9152
9153 return d;
9154}
9155
9156void QRhiImplementation::prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags, QRhiAdapter *adapter)
9157{
9158 q = rhi;
9159
9160 debugMarkers = flags.testFlag(QRhi::EnableDebugMarkers);
9161
9162 implType = impl;
9163 implThread = QThread::currentThread();
9164
9165 requestedRhiAdapter = adapter;
9166}
9167
9168QRhi::AdapterList QRhiImplementation::enumerateAdaptersBeforeCreate(QRhiNativeHandles *) const
9169{
9170 return {};
9171}
9172
9173/*!
9174 \overload
9175
9176 Equivalent to create(\a impl, \a params, \a flags, \a importDevice, \c nullptr).
9177 */
9178QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice)
9179{
9180 return create(impl, params, flags, importDevice, nullptr);
9181}
9182
9183/*!
9184 \return a new QRhi instance with a backend for the graphics API specified
9185 by \a impl with the specified \a flags. \return \c nullptr if the
9186 function fails.
9187
9188 \a params must point to an instance of one of the backend-specific
9189 subclasses of QRhiInitParams, such as, QRhiVulkanInitParams,
9190 QRhiMetalInitParams, QRhiD3D11InitParams, QRhiD3D12InitParams,
9191 QRhiGles2InitParams. See these classes for examples on creating a QRhi.
9192
9193 QRhi by design does not implement any fallback logic: if the specified API
9194 cannot be initialized, create() will fail, with warnings printed on the
9195 debug output by the backends. The clients of QRhi, for example Qt Quick,
9196 may however provide additional logic that allow falling back to an API
9197 different than what was requested, depending on the platform. If the
9198 intention is just to test if initialization would succeed when calling
9199 create() at later point, it is preferable to use probe() instead of
9200 create(), because with some backends probing can be implemented in a more
9201 lightweight manner as opposed to create(), which performs full
9202 initialization of the infrastructure and is wasteful if that QRhi instance
9203 is then thrown immediately away.
9204
9205 \a importDevice allows using an already existing graphics device, without
9206 QRhi creating its own. When not null, this parameter must point to an
9207 instance of one of the subclasses of QRhiNativeHandles:
9208 QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles,
9209 QRhiMetalNativeHandles, QRhiGles2NativeHandles. The exact details and
9210 semantics depend on the backand and the underlying graphics API.
9211
9212 Specifying a QRhiAdapter in \a adapter offers a transparent, cross-API
9213 alternative to passing in a \c VkPhysicalDevice via QRhiVulkanNativeHandles,
9214 or an adapter LUID via QRhiD3D12NativeHandles. The ownership of \a adapter
9215 is not taken. See enumerateAdapters() for more information on this approach.
9216
9217 \note \a importDevice and \a adapter cannot be both specified.
9218
9219 \sa probe()
9220 */
9221QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice, QRhiAdapter *adapter)
9222{
9223 if (adapter && importDevice)
9224 qWarning("adapter and importDevice should not both be non-null in QRhi::create()");
9225
9226 std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, importDevice));
9227 if (!rd)
9228 return nullptr;
9229
9230 std::unique_ptr<QRhi> r(new QRhi);
9231 r->d = rd.release();
9232 r->d->prepareForCreate(r.get(), impl, flags, adapter);
9233 if (!r->d->create(flags))
9234 return nullptr;
9235
9236 return r.release();
9237}
9238
9239/*!
9240 \return true if create() can be expected to succeed when called the given
9241 \a impl and \a params.
9242
9243 For some backends this is equivalent to calling create(), checking its
9244 return value, and then destroying the resulting QRhi.
9245
9246 For others, in particular with Metal, there may be a specific probing
9247 implementation, which allows testing in a more lightweight manner without
9248 polluting the debug output with warnings upon failures.
9249
9250 \sa create()
9251 */
9252bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)
9253{
9254 bool ok = false;
9255
9256 // The only place currently where this makes sense is Metal, where the API
9257 // is simple enough so that a special probing function - doing nothing but
9258 // a MTLCreateSystemDefaultDevice - is reasonable. Elsewhere, just call
9259 // create() and then drop the result.
9260
9261 if (impl == Metal) {
9262#if QT_CONFIG(metal)
9263 ok = QRhiMetal::probe(static_cast<QRhiMetalInitParams *>(params));
9264#endif
9265 } else {
9266 QRhi *rhi = create(impl, params);
9267 ok = rhi != nullptr;
9268 delete rhi;
9269 }
9270 return ok;
9271}
9272
9273/*!
9274 \typedef QRhi::AdapterList
9275 \relates QRhi
9276 \since 6.10
9277
9278 Synonym for QVector<QRhiAdapter *>.
9279*/
9280
9281/*!
9282 \return the list of adapters (physical devices) present, or an empty list
9283 when such control is not available with a given graphics API.
9284
9285 Backends where such level of control is not available, the returned list is
9286 always empty. Thus an empty list does not indicate there are no graphics
9287 devices in the system, but that fine-grained control over selecting which
9288 one to use is not available.
9289
9290 Backends for Direct 3D 11, Direct 3D 12, and Vulkan can be expected to fully
9291 support enumerating adapters. Others may not. The backend is specified by \a
9292 impl. A QRhiAdapter returned from this function must only be used in a
9293 create() call with the same \a impl. Some underlying APIs may present
9294 further limitations, with Vulkan in particular the QRhiAdapter is specified
9295 to the QVulkanInstance (\c VkInstance).
9296
9297 The caller is expected to destroy the QRhiAdapter objects in the list. Apart
9298 from querying \l{QRhiAdapter::}{info()}, the only purpose of these objects is
9299 to be passed on to create(), or the corresponding functions in higher layers
9300 such as Qt Quick.
9301
9302 The following snippet, written specifically for Vulkan, shows how to
9303 enumerate the available physical devices and request to create a QRhi for
9304 the chosen one. This in practice is equivalent to passing in a \c
9305 VkPhysicalDevice via a QRhiVulkanNativeHandles to create(), but it involves
9306 less API-specific code on the application side:
9307
9308 \code
9309 QRhiVulkanInitParams initParams;
9310 initParams.inst = &vulkanInstance;
9311 QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::Vulkan, &initParams);
9312 QRhiAdapter *chosenAdapter = nullptr;
9313 for (QRhiAdapter *adapter : adapters) {
9314 if (looksGood(adapter->info())) {
9315 chosenAdapter = adapter;
9316 break;
9317 }
9318 }
9319 QRhi *rhi = QRhi::create(QRhi::Vulkan, &initParams, {}, nullptr, chosenAdapter);
9320 qDeleteAll(adapters);
9321 \endcode
9322
9323 Passing in \a params is required due to some of the underlying graphics
9324 APIs' design. With Vulkan in particular, the QVulkanInstance must be
9325 provided, since enumerating is not possible without it. Other fields in the
9326 backend-specific \a params will not actually be used by this function.
9327
9328 \a nativeHandles is optional. When specified, it must be a valid
9329 QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, or QRhiVulkanNativeHandles,
9330 similarly to create(). However, unlike create(), only the physical device
9331 (in case of Vulkan) or the adapter LUID (in case of D3D) fields are used,
9332 all other fields are ignored. This can be used the restrict the results to a
9333 given adapter. The returned list will contain 1 or 0 elements in this case.
9334
9335 Note how in the previous code snippet the looksGood() function
9336 implementation cannot perform any platform-specific filtering based on the
9337 true adapter / physical device identity, such as the adapter LUID on Windows
9338 or the VkPhysicalDevice with Vulkan. This is because QRhiDriverInfo does not
9339 contain platform-specific data. Instead, use \a nativeHandles to get the
9340 results filtered already inside enumerateAdapters().
9341
9342 The following two snippets, using Direct 3D 12 as an example, are equivalent
9343 in practice:
9344
9345 \code
9346 // enumerateAdapters-based approach from Qt 6.10 on
9347 QRhiD3D12InitParams initParams;
9348 QRhiD3D12NativeHandles nativeHandles;
9349 nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
9350 nativeHandles.adapterLuidHigh = luid.HighPart;
9351 QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::D3D12, &initParams, &nativeHandles);
9352 if (adapters.isEmpty()) { qWarning("Requested adapter was not found"); }
9353 QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, nullptr, adapters[0]);
9354 qDeleteAll(adapters);
9355 \endcode
9356
9357 \code
9358 // traditional approach, more lightweight
9359 QRhiD3D12InitParams initParams;
9360 QRhiD3D12NativeHandles nativeHandles;
9361 nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
9362 nativeHandles.adapterLuidHigh = luid.HighPart;
9363 QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, &nativeHandles, nullptr);
9364 \endcode
9365
9366 \since 6.10
9367 \sa create()
9368 */
9369QRhi::AdapterList QRhi::enumerateAdapters(Implementation impl, QRhiInitParams *params, QRhiNativeHandles *nativeHandles)
9370{
9371 std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, nullptr));
9372 if (!rd)
9373 return {};
9374
9375 return rd->enumerateAdaptersBeforeCreate(nativeHandles);
9376}
9377
9378/*!
9379 \struct QRhiSwapChainProxyData
9380 \inmodule QtGuiPrivate
9381 \inheaderfile rhi/qrhi.h
9382 \since 6.6
9383
9384 \brief Opaque data describing native objects needed to set up a swapchain.
9385
9386 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9387 for details.
9388
9389 \sa QRhi::updateSwapChainProxyData()
9390 */
9391
9392/*!
9393 Generates and returns a QRhiSwapChainProxyData struct containing opaque
9394 data specific to the backend and graphics API specified by \a impl. \a
9395 window is the QWindow a swapchain is targeting.
9396
9397 The returned struct can be passed to QRhiSwapChain::setProxyData(). This
9398 makes sense in threaded rendering systems: this static function is expected
9399 to be called on the \b{main (gui) thread}, unlike all QRhi operations, then
9400 transferred to the thread working with the QRhi and QRhiSwapChain and passed
9401 on to the swapchain. This allows doing native platform queries that are
9402 only safe to be called on the main thread, for example to query the
9403 CAMetalLayer from a NSView, and then passing on the data to the
9404 QRhiSwapChain living on the rendering thread. With the Metal example, doing
9405 the view.layer access on a dedicated rendering thread causes a warning in
9406 the Xcode Thread Checker. With the data proxy mechanism, this is avoided.
9407
9408 When threads are not involved, generating and passing on the
9409 QRhiSwapChainProxyData is not required: backends are guaranteed to be able
9410 to query whatever is needed on their own, and if everything lives on the
9411 main (gui) thread, that should be sufficient.
9412
9413 \note \a impl should match what the QRhi is created with. For example,
9414 calling with QRhi::Metal on a non-Apple platform will not generate any
9415 useful data.
9416 */
9417QRhiSwapChainProxyData QRhi::updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)
9418{
9419#if QT_CONFIG(metal)
9420 if (impl == Metal)
9421 return QRhiMetal::updateSwapChainProxyData(window);
9422#else
9423 Q_UNUSED(impl);
9424 Q_UNUSED(window);
9425#endif
9426 return {};
9427}
9428
9429/*!
9430 \return the backend type for this QRhi.
9431 */
9432QRhi::Implementation QRhi::backend() const
9433{
9434 return d->implType;
9435}
9436
9437/*!
9438 \return a friendly name for the backend \a impl, usually the name of the 3D
9439 API in use.
9440 */
9441const char *QRhi::backendName(Implementation impl)
9442{
9443 switch (impl) {
9444 case QRhi::Null:
9445 return "Null";
9446 case QRhi::Vulkan:
9447 return "Vulkan";
9448 case QRhi::OpenGLES2:
9449 return "OpenGL";
9450 case QRhi::D3D11:
9451 return "D3D11";
9452 case QRhi::Metal:
9453 return "Metal";
9454 case QRhi::D3D12:
9455 return "D3D12";
9456 }
9457
9458 Q_UNREACHABLE_RETURN("Unknown");
9459}
9460
9461/*!
9462 \return the backend type as string for this QRhi.
9463 */
9464const char *QRhi::backendName() const
9465{
9466 return backendName(d->implType);
9467}
9468
9469/*!
9470 \enum QRhiDriverInfo::DeviceType
9471 Specifies the graphics device's type, when the information is available.
9472
9473 In practice this is only applicable with Vulkan and Metal. With Direct 3D
9474 11 and 12, using an adapter with the software flag set leads to the value
9475 \c CpuDevice. Otherwise, and with OpenGL, the value is always UnknownDevice.
9476
9477 \value UnknownDevice
9478 \value IntegratedDevice
9479 \value DiscreteDevice
9480 \value ExternalDevice
9481 \value VirtualDevice
9482 \value CpuDevice
9483*/
9484
9485/*!
9486 \struct QRhiDriverInfo
9487 \inmodule QtGuiPrivate
9488 \inheaderfile rhi/qrhi.h
9489 \since 6.6
9490
9491 \brief Describes the physical device, adapter, or graphics API
9492 implementation that is used by an initialized QRhi.
9493
9494 Graphics APIs offer different levels and kinds of information. The only
9495 value that is available across all APIs is the deviceName, which is a
9496 freetext description of the physical device, adapter, or is a combination
9497 of the strings reported for \c{GL_VENDOR} + \c{GL_RENDERER} +
9498 \c{GL_VERSION}. The deviceId is always 0 for OpenGL. vendorId is always 0
9499 for OpenGL and Metal. deviceType is always UnknownDevice for OpenGL and
9500 Direct 3D.
9501
9502 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9503 for details.
9504 */
9505
9506/*!
9507 \variable QRhiDriverInfo::deviceName
9508
9509 \sa QRhi::driverInfo()
9510*/
9511
9512/*!
9513 \variable QRhiDriverInfo::deviceId
9514
9515 \sa QRhi::driverInfo()
9516*/
9517
9518/*!
9519 \variable QRhiDriverInfo::vendorId
9520
9521 \sa QRhi::driverInfo()
9522*/
9523
9524/*!
9525 \variable QRhiDriverInfo::deviceType
9526
9527 \sa QRhi::driverInfo(), QRhiDriverInfo::DeviceType
9528*/
9529
9530#ifndef QT_NO_DEBUG_STREAM
9531static inline const char *deviceTypeStr(QRhiDriverInfo::DeviceType type)
9532{
9533 switch (type) {
9534 case QRhiDriverInfo::UnknownDevice:
9535 return "Unknown";
9536 case QRhiDriverInfo::IntegratedDevice:
9537 return "Integrated";
9538 case QRhiDriverInfo::DiscreteDevice:
9539 return "Discrete";
9540 case QRhiDriverInfo::ExternalDevice:
9541 return "External";
9542 case QRhiDriverInfo::VirtualDevice:
9543 return "Virtual";
9544 case QRhiDriverInfo::CpuDevice:
9545 return "Cpu";
9546 }
9547
9548 Q_UNREACHABLE_RETURN(nullptr);
9549}
9550QDebug operator<<(QDebug dbg, const QRhiDriverInfo &info)
9551{
9552 QDebugStateSaver saver(dbg);
9553 dbg.nospace() << "QRhiDriverInfo(deviceName=" << info.deviceName
9554 << " deviceId=0x" << Qt::hex << info.deviceId
9555 << " vendorId=0x" << info.vendorId
9556 << " deviceType=" << deviceTypeStr(info.deviceType)
9557 << ')';
9558 return dbg;
9559}
9560#endif
9561
9562/*!
9563 \return metadata for the graphics device used by this successfully
9564 initialized QRhi instance.
9565 */
9566QRhiDriverInfo QRhi::driverInfo() const
9567{
9568 return d->driverInfo();
9569}
9570
9571/*!
9572 \class QRhiAdapter
9573 \inmodule QtGuiPrivate
9574 \inheaderfile rhi/qrhi.h
9575 \since 6.10
9576
9577 \brief Represents a physical graphics device.
9578
9579 Some QRhi backends target graphics APIs that expose the concept of \c
9580 adapters or \c{physical devices}. Call the static \l
9581 {QRhi::}{enumerateAdapters()} function to retrieve a list of the adapters
9582 present in the system. Pass one of the returned QRhiAdapter objects to \l
9583 {QRhi::}{create()} in order to request using the adapter or physical device
9584 the QRhiAdapter corresponds to. Other than exposing the QRhiDriverInfo,
9585 QRhiAdapter is to be treated as an opaque handle.
9586
9587 \note With Vulkan, the QRhiAdapter is valid only as long as the
9588 QVulkanInstance that was used for \l{QRhi::}{enumerateAdapters()} is valid.
9589 This also means that a QRhiAdapter is tied to the Vulkan instance
9590 (QVulkanInstance, \c VkInstance) and cannot be used in the context of
9591 another Vulkan instance.
9592
9593 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9594 for details.
9595 */
9596
9597/*!
9598 \fn virtual QRhiDriverInfo QRhiAdapter::info() const = 0
9599
9600 \return the corresponding QRhiDriverInfo.
9601 */
9602
9603/*!
9604 \internal
9605 */
9606QRhiAdapter::~QRhiAdapter()
9607{
9608}
9609
9610/*!
9611 \return the thread on which the QRhi was \l{QRhi::create()}{initialized}.
9612 */
9613QThread *QRhi::thread() const
9614{
9615 return d->implThread;
9616}
9617
9618/*!
9619 Registers a \a callback that is invoked when the QRhi is destroyed.
9620
9621 The callback will run with the graphics resource still available, so this
9622 provides an opportunity for the application to cleanly release QRhiResource
9623 instances belonging to the QRhi. This is particularly useful for managing
9624 the lifetime of resources stored in \c cache type of objects, where the
9625 cache holds QRhiResources or objects containing QRhiResources.
9626
9627 \sa ~QRhi()
9628 */
9629void QRhi::addCleanupCallback(const CleanupCallback &callback)
9630{
9631 d->addCleanupCallback(callback);
9632}
9633
9634/*!
9635 \overload
9636
9637 Registers \a callback to be invoked when the QRhi is destroyed. This
9638 overload takes an opaque pointer, \a key, that is used to ensure that a
9639 given callback is registered (and so called) only once.
9640
9641 \sa removeCleanupCallback()
9642 */
9643void QRhi::addCleanupCallback(const void *key, const CleanupCallback &callback)
9644{
9645 d->addCleanupCallback(key, callback);
9646}
9647
9648/*!
9649 Deregisters the callback with \a key. If no cleanup callback was registered
9650 with \a key, the function does nothing. Callbacks registered without a key
9651 cannot be removed.
9652
9653 \sa addCleanupCallback()
9654 */
9655void QRhi::removeCleanupCallback(const void *key)
9656{
9657 d->removeCleanupCallback(key);
9658}
9659
9660void QRhiImplementation::runCleanup()
9661{
9662 for (const QRhi::CleanupCallback &f : std::as_const(cleanupCallbacks))
9663 f(q);
9664
9665 cleanupCallbacks.clear();
9666
9667 for (auto it = keyedCleanupCallbacks.cbegin(), end = keyedCleanupCallbacks.cend(); it != end; ++it)
9668 it.value()(q);
9669
9670 keyedCleanupCallbacks.clear();
9671}
9672
9673/*!
9674 \class QRhiResourceUpdateBatch
9675 \inmodule QtGuiPrivate
9676 \inheaderfile rhi/qrhi.h
9677 \since 6.6
9678 \brief Records upload and copy type of operations.
9679
9680 With QRhi it is no longer possible to perform copy type of operations at
9681 arbitrary times. Instead, all such operations are recorded into batches
9682 that are then passed, most commonly, to QRhiCommandBuffer::beginPass().
9683 What then happens under the hood is hidden from the application: the
9684 underlying implementations can defer and implement these operations in
9685 various different ways.
9686
9687 A resource update batch owns no graphics resources and does not perform any
9688 actual operations on its own. It should rather be viewed as a command
9689 buffer for update, upload, and copy type of commands.
9690
9691 To get an available, empty batch from the pool, call
9692 QRhi::nextResourceUpdateBatch().
9693
9694 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9695 for details.
9696 */
9697
9698/*!
9699 \internal
9700 */
9701QRhiResourceUpdateBatch::QRhiResourceUpdateBatch(QRhiImplementation *rhi)
9702 : d(new QRhiResourceUpdateBatchPrivate)
9703{
9704 d->q = this;
9705 d->rhi = rhi;
9706}
9707
9708QRhiResourceUpdateBatch::~QRhiResourceUpdateBatch()
9709{
9710 delete d;
9711}
9712
9713/*!
9714 \return the batch to the pool. This should only be used when the batch is
9715 not passed to one of QRhiCommandBuffer::beginPass(),
9716 QRhiCommandBuffer::endPass(), or QRhiCommandBuffer::resourceUpdate()
9717 because these implicitly call destroy().
9718
9719 \note QRhiResourceUpdateBatch instances must never by \c deleted by
9720 applications.
9721 */
9722void QRhiResourceUpdateBatch::release()
9723{
9724 d->free();
9725}
9726
9727/*!
9728 Copies all queued operations from the \a other batch into this one.
9729
9730 \note \a other may no longer contain valid data after the merge operation,
9731 and must not be submitted, but it will still need to be released by calling
9732 release().
9733
9734 This allows for a convenient pattern where resource updates that are
9735 already known during the initialization step are collected into a batch
9736 that is then merged into another when starting to first render pass later
9737 on:
9738
9739 \code
9740 void init()
9741 {
9742 initialUpdates = rhi->nextResourceUpdateBatch();
9743 initialUpdates->uploadStaticBuffer(vbuf, vertexData);
9744 initialUpdates->uploadStaticBuffer(ibuf, indexData);
9745 // ...
9746 }
9747
9748 void render()
9749 {
9750 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
9751 if (initialUpdates) {
9752 resUpdates->merge(initialUpdates);
9753 initialUpdates->release();
9754 initialUpdates = nullptr;
9755 }
9756 // resUpdates->updateDynamicBuffer(...);
9757 cb->beginPass(rt, clearCol, clearDs, resUpdates);
9758 }
9759 \endcode
9760 */
9761void QRhiResourceUpdateBatch::merge(QRhiResourceUpdateBatch *other)
9762{
9763 d->merge(other->d);
9764}
9765
9766/*!
9767 \return true until the number of buffer and texture operations enqueued
9768 onto this batch is below a reasonable limit.
9769
9770 The return value is false when the number of buffer and/or texture
9771 operations added to this batch have reached, or are about to reach, a
9772 certain limit. The batch is fully functional afterwards as well, but may
9773 need to allocate additional memory. Therefore, a renderer that collects
9774 lots of buffer and texture updates in a single batch when preparing a frame
9775 may want to consider \l{QRhiCommandBuffer::resourceUpdate()}{submitting the
9776 batch} and \l{QRhi::nextResourceUpdateBatch()}{starting a new one} when
9777 this function returns false.
9778 */
9779bool QRhiResourceUpdateBatch::hasOptimalCapacity() const
9780{
9781 return d->hasOptimalCapacity();
9782}
9783
9784/*!
9785 Enqueues updating a region of a QRhiBuffer \a buf created with the type
9786 QRhiBuffer::Dynamic.
9787
9788 The region is specified \a offset and \a size. The actual bytes to write
9789 are specified by \a data which must have at least \a size bytes available.
9790
9791 \a data is copied and can safely be destroyed or changed once this function
9792 returns.
9793
9794 \note If host writes are involved, which is the case with
9795 updateDynamicBuffer() typically as such buffers are backed by host visible
9796 memory with most backends, they may accumulate within a frame. Thus pass 1
9797 reading a region changed by a batch passed to pass 2 may see the changes
9798 specified in pass 2's update batch.
9799
9800 \note QRhi transparently manages double buffering in order to prevent
9801 stalling the graphics pipeline. The fact that a QRhiBuffer may have
9802 multiple native buffer objects underneath can be safely ignored when using
9803 the QRhi and QRhiResourceUpdateBatch.
9804 */
9805void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
9806{
9807 if (size > 0) {
9808 const int idx = d->activeBufferOpCount++;
9809 const int opListSize = d->bufferOps.size();
9810 if (idx < opListSize)
9811 QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, size, data);
9812 else
9813 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, size, data));
9814 }
9815}
9816
9817/*!
9818 \overload
9819 \since 6.10
9820
9821 Enqueues updating a region of a QRhiBuffer \a buf created with the type
9822 QRhiBuffer::Dynamic.
9823
9824 \a data is moved into the batch instead of copied with this overload.
9825 */
9826void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
9827{
9828 if (!data.isEmpty()) {
9829 const int idx = d->activeBufferOpCount++;
9830 const int opListSize = d->bufferOps.size();
9831 if (idx < opListSize)
9832 QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, std::move(data));
9833 else
9834 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, std::move(data)));
9835 }
9836}
9837
9838/*!
9839 Enqueues updating a region of a QRhiBuffer \a buf created with the type
9840 QRhiBuffer::Immutable or QRhiBuffer::Static.
9841
9842 The region is specified \a offset and \a size. The actual bytes to write
9843 are specified by \a data which must have at least \a size bytes available.
9844
9845 \a data is copied and can safely be destroyed or changed once this function
9846 returns.
9847 */
9848void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
9849{
9850 if (size > 0) {
9851 const int idx = d->activeBufferOpCount++;
9852 if (idx < d->bufferOps.size())
9853 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, size, data);
9854 else
9855 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, size, data));
9856 }
9857}
9858
9859/*!
9860 \overload
9861 \since 6.10
9862
9863 Enqueues updating a region of a QRhiBuffer \a buf created with the type
9864 QRhiBuffer::Immutable or QRhiBuffer::Static.
9865
9866 \a data is moved into the batch instead of copied with this overload.
9867 */
9868void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
9869{
9870 if (!data.isEmpty()) {
9871 const int idx = d->activeBufferOpCount++;
9872 if (idx < d->bufferOps.size())
9873 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, std::move(data));
9874 else
9875 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, std::move(data)));
9876 }
9877}
9878
9879/*!
9880 \overload
9881
9882 Enqueues updating the entire QRhiBuffer \a buf created with the type
9883 QRhiBuffer::Immutable or QRhiBuffer::Static.
9884 */
9885void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *data)
9886{
9887 if (buf->size() > 0) {
9888 const int idx = d->activeBufferOpCount++;
9889 if (idx < d->bufferOps.size())
9890 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, 0, data);
9891 else
9892 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, 0, data));
9893 }
9894}
9895
9896/*!
9897 \overload
9898 \since 6.10
9899
9900 Enqueues updating the entire QRhiBuffer \a buf created with the type
9901 QRhiBuffer::Immutable or QRhiBuffer::Static.
9902
9903 \a data is moved into the batch instead of copied with this overload.
9904
9905 \a data size must equal the size of \a buf.
9906 */
9907void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, QByteArray data)
9908{
9909 if (buf->size() > 0 && quint32(data.size()) == buf->size()) {
9910 const int idx = d->activeBufferOpCount++;
9911 if (idx < d->bufferOps.size())
9912 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, std::move(data));
9913 else
9914 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, std::move(data)));
9915 }
9916}
9917
9918/*!
9919 Enqueues reading back a region of the QRhiBuffer \a buf. The size of the
9920 region is specified by \a size in bytes, \a offset is the offset in bytes
9921 to start reading from.
9922
9923 A readback is asynchronous. \a result contains a callback that is invoked
9924 when the operation has completed. The data is provided in
9925 QRhiReadbackResult::data. Upon successful completion that QByteArray
9926 will have a size equal to \a size. On failure the QByteArray will be empty.
9927
9928 \note Reading buffers with a usage different than QRhiBuffer::UniformBuffer
9929 is supported only when the QRhi::ReadBackNonUniformBuffer feature is
9930 reported as supported.
9931
9932 \note The asynchronous readback is guaranteed to have completed when one of
9933 the following conditions is met: \l{QRhi::finish()}{finish()} has been
9934 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
9935 including the frame that issued the readback operation, and the
9936 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
9937 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
9938 QRhi::MaxAsyncReadbackFrames.
9939
9940 \sa readBackTexture(), QRhi::isFeatureSupported(), QRhi::resourceLimit()
9941 */
9942void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
9943{
9944 const int idx = d->activeBufferOpCount++;
9945 if (idx < d->bufferOps.size())
9946 d->bufferOps[idx] = QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result);
9947 else
9948 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result));
9949}
9950
9951/*!
9952 Enqueues uploading the image data for one or more mip levels in one or more
9953 layers of the texture \a tex.
9954
9955 The details of the copy (source QImage or compressed texture data, regions,
9956 target layers and levels) are described in \a desc.
9957 */
9958void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
9959{
9960 if (desc.cbeginEntries() != desc.cendEntries()) {
9961 const int idx = d->activeTextureOpCount++;
9962 if (idx < d->textureOps.size())
9963 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc);
9964 else
9965 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc));
9966 }
9967}
9968
9969/*!
9970 Enqueues uploading the image data for mip level 0 of layer 0 of the texture
9971 \a tex.
9972
9973 \a tex must have an uncompressed format. Its format must also be compatible
9974 with the QImage::format() of \a image. The source data is given in \a
9975 image.
9976 */
9977void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &image)
9978{
9979 uploadTexture(tex,
9980 QRhiTextureUploadEntry(0, 0, QRhiTextureSubresourceUploadDescription(image)));
9981}
9982
9983/*!
9984 Enqueues a texture-to-texture copy operation from \a src into \a dst as
9985 described by \a desc.
9986
9987 \note The source texture \a src must be created with
9988 QRhiTexture::UsedAsTransferSource.
9989
9990 \note The format of the textures must match. With most graphics
9991 APIs the data is copied as-is without any format conversions. If
9992 \a dst and \a src are created with different formats, unspecified
9993 issues may arise.
9994 */
9995void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
9996{
9997 const int idx = d->activeTextureOpCount++;
9998 if (idx < d->textureOps.size())
9999 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc);
10000 else
10001 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc));
10002}
10003
10004/*!
10005 Enqueues a texture-to-host copy operation as described by \a rb.
10006
10007 Normally \a rb will specify a QRhiTexture as the source. However, when the
10008 swapchain in the current frame was created with
10009 QRhiSwapChain::UsedAsTransferSource, it can also be the source of the
10010 readback. For this, leave the texture set to null in \a rb.
10011
10012 Unlike other operations, the results here need to be processed by the
10013 application. Therefore, \a result provides not just the data but also a
10014 callback as operations on the batch are asynchronous by nature:
10015
10016 \code
10017 rhi->beginFrame(swapchain);
10018 cb->beginPass(swapchain->currentFrameRenderTarget(), colorClear, dsClear);
10019 // ...
10020 QRhiReadbackResult *rbResult = new QRhiReadbackResult;
10021 rbResult->completed = [rbResult] {
10022 {
10023 const QImage::Format fmt = QImage::Format_RGBA8888_Premultiplied; // fits QRhiTexture::RGBA8
10024 const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
10025 QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
10026 image.save("result.png");
10027 }
10028 delete rbResult;
10029 };
10030 QRhiResourceUpdateBatch *u = nextResourceUpdateBatch();
10031 QRhiReadbackDescription rb; // no texture -> uses the current backbuffer of sc
10032 u->readBackTexture(rb, rbResult);
10033 cb->endPass(u);
10034 rhi->endFrame(swapchain);
10035 \endcode
10036
10037 \note The texture must be created with QRhiTexture::UsedAsTransferSource.
10038
10039 \note Multisample textures cannot be read back.
10040
10041 \note The readback returns raw byte data, in order to allow the applications
10042 to interpret it in any way they see fit. Be aware of the blending settings
10043 of rendering code: if the blending is set up to rely on premultiplied alpha,
10044 the results of the readback must also be interpreted as Premultiplied.
10045
10046 \note When interpreting the resulting raw data, be aware that the readback
10047 happens with a byte ordered format. A \l{QRhiTexture::RGBA8}{RGBA8} texture
10048 maps therefore to byte ordered QImage formats, such as,
10049 QImage::Format_RGBA8888.
10050
10051 \note The asynchronous readback is guaranteed to have completed when one of
10052 the following conditions is met: \l{QRhi::finish()}{finish()} has been
10053 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
10054 including the frame that issued the readback operation, and the
10055 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
10056 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
10057 QRhi::MaxAsyncReadbackFrames.
10058
10059 A single readback operation copies one mip level of one layer (cubemap face
10060 or 3D slice or texture array element) at a time. The level and layer are
10061 specified by the respective fields in \a rb.
10062
10063 \sa readBackBuffer(), QRhi::resourceLimit()
10064 */
10065void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
10066{
10067 const int idx = d->activeTextureOpCount++;
10068 if (idx < d->textureOps.size())
10069 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result);
10070 else
10071 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result));
10072}
10073
10074/*!
10075 Enqueues a mipmap generation operation for the specified texture \a tex.
10076
10077 2D and cube textures are supported. 1D and 3D textures are supported when
10078 the QRhi::OneDimensionalTextureMipmaps or QRhi::ThreeDimensionalTextureMipmaps
10079 feature is reported as supported, respectively.
10080
10081 \note The texture must be created with QRhiTexture::MipMapped and
10082 QRhiTexture::UsedWithGenerateMips.
10083
10084 \warning QRhi cannot guarantee that mipmaps can be generated for all
10085 supported texture formats. For example, QRhiTexture::RGBA32F is not a \c
10086 filterable format in OpenGL ES 3.0 and Metal on iOS, and therefore the
10087 mipmap generation request may fail. RGBA8 and RGBA16F are typically
10088 filterable, so it is recommended to use these formats when mipmap generation
10089 is desired.
10090 */
10091void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex)
10092{
10093 const int idx = d->activeTextureOpCount++;
10094 if (idx < d->textureOps.size())
10095 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex);
10096 else
10097 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex));
10098}
10099
10100/*!
10101 \return an available, empty batch to which copy type of operations can be
10102 recorded.
10103
10104 \note the return value is not owned by the caller and must never be
10105 destroyed. Instead, the batch is returned the pool for reuse by passing
10106 it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or
10107 QRhiCommandBuffer::resourceUpdate(), or by calling
10108 QRhiResourceUpdateBatch::release() on it.
10109
10110 \note Can be called outside beginFrame() - endFrame() as well since a batch
10111 instance just collects data on its own, it does not perform any operations.
10112
10113 Due to not being tied to a frame being recorded, the following sequence is
10114 valid for example:
10115
10116 \code
10117 rhi->beginFrame(swapchain);
10118 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
10119 u->uploadStaticBuffer(buf, data);
10120 // ... do not commit the batch
10121 rhi->endFrame();
10122 // u stays valid (assuming buf stays valid as well)
10123 rhi->beginFrame(swapchain);
10124 swapchain->currentFrameCommandBuffer()->resourceUpdate(u);
10125 // ... draw with buf
10126 rhi->endFrame();
10127 \endcode
10128
10129 \warning The maximum number of batches per QRhi is 64. When this limit is
10130 reached, the function will return null until a batch is returned to the
10131 pool.
10132 */
10133QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
10134{
10135 // By default we prefer spreading out the utilization of the worst case 64
10136 // (but typically 4) batches as much as possible, meaning we won't pick the
10137 // first one even if it's free, but prefer picking one after the last picked
10138 // one. Relevant due to implicit sharing (the backend may hold on to the
10139 // QRhiBufferData until frame no. current+FramesInFlight-1, but
10140 // implementations may vary), combined with the desire to reuse container
10141 // and QRhiBufferData allocations in bufferOps instead of flooding every
10142 // frame with allocs. See free(). In typical Qt Quick scenes this leads to
10143 // eventually seeding all 4 (or more) resource batches with buffer operation
10144 // data allocations which may (*) then be reused in subsequent frames. This
10145 // comes at the expense of using more memory, but has proven good results
10146 // when (CPU) profiling typical Quick/Quick3D apps.
10147 //
10148 // (*) Due to implicit sharing(ish), the exact behavior is unpredictable. If
10149 // a backend holds on to the QRhiBufferData for, e.g., a dynamic buffer
10150 // update, and then there is a new assign() for that same QRhiBufferData
10151 // while the refcount is still 2, it will "detach" (without contents) and
10152 // there is no reuse of the alloc. This is mitigated by the 'choose the one
10153 // afer the last picked one' logic when handing out batches.
10154
10155 auto nextFreeBatch = [this]() -> QRhiResourceUpdateBatch * {
10156 auto isFree = [this](int i) -> QRhiResourceUpdateBatch * {
10157 const quint64 mask = 1ULL << quint64(i);
10158 if (!(d->resUpdPoolMap & mask)) {
10159 d->resUpdPoolMap |= mask;
10160 QRhiResourceUpdateBatch *u = d->resUpdPool[i];
10161 QRhiResourceUpdateBatchPrivate::get(u)->poolIndex = i;
10162 d->lastResUpdIdx = i;
10163 return u;
10164 }
10165 return nullptr;
10166 };
10167 const int poolSize = d->resUpdPool.size();
10168 for (int i = d->lastResUpdIdx + 1; i < poolSize; ++i) {
10169 if (QRhiResourceUpdateBatch *u = isFree(i))
10170 return u;
10171 }
10172 for (int i = 0; i <= d->lastResUpdIdx; ++i) {
10173 if (QRhiResourceUpdateBatch *u = isFree(i))
10174 return u;
10175 }
10176 return nullptr;
10177 };
10178
10179 QRhiResourceUpdateBatch *u = nextFreeBatch();
10180 if (!u) {
10181 const int oldSize = d->resUpdPool.size();
10182 // 4, 8, 12, ..., up to 64
10183 const int newSize = oldSize + qMin(4, qMax(0, 64 - oldSize));
10184 d->resUpdPool.resize(newSize);
10185 for (int i = oldSize; i < newSize; ++i)
10186 d->resUpdPool[i] = new QRhiResourceUpdateBatch(d);
10187 u = nextFreeBatch();
10188 if (!u)
10189 qWarning("Resource update batch pool exhausted (max is 64)");
10190 }
10191
10192 return u;
10193}
10194
10196{
10197 Q_ASSERT(poolIndex >= 0 && rhi->resUpdPool[poolIndex] == q);
10198
10199 quint32 bufferDataTotal = 0;
10200 quint32 bufferLargeAllocTotal = 0;
10201 for (const BufferOp &op : std::as_const(bufferOps)) {
10202 bufferDataTotal += op.data.size();
10203 bufferLargeAllocTotal += op.data.largeAlloc(); // alloc when > 1 KB
10204 }
10205
10206 if (QRHI_LOG_RUB().isDebugEnabled()) {
10207 qDebug() << "[rub] release to pool upd.batch #" << poolIndex
10208 << "/ bufferOps active" << activeBufferOpCount
10209 << "of" << bufferOps.count()
10210 << "data" << bufferDataTotal
10211 << "largeAlloc" << bufferLargeAllocTotal
10212 << "textureOps active" << activeTextureOpCount
10213 << "of" << textureOps.count();
10214 }
10215
10218
10219 const quint64 mask = 1ULL << quint64(poolIndex);
10220 rhi->resUpdPoolMap &= ~mask;
10221 poolIndex = -1;
10222
10223 // textureOps is cleared, to not keep the potentially large image pixel
10224 // data alive, but it is expected that the container keeps the list alloc
10225 // at least. Only trimOpList() goes for the more aggressive route with squeeze.
10226 textureOps.clear();
10227
10228 // bufferOps is not touched in many cases, to allow reusing allocations
10229 // (incl. in the elements' QRhiBufferData) as much as possible when this
10230 // batch is used again in the future, which is important for performance, in
10231 // particular with Qt Quick where it is easy for scenes to produce lots of,
10232 // typically small buffer changes on every frame.
10233 //
10234 // However, ensure that even in the unlikely case of having the max number
10235 // of batches (64) created in resUpdPool, no more than 64 MB in total is
10236 // used up by buffer data just to help future reuse. For simplicity, if
10237 // there is more than 1 MB data -> clear. Applications with frequent, huge
10238 // buffer updates probably have other bottlenecks anyway.
10239 if (bufferLargeAllocTotal > 1024 * 1024)
10240 bufferOps.clear();
10241}
10242
10244{
10245 int combinedSize = activeBufferOpCount + other->activeBufferOpCount;
10246 if (bufferOps.size() < combinedSize)
10247 bufferOps.resize(combinedSize);
10248 for (int i = activeBufferOpCount; i < combinedSize; ++i)
10249 bufferOps[i] = std::move(other->bufferOps[i - activeBufferOpCount]);
10251
10252 combinedSize = activeTextureOpCount + other->activeTextureOpCount;
10253 if (textureOps.size() < combinedSize)
10254 textureOps.resize(combinedSize);
10255 for (int i = activeTextureOpCount; i < combinedSize; ++i)
10256 textureOps[i] = std::move(other->textureOps[i - activeTextureOpCount]);
10258}
10259
10265
10267{
10268 // Unlike free(), this is expected to aggressively deallocate all memory
10269 // used by both the buffer and texture operation lists. (i.e. using
10270 // squeeze() to only keep the stack prealloc of the QVLAs)
10271 //
10272 // This (e.g. just the destruction of bufferOps elements) may have a
10273 // non-negligible performance impact e.g. with Qt Quick with scenes where
10274 // there are lots of buffer operations per frame.
10275
10277 bufferOps.clear();
10278 bufferOps.squeeze();
10279
10281 textureOps.clear();
10282 textureOps.squeeze();
10283}
10284
10285/*!
10286 Sometimes committing resource updates is necessary or just more convenient
10287 without starting a render pass. Calling this function with \a
10288 resourceUpdates is an alternative to passing \a resourceUpdates to a
10289 beginPass() call (or endPass(), which would be typical in case of readbacks).
10290
10291 \note Cannot be called inside a pass.
10292 */
10293void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
10294{
10295 if (resourceUpdates)
10296 m_rhi->resourceUpdate(this, resourceUpdates);
10297}
10298
10299/*!
10300 Records starting a new render pass targeting the render target \a rt.
10301
10302 \a resourceUpdates, when not null, specifies a resource update batch that
10303 is to be committed and then released.
10304
10305 The color and depth/stencil buffers of the render target are normally
10306 cleared. The clear values are specified in \a colorClearValue and \a
10307 depthStencilClearValue. The exception is when the render target was created
10308 with QRhiTextureRenderTarget::PreserveColorContents and/or
10309 QRhiTextureRenderTarget::PreserveDepthStencilContents. The clear values are
10310 ignored then.
10311
10312 \note Enabling preserved color or depth contents leads to decreased
10313 performance depending on the underlying hardware. Mobile GPUs with tiled
10314 architecture benefit from not having to reload the previous contents into
10315 the tile buffer. Similarly, a QRhiTextureRenderTarget with a QRhiTexture as
10316 the depth buffer is less efficient than a QRhiRenderBuffer since using a
10317 depth texture triggers requiring writing the data out to it, while with
10318 renderbuffers this is not needed (as the API does not allow sampling or
10319 reading from a renderbuffer).
10320
10321 \note Do not assume that any state or resource bindings persist between
10322 passes.
10323
10324 \note The QRhiCommandBuffer's \c set and \c draw functions can only be
10325 called inside a pass. Also, with the exception of setGraphicsPipeline(),
10326 they expect to have a pipeline set already on the command buffer.
10327 Unspecified issues may arise otherwise, depending on the backend.
10328
10329 If \a rt is a QRhiTextureRenderTarget, beginPass() performs a check to see
10330 if the texture and renderbuffer objects referenced from the render target
10331 are up-to-date. This is similar to what setShaderResources() does for
10332 QRhiShaderResourceBindings. If any of the attachments had been rebuilt
10333 since QRhiTextureRenderTarget::create(), an implicit call to create() is
10334 made on \a rt. Therefore, if \a rt has a QRhiTexture color attachment \c
10335 texture, and one needs to make the texture a different size, the following
10336 is then valid:
10337 \code
10338 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ { texture } });
10339 rt->create();
10340 // ...
10341 texture->setPixelSize(new_size);
10342 texture->create();
10343 cb->beginPass(rt, colorClear, dsClear); // this is ok, no explicit rt->create() is required before
10344 \endcode
10345
10346 \a flags allow controlling certain advanced functionality. One commonly used
10347 flag is \c ExternalContents. This should be specified whenever
10348 beginExternal() will be called within the pass started by this function.
10349
10350 \sa endPass(), BeginPassFlags
10351 */
10352void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
10353 const QColor &colorClearValue,
10354 const QRhiDepthStencilClearValue &depthStencilClearValue,
10355 QRhiResourceUpdateBatch *resourceUpdates,
10356 BeginPassFlags flags)
10357{
10358 m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates, flags);
10359}
10360
10361/*!
10362 Records ending the current render pass.
10363
10364 \a resourceUpdates, when not null, specifies a resource update batch that
10365 is to be committed and then released.
10366
10367 \sa beginPass()
10368 */
10369void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates)
10370{
10371 m_rhi->endPass(this, resourceUpdates);
10372}
10373
10374/*!
10375 Records setting a new graphics pipeline \a ps.
10376
10377 \note This function must be called before recording other \c set or \c draw
10378 commands on the command buffer.
10379
10380 \note QRhi will optimize out unnecessary invocations within a pass, so
10381 therefore overoptimizing to avoid calls to this function is not necessary
10382 on the applications' side.
10383
10384 \note This function can only be called inside a render pass, meaning
10385 between a beginPass() and endPass() call.
10386
10387 \note The new graphics pipeline \a ps must be a valid pointer.
10388
10389 Setting a graphics pipeline that does not have the
10390 \l{QRhiGraphicsPipeline::}{UsesScissor} flag will either disable scissoring,
10391 with graphics APIs where that is applicable, or set the scissor rectangle to
10392 match the viewport that was last set (with graphics APIs where scissoring is
10393 effectively always active), in order to ensure a uniform behavior across QRhi
10394 backends.
10395 */
10396void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)
10397{
10398 Q_ASSERT(ps != nullptr);
10399 m_rhi->setGraphicsPipeline(this, ps);
10400}
10401
10402/*!
10403 Records binding a set of shader resources, such as, uniform buffers or
10404 textures, that are made visible to one or more shader stages.
10405
10406 \a srb can be null in which case the current graphics or compute pipeline's
10407 associated QRhiShaderResourceBindings is used. When \a srb is non-null, it
10408 must be
10409 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible},
10410 meaning the layout (number of bindings, the type and binding number of each
10411 binding) must fully match the QRhiShaderResourceBindings that was
10412 associated with the pipeline at the time of calling the pipeline's create().
10413
10414 There are cases when a seemingly unnecessary setShaderResources() call is
10415 mandatory: when rebuilding a resource referenced from \a srb, for example
10416 changing the size of a QRhiBuffer followed by a QRhiBuffer::create(), this
10417 is the place where associated native objects (such as descriptor sets in
10418 case of Vulkan) are updated to refer to the current native resources that
10419 back the QRhiBuffer, QRhiTexture, QRhiSampler objects referenced from \a
10420 srb. In this case setShaderResources() must be called even if \a srb is
10421 the same as in the last call.
10422
10423 When \a srb is not null, the QRhiShaderResourceBindings object the pipeline
10424 was built with in create() is guaranteed to be not accessed in any form. In
10425 fact, it does not need to be valid even at this point: destroying the
10426 pipeline's associated srb after create() and instead explicitly specifying
10427 another, \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout
10428 compatible} one in every setShaderResources() call is valid.
10429
10430 \a dynamicOffsets allows specifying buffer offsets for uniform buffers that
10431 were associated with \a srb via
10432 QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(). This is
10433 different from providing the offset in the \a srb itself: dynamic offsets
10434 do not require building a new QRhiShaderResourceBindings for every
10435 different offset, can avoid writing the underlying descriptors (with
10436 backends where applicable), and so they may be more efficient. Each element
10437 of \a dynamicOffsets is a \c binding - \c offset pair.
10438 \a dynamicOffsetCount specifies the number of elements in \a dynamicOffsets.
10439
10440 \note All offsets in \a dynamicOffsets must be byte aligned to the value
10441 returned from QRhi::ubufAlignment().
10442
10443 \note Some backends may limit the number of supported dynamic offsets.
10444 Avoid using a \a dynamicOffsetCount larger than 8.
10445
10446 \note QRhi will optimize out unnecessary invocations within a pass (taking
10447 the conditions described above into account), so therefore overoptimizing
10448 to avoid calls to this function is not necessary on the applications' side.
10449
10450 \note This function can only be called inside a render or compute pass,
10451 meaning between a beginPass() and endPass(), or beginComputePass() and
10452 endComputePass().
10453 */
10454void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb,
10455 int dynamicOffsetCount,
10456 const DynamicOffset *dynamicOffsets)
10457{
10458 m_rhi->setShaderResources(this, srb, dynamicOffsetCount, dynamicOffsets);
10459}
10460
10461/*!
10462 Records vertex input bindings.
10463
10464 The index buffer used by subsequent drawIndexed() commands is specified by
10465 \a indexBuf, \a indexOffset, and \a indexFormat. \a indexBuf can be set to
10466 null when indexed drawing is not needed.
10467
10468 Vertex buffer bindings are batched. \a startBinding specifies the first
10469 binding number. The recorded command then binds each buffer from \a
10470 bindings to the binding point \c{startBinding + i} where \c i is the index
10471 in \a bindings. Each element in \a bindings specifies a QRhiBuffer and an
10472 offset.
10473
10474 \note Some backends may limit the number of vertex buffer bindings. Avoid
10475 using a \a bindingCount larger than 8.
10476
10477 Superfluous vertex input and index changes in the same pass are ignored
10478 automatically with most backends and therefore applications do not need to
10479 overoptimize to avoid calls to this function.
10480
10481 \note This function can only be called inside a render pass, meaning
10482 between a beginPass() and endPass() call.
10483
10484 As a simple example, take a vertex shader with two inputs:
10485
10486 \badcode
10487 layout(location = 0) in vec4 position;
10488 layout(location = 1) in vec3 color;
10489 \endcode
10490
10491 and assume we have the data available in interleaved format, using only 2
10492 floats for position (so 5 floats per vertex: x, y, r, g, b). A QRhiGraphicsPipeline for
10493 this shader can then be created using the input layout:
10494
10495 \code
10496 QRhiVertexInputLayout inputLayout;
10497 inputLayout.setBindings({
10498 { 5 * sizeof(float) }
10499 });
10500 inputLayout.setAttributes({
10501 { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
10502 { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
10503 });
10504 \endcode
10505
10506 Here there is one buffer binding (binding number 0), with two inputs
10507 referencing it. When recording the pass, once the pipeline is set, the
10508 vertex bindings can be specified simply like the following, assuming vbuf
10509 is the QRhiBuffer with all the interleaved position+color data:
10510
10511 \code
10512 const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
10513 cb->setVertexInput(0, 1, &vbufBinding);
10514 \endcode
10515 */
10516void QRhiCommandBuffer::setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
10517 QRhiBuffer *indexBuf, quint32 indexOffset,
10518 IndexFormat indexFormat)
10519{
10520 m_rhi->setVertexInput(this, startBinding, bindingCount, bindings, indexBuf, indexOffset, indexFormat);
10521}
10522
10523/*!
10524 Records setting the active viewport rectangle specified in \a viewport.
10525
10526 With backends where the underlying graphics API has scissoring always
10527 enabled, this function also sets the scissor to match the viewport whenever
10528 the active QRhiGraphicsPipeline does not have
10529 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set.
10530
10531 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
10532 bottom-left.
10533
10534 \note This function can only be called inside a render pass, meaning
10535 between a beginPass() and endPass() call.
10536 */
10537void QRhiCommandBuffer::setViewport(const QRhiViewport &viewport)
10538{
10539 m_rhi->setViewport(this, viewport);
10540}
10541
10542/*!
10543 Records setting the active scissor rectangle specified in \a scissor.
10544
10545 This can only be called when the bound pipeline has
10546 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set. When the flag is
10547 set on the active pipeline, this function must be called because scissor
10548 testing will get enabled and so a scissor rectangle must be provided.
10549
10550 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
10551 bottom-left.
10552
10553 \note This function can only be called inside a render pass, meaning
10554 between a beginPass() and endPass() call.
10555 */
10556void QRhiCommandBuffer::setScissor(const QRhiScissor &scissor)
10557{
10558 m_rhi->setScissor(this, scissor);
10559}
10560
10561/*!
10562 Records setting the active blend constants to \a c.
10563
10564 This can only be called when the bound pipeline has
10565 QRhiGraphicsPipeline::UsesBlendConstants set.
10566
10567 \note This function can only be called inside a render pass, meaning
10568 between a beginPass() and endPass() call.
10569 */
10570void QRhiCommandBuffer::setBlendConstants(const QColor &c)
10571{
10572 m_rhi->setBlendConstants(this, c);
10573}
10574
10575/*!
10576 Records setting the active stencil reference value to \a refValue.
10577
10578 This can only be called when the bound pipeline has
10579 QRhiGraphicsPipeline::UsesStencilRef set.
10580
10581 \note This function can only be called inside a render pass, meaning between
10582 a beginPass() and endPass() call.
10583 */
10584void QRhiCommandBuffer::setStencilRef(quint32 refValue)
10585{
10586 m_rhi->setStencilRef(this, refValue);
10587}
10588
10589/*!
10590 Sets the shading rate for the following draw calls to \a coarsePixelSize.
10591
10592 The default is 1x1.
10593
10594 Functional only when the \l QRhi::VariableRateShading feature is reported as
10595 supported and the QRhiGraphicsPipeline(s) bound on the command buffer were
10596 declaring \l QRhiGraphicsPipeline::UsesShadingRate when creating them.
10597
10598 Call \l QRhi::supportedShadingRates() to check what shading rates are
10599 supported for a given sample count.
10600
10601 When both a QRhiShadingRateMap and this function are in use, the higher of
10602 the two shading rates is used for each tile. There is currently no control
10603 offered over the combiner behavior.
10604
10605 \since 6.9
10606 */
10607void QRhiCommandBuffer::setShadingRate(const QSize &coarsePixelSize)
10608{
10609 m_rhi->setShadingRate(this, coarsePixelSize);
10610}
10611
10612/*!
10613 Records a non-indexed draw.
10614
10615 The number of vertices is specified in \a vertexCount. For instanced
10616 drawing set \a instanceCount to a value other than 1. \a firstVertex is the
10617 index of the first vertex to draw. When drawing multiple instances, the
10618 first instance ID is specified by \a firstInstance.
10619
10620 \note \a firstInstance may not be supported, and is ignored when the
10621 QRhi::BaseInstance feature is reported as not supported. The first instance
10622 ID is always 0 in that case. QRhi::BaseInstance is never supported with
10623 OpenGL at the moment, mainly due to OpenGL ES limitations, and therefore
10624 portable applications should not be designed to rely on this argument.
10625
10626 \note Shaders that need to access the index of the current vertex or
10627 instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
10628 Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
10629 gl_InstanceID.
10630
10631 \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
10632 include the base value with some of the underlying 3D APIs. This is
10633 indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
10634 on a base instance value cannot be avoided, applications are advised to pass
10635 in the value as a uniform conditionally based on what that feature reports,
10636 and add it to \c gl_InstanceIndex in the shader.
10637
10638 \note This function can only be called inside a render pass, meaning
10639 between a beginPass() and endPass() call.
10640 */
10641void QRhiCommandBuffer::draw(quint32 vertexCount,
10642 quint32 instanceCount,
10643 quint32 firstVertex,
10644 quint32 firstInstance)
10645{
10646 m_rhi->draw(this, vertexCount, instanceCount, firstVertex, firstInstance);
10647}
10648
10649/*!
10650 Records an indexed draw.
10651
10652 The number of vertices is specified in \a indexCount. \a firstIndex is the
10653 base index. The effective offset in the index buffer is given by
10654 \c{indexOffset + firstIndex * n} where \c n is 2 or 4 depending on the
10655 index element type. \c indexOffset is specified in setVertexInput().
10656
10657 \note The effective offset in the index buffer must be 4 byte aligned with
10658 some backends (for example, Metal). With these backends the
10659 \l{QRhi::NonFourAlignedEffectiveIndexBufferOffset}{NonFourAlignedEffectiveIndexBufferOffset}
10660 feature will be reported as not-supported.
10661
10662 \a vertexOffset (also called \c{base vertex}) is a signed value that is
10663 added to the element index before indexing into the vertex buffer. Support
10664 for this is not always available, and the value is ignored when the feature
10665 QRhi::BaseVertex is reported as unsupported.
10666
10667 For instanced drawing set \a instanceCount to a value other than 1. When
10668 drawing multiple instances, the first instance ID is specified by \a
10669 firstInstance.
10670
10671 \note \a firstInstance may not be supported, and is ignored when the
10672 QRhi::BaseInstance feature is reported as not supported. The first instance
10673 ID is always 0 in that case. QRhi::BaseInstance is never supported with
10674 OpenGL at the moment, mainly due to OpenGL ES limitations, and therefore
10675 portable applications should not be designed to rely on this argument.
10676
10677 \note Shaders that need to access the index of the current vertex or
10678 instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
10679 Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
10680 gl_InstanceID.
10681
10682 \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
10683 include the base value with some of the underlying 3D APIs. This is
10684 indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
10685 on a base instance value cannot be avoided, applications are advised to pass
10686 in the value as a uniform conditionally based on what that feature reports,
10687 and add it to \c gl_InstanceIndex in the shader.
10688
10689 \note This function can only be called inside a render pass, meaning
10690 between a beginPass() and endPass() call.
10691 */
10692void QRhiCommandBuffer::drawIndexed(quint32 indexCount,
10693 quint32 instanceCount,
10694 quint32 firstIndex,
10695 qint32 vertexOffset,
10696 quint32 firstInstance)
10697{
10698 m_rhi->drawIndexed(this, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
10699}
10700
10701/*!
10702 Records a non-indexed, indirect draw.
10703
10704 The draw parameters are provided by the buffer specified in \a indirectBuffer,
10705 which must contain an array of elements of type QRhiIndirectDrawCommand.
10706 The parameters in QRhiIndirectDrawCommand have the same meaning as in draw().
10707
10708 The offset, in bytes, from which the parameters are read in the buffer is specified
10709 by \a indirectBufferOffset.
10710
10711 \a drawCount specifies the number of such draw commands to issue.
10712
10713 \a stride indicates the byte size of each individual draw command structure
10714 in the buffer. This allows interleaving custom data between commands if needed.
10715 The value must be a multiple of 4 and greater than or equal to sizeof(QRhiIndirectDrawCommand).
10716
10717 \note A \a drawCount value greater than 1 is only natively supported if the
10718 QRhi::DrawIndirectMulti feature is reported as supported and stride is the default.
10719 Otherwise, this function emulates multi-draw by recording multiple draw calls,
10720 offering no performance benefit over repeated draw() calls.
10721
10722 \note This function can only be called inside a render pass, meaning
10723 between a beginPass() and endPass() call.
10724
10725 \since 6.12
10726 */
10727void QRhiCommandBuffer::drawIndirect(QRhiBuffer *indirectBuffer,
10728 quint32 indirectBufferOffset,
10729 quint32 drawCount,
10730 quint32 stride)
10731{
10732 Q_ASSERT(indirectBuffer);
10733 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
10734 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
10735 Q_ASSERT(stride >= sizeof(QRhiIndirectDrawCommand));
10736 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
10737 m_rhi->drawIndirect(this, indirectBuffer, indirectBufferOffset, drawCount, stride);
10738}
10739
10740/*!
10741 Records an indexed, indirect draw.
10742
10743 The draw parameters are provided by the buffer specified in \a indirectBuffer,
10744 which must contain an array of elements of type QRhiIndexedIndirectDrawCommand.
10745 The parameters in QRhiIndexedIndirectDrawCommand have the same meaning as in drawIndexed().
10746
10747 The offset, in bytes, from which the parameters are read in the buffer is specified
10748 by \a indirectBufferOffset.
10749
10750 \a drawCount specifies the number of such draw commands to issue.
10751
10752 \a stride indicates the byte size of each individual draw command structure
10753 in the buffer. This allows interleaving custom data between commands if needed.
10754 The value must be a multiple of 4 and greater than or equal to sizeof(QRhiIndexedIndirectDrawCommand).
10755
10756 \note A \a drawCount value greater than 1 is only natively supported if the
10757 QRhi::DrawIndirectMulti feature is reported as supported and stride is the default.
10758 Otherwise, this function emulates multi-draw by recording multiple draw calls,
10759 offering no performance benefit over repeated drawIndexed() calls.
10760
10761 \note This function can only be called inside a render pass, meaning
10762 between a beginPass() and endPass() call.
10763
10764 \since 6.12
10765 */
10766void QRhiCommandBuffer::drawIndexedIndirect(QRhiBuffer *indirectBuffer,
10767 quint32 indirectBufferOffset,
10768 quint32 drawCount,
10769 quint32 stride)
10770{
10771 Q_ASSERT(indirectBuffer);
10772 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
10773 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
10774 Q_ASSERT(stride >= sizeof(QRhiIndexedIndirectDrawCommand));
10775 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
10776 m_rhi->drawIndexedIndirect(this, indirectBuffer, indirectBufferOffset, drawCount, stride);
10777}
10778
10779/*!
10780 Records a named debug group on the command buffer with the specified \a
10781 name. This is shown in graphics debugging tools such as
10782 \l{https://renderdoc.org/}{RenderDoc} and
10783 \l{https://developer.apple.com/xcode/}{XCode}. The end of the grouping is
10784 indicated by debugMarkEnd().
10785
10786 \note Ignored when QRhi::DebugMarkers are not supported or
10787 QRhi::EnableDebugMarkers is not set.
10788
10789 \note Can be called anywhere within the frame, both inside and outside of passes.
10790 */
10791void QRhiCommandBuffer::debugMarkBegin(const QByteArray &name)
10792{
10793 m_rhi->debugMarkBegin(this, name);
10794}
10795
10796/*!
10797 Records the end of a debug group.
10798
10799 \note Ignored when QRhi::DebugMarkers are not supported or
10800 QRhi::EnableDebugMarkers is not set.
10801
10802 \note Can be called anywhere within the frame, both inside and outside of passes.
10803 */
10804void QRhiCommandBuffer::debugMarkEnd()
10805{
10806 m_rhi->debugMarkEnd(this);
10807}
10808
10809/*!
10810 Inserts a debug message \a msg into the command stream.
10811
10812 \note Ignored when QRhi::DebugMarkers are not supported or
10813 QRhi::EnableDebugMarkers is not set.
10814
10815 \note With some backends debugMarkMsg() is only supported inside a pass and
10816 is ignored when called outside a pass. With others it is recorded anywhere
10817 within the frame.
10818 */
10819void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)
10820{
10821 m_rhi->debugMarkMsg(this, msg);
10822}
10823
10824/*!
10825 Records starting a new compute pass.
10826
10827 \a resourceUpdates, when not null, specifies a resource update batch that
10828 is to be committed and then released.
10829
10830 \note Do not assume that any state or resource bindings persist between
10831 passes.
10832
10833 \note A compute pass can record setComputePipeline(), setShaderResources(),
10834 and dispatch() calls, not graphics ones. General functionality, such as,
10835 debug markers and beginExternal() is available both in render and compute
10836 passes.
10837
10838 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
10839 is reported as supported.
10840
10841 \a flags is not currently used.
10842 */
10843void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates, BeginPassFlags flags)
10844{
10845 m_rhi->beginComputePass(this, resourceUpdates, flags);
10846}
10847
10848/*!
10849 Records ending the current compute pass.
10850
10851 \a resourceUpdates, when not null, specifies a resource update batch that
10852 is to be committed and then released.
10853 */
10854void QRhiCommandBuffer::endComputePass(QRhiResourceUpdateBatch *resourceUpdates)
10855{
10856 m_rhi->endComputePass(this, resourceUpdates);
10857}
10858
10859/*!
10860 Records setting a new compute pipeline \a ps.
10861
10862 \note This function must be called before recording setShaderResources() or
10863 dispatch() commands on the command buffer.
10864
10865 \note QRhi will optimize out unnecessary invocations within a pass, so
10866 therefore overoptimizing to avoid calls to this function is not necessary
10867 on the applications' side.
10868
10869 \note This function can only be called inside a compute pass, meaning
10870 between a beginComputePass() and endComputePass() call.
10871 */
10872void QRhiCommandBuffer::setComputePipeline(QRhiComputePipeline *ps)
10873{
10874 m_rhi->setComputePipeline(this, ps);
10875}
10876
10877/*!
10878 Records dispatching compute work items, with \a x, \a y, and \a z
10879 specifying the number of local workgroups in the corresponding dimension.
10880
10881 \note This function can only be called inside a compute pass, meaning
10882 between a beginComputePass() and endComputePass() call.
10883
10884 \note \a x, \a y, and \a z must fit the limits from the underlying graphics
10885 API implementation at run time. The maximum values are typically 65535.
10886
10887 \note Watch out for possible limits on the local workgroup size as well.
10888 This is specified in the shader, for example: \c{layout(local_size_x = 16,
10889 local_size_y = 16) in;}. For example, with OpenGL the minimum value mandated
10890 by the specification for the number of invocations in a single local work
10891 group (the product of \c local_size_x, \c local_size_y, and \c local_size_z)
10892 is 1024, while with OpenGL ES (3.1) the value may be as low as 128. This
10893 means that the example given above may be rejected by some OpenGL ES
10894 implementations as the number of invocations is 256.
10895 */
10896void QRhiCommandBuffer::dispatch(int x, int y, int z)
10897{
10898 m_rhi->dispatch(this, x, y, z);
10899}
10900
10901/*!
10902 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
10903 QRhiVulkanCommandBufferNativeHandles. The returned value is \nullptr when
10904 exposing the underlying native resources is not supported by, or not
10905 applicable to, the backend.
10906
10907 \sa QRhiVulkanCommandBufferNativeHandles,
10908 QRhiMetalCommandBufferNativeHandles, beginExternal(), endExternal()
10909 */
10910const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
10911{
10912 return m_rhi->nativeHandles(this);
10913}
10914
10915/*!
10916 To be called when the application before the application is about to
10917 enqueue commands to the current pass' command buffer by calling graphics
10918 API functions directly.
10919
10920 \note This is only available when the intent was declared upfront in
10921 beginPass() or beginComputePass(). Therefore this function must only be
10922 called when the pass recording was started with specifying
10923 QRhiCommandBuffer::ExternalContent.
10924
10925 With Vulkan, Metal, or Direct3D 12 one can query the native command buffer
10926 or encoder objects via nativeHandles() and enqueue commands to them. With
10927 OpenGL or Direct3D 11 the (device) context can be retrieved from
10928 QRhi::nativeHandles(). However, this must never be done without ensuring
10929 the QRhiCommandBuffer's state stays up-to-date. Hence the requirement for
10930 wrapping any externally added command recording between beginExternal() and
10931 endExternal(). Conceptually this is the same as QPainter's
10932 \l{QPainter::beginNativePainting()}{beginNativePainting()} and
10933 \l{QPainter::endNativePainting()}{endNativePainting()} functions.
10934
10935 For OpenGL in particular, this function has an additional task: it makes
10936 sure the context is made current on the current thread.
10937
10938 \note Once beginExternal() is called, no other render pass specific
10939 functions (\c set* or \c draw*) must be called on the
10940 QRhiCommandBuffer until endExternal().
10941
10942 \warning Some backends may return a native command buffer object from
10943 QRhiCommandBuffer::nativeHandles() that is different from the primary one
10944 when inside a beginExternal() - endExternal() block. Therefore it is
10945 important to (re)query the native command buffer object after calling
10946 beginExternal(). In practical terms this means that with Vulkan for example
10947 the externally recorded Vulkan commands are placed onto a secondary command
10948 buffer (with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT).
10949 nativeHandles() returns this secondary command buffer when called between
10950 begin/endExternal.
10951
10952 \sa endExternal(), nativeHandles()
10953 */
10954void QRhiCommandBuffer::beginExternal()
10955{
10956 m_rhi->beginExternal(this);
10957}
10958
10959/*!
10960 To be called once the externally added commands are recorded to the command
10961 buffer or context.
10962
10963 \note All QRhiCommandBuffer state must be assumed as invalid after calling
10964 this function. Pipelines, vertex and index buffers, and other state must be
10965 set again if more draw calls are recorded after the external commands.
10966
10967 \sa beginExternal(), nativeHandles()
10968 */
10969void QRhiCommandBuffer::endExternal()
10970{
10971 m_rhi->endExternal(this);
10972}
10973
10974/*!
10975 \return the last available timestamp, in seconds, when
10976 \l QRhi::EnableTimestamps was enabled when creating the QRhi. The value
10977 indicates the elapsed time on the GPU during the last completed frame.
10978
10979 \note Do not expect results other than 0 when the QRhi::Timestamps feature
10980 is not reported as supported, or when QRhi::EnableTimestamps was not passed
10981 to QRhi::create(). There are exceptions to this, because with some graphics
10982 APIs (Metal) timings are available without having to perform extra
10983 operations (timestamp queries), but portable applications should always
10984 consciously opt-in to timestamp collection when they know it is needed, and
10985 call this function accordingly.
10986
10987 Care must be exercised with the interpretation of the value, as its
10988 precision and granularity is often not controlled by Qt, and depends on the
10989 underlying graphics API and its implementation. In particular, comparing
10990 the values between different graphics APIs and hardware is discouraged and
10991 may be meaningless.
10992
10993 The timing values will likely become available asynchronously. The returned
10994 value may therefore be 0 (e.g., for the first 1-2 frames) or the last known
10995 value referring to some previous frame. The value my also become 0 again
10996 under certain conditions, such as when resizing the window. It can be
10997 expected that the most up-to-date available value is retrieved in
10998 beginFrame() and becomes queriable via this function once beginFrame()
10999 returns.
11000
11001 \note Do not assume that the value refers to the previous
11002 (\c{currently_recorded - 1}) frame. It may refer to \c{currently_recorded -
11003 2} or \c{currently_recorded - 3} as well. The exact behavior may depend on
11004 the graphics API and its implementation.
11005
11006 Watch out for the consequences of GPU frequency scaling and GPU clock
11007 changes, depending on the platform. For example, on Windows the returned
11008 timing may vary in a quite wide range between frames with modern graphics
11009 cards, even when submitting frames with a similar, or the same workload.
11010 This is out of scope for Qt to control and solve, generally speaking.
11011 However, the D3D12 backend automatically calls
11012 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-setstablepowerstate}{ID3D12Device::SetStablePowerState()}
11013 whenever the environment variable \c QT_D3D_STABLE_POWER_STATE is set to a
11014 non-zero value. This can greatly stabilize the result. It can also have a
11015 non-insignificant effect on the CPU-side timings measured via QElapsedTimer
11016 for example, especially when offscreen frames are involved.
11017
11018 \note Do not and never ship applications to production with
11019 \c QT_D3D_STABLE_POWER_STATE set. See the Windows API documentation for details.
11020
11021 \sa QRhi::Timestamps, QRhi::EnableTimestamps
11022 */
11023double QRhiCommandBuffer::lastCompletedGpuTime()
11024{
11025 return m_rhi->lastCompletedGpuTime(this);
11026}
11027
11028/*!
11029 \return the value (typically an offset) \a v aligned to the uniform buffer
11030 alignment given by ubufAlignment().
11031 */
11032int QRhi::ubufAligned(int v) const
11033{
11034 const int byteAlign = ubufAlignment();
11035 return (v + byteAlign - 1) & ~(byteAlign - 1);
11036}
11037
11038/*!
11039 \return the number of mip levels for a given \a size.
11040 */
11041int QRhi::mipLevelsForSize(const QSize &size)
11042{
11043 return qFloor(std::log2(qMax(size.width(), size.height()))) + 1;
11044}
11045
11046/*!
11047 \return the texture image size for a given \a mipLevel, calculated based on
11048 the level 0 size given in \a baseLevelSize.
11049 */
11050QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)
11051{
11052 const int w = qMax(1, baseLevelSize.width() >> mipLevel);
11053 const int h = qMax(1, baseLevelSize.height() >> mipLevel);
11054 return QSize(w, h);
11055}
11056
11057/*!
11058 \return \c true if the underlying graphics API has the Y axis pointing up
11059 in framebuffers and images.
11060
11061 In practice this is \c true for OpenGL only.
11062 */
11063bool QRhi::isYUpInFramebuffer() const
11064{
11065 return d->isYUpInFramebuffer();
11066}
11067
11068/*!
11069 \return \c true if the underlying graphics API has the Y axis pointing up
11070 in its normalized device coordinate system.
11071
11072 In practice this is \c false for Vulkan only.
11073
11074 \note clipSpaceCorrMatrix() includes the corresponding adjustment (to make
11075 Y point up) in its returned matrix.
11076 */
11077bool QRhi::isYUpInNDC() const
11078{
11079 return d->isYUpInNDC();
11080}
11081
11082/*!
11083 \return \c true if the underlying graphics API uses depth range [0, 1] in
11084 clip space.
11085
11086 In practice this is \c false for OpenGL only, because OpenGL uses a
11087 post-projection depth range of [-1, 1]. (not to be confused with the
11088 NDC-to-window mapping controlled by glDepthRange(), which uses a range of
11089 [0, 1], unless overridden by the QRhiViewport) In some OpenGL versions
11090 glClipControl() could be used to change this, but the OpenGL backend of
11091 QRhi does not use that function as it is not available in OpenGL ES or
11092 OpenGL versions lower than 4.5.
11093
11094 \note clipSpaceCorrMatrix() includes the corresponding adjustment in its
11095 returned matrix. Therefore, many users of QRhi do not need to take any
11096 further measures apart from pre-multiplying their projection matrices with
11097 clipSpaceCorrMatrix(). However, some graphics techniques, such as, some
11098 types of shadow mapping, involve working with and outputting depth values
11099 in the shaders. These will need to query and take the value of this
11100 function into account as appropriate.
11101 */
11102bool QRhi::isClipDepthZeroToOne() const
11103{
11104 return d->isClipDepthZeroToOne();
11105}
11106
11107/*!
11108 \return a matrix that can be used to allow applications keep using
11109 OpenGL-targeted vertex data and perspective projection matrices (such as,
11110 the ones generated by QMatrix4x4::perspective()), regardless of the active
11111 QRhi backend.
11112
11113 In a typical renderer, once \c{this_matrix * mvp} is used instead of just
11114 \c mvp, vertex data with Y up and viewports with depth range 0 - 1 can be
11115 used without considering what backend (and so graphics API) is going to be
11116 used at run time. This way branching based on isYUpInNDC() and
11117 isClipDepthZeroToOne() can be avoided (although such logic may still become
11118 required when implementing certain advanced graphics techniques).
11119
11120 See
11121 \l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this
11122 page} for a discussion of the topic from Vulkan perspective.
11123 */
11124QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
11125{
11126 return d->clipSpaceCorrMatrix();
11127}
11128
11129/*!
11130 \return \c true if the specified texture \a format modified by \a flags is
11131 supported.
11132
11133 The query is supported both for uncompressed and compressed formats.
11134 */
11135bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
11136{
11137 return d->isTextureFormatSupported(format, flags);
11138}
11139
11140/*!
11141 \return \c true if the specified \a feature is supported
11142 */
11143bool QRhi::isFeatureSupported(QRhi::Feature feature) const
11144{
11145 return d->isFeatureSupported(feature);
11146}
11147
11148/*!
11149 \return the value for the specified resource \a limit.
11150
11151 The values are expected to be queried by the backends upon initialization,
11152 meaning calling this function is a light operation.
11153 */
11154int QRhi::resourceLimit(ResourceLimit limit) const
11155{
11156 return d->resourceLimit(limit);
11157}
11158
11159/*!
11160 \return a pointer to the backend-specific collection of native objects
11161 for the device, context, and similar concepts used by the backend.
11162
11163 Cast to QRhiVulkanNativeHandles, QRhiD3D11NativeHandles,
11164 QRhiD3D12NativeHandles, QRhiGles2NativeHandles, or QRhiMetalNativeHandles
11165 as appropriate.
11166
11167 \note No ownership is transferred, neither for the returned pointer nor for
11168 any native objects.
11169 */
11170const QRhiNativeHandles *QRhi::nativeHandles()
11171{
11172 return d->nativeHandles();
11173}
11174
11175/*!
11176 With OpenGL this makes the OpenGL context current on the current thread.
11177 The function has no effect with other backends.
11178
11179 Calling this function is relevant typically in Qt framework code, when one
11180 has to ensure external OpenGL code provided by the application can still
11181 run like it did before with direct usage of OpenGL, as long as the QRhi is
11182 using the OpenGL backend.
11183
11184 \return false when failed, similarly to QOpenGLContext::makeCurrent(). When
11185 the operation failed, isDeviceLost() can be called to determine if there
11186 was a loss of context situation. Such a check is equivalent to checking via
11187 QOpenGLContext::isValid().
11188
11189 \sa QOpenGLContext::makeCurrent(), QOpenGLContext::isValid()
11190 */
11191bool QRhi::makeThreadLocalNativeContextCurrent()
11192{
11193 return d->makeThreadLocalNativeContextCurrent();
11194}
11195
11196/*!
11197 With backends and graphics APIs where applicable, this function allows to
11198 provide additional arguments to the \b next submission of commands to the
11199 graphics command queue.
11200
11201 In particular, with Vulkan this allows passing in a list of Vulkan semaphore
11202 objects for \c vkQueueSubmit() to signal and wait on. \a params must then be
11203 a \l QRhiVulkanQueueSubmitParams. This becomes essential in certain advanced
11204 use cases, such as when performing native Vulkan calls that involve having
11205 to wait on and signal VkSemaphores that the application's custom Vulkan
11206 rendering or compute code manages. In addition, this also allows specifying
11207 additional semaphores to wait on in the next \c vkQueuePresentKHR().
11208
11209 \note This function affects the next queue submission only, which will
11210 happen in endFrame(), endOffscreenFrame(), or finish(). The enqueuing of
11211 present happens in endFrame().
11212
11213 With many other backends the implementation of this function is a no-op.
11214
11215 \since 6.9
11216 */
11217void QRhi::setQueueSubmitParams(QRhiNativeHandles *params)
11218{
11219 d->setQueueSubmitParams(params);
11220}
11221
11222/*!
11223 Attempts to release resources in the backend's caches. This can include both
11224 CPU and GPU resources. Only memory and resources that can be recreated
11225 automatically are in scope. As an example, if the backend's
11226 QRhiGraphicsPipeline implementation maintains a cache of shader compilation
11227 results, calling this function leads to emptying that cache, thus
11228 potentially freeing up memory and graphics resources.
11229
11230 Calling this function makes sense in resource constrained environments,
11231 where at a certain point there is a need to ensure minimal resource usage,
11232 at the expense of performance.
11233 */
11234void QRhi::releaseCachedResources()
11235{
11236 d->releaseCachedResources();
11237
11238 for (QRhiResourceUpdateBatch *u : d->resUpdPool) {
11239 if (u->d->poolIndex < 0)
11240 u->d->trimOpLists();
11241 }
11242}
11243
11244/*!
11245 \return true if the graphics device was lost.
11246
11247 The loss of the device is typically detected in beginFrame(), endFrame() or
11248 QRhiSwapChain::createOrResize(), depending on the backend and the underlying
11249 native APIs. The most common is endFrame() because that is where presenting
11250 happens. With some backends QRhiSwapChain::createOrResize() can also fail
11251 due to a device loss. Therefore this function is provided as a generic way
11252 to check if a device loss was detected by a previous operation.
11253
11254 When the device is lost, no further operations should be done via the QRhi.
11255 Rather, all QRhi resources should be released, followed by destroying the
11256 QRhi. A new QRhi can then be attempted to be created. If successful, all
11257 graphics resources must be reinitialized. If not, try again later,
11258 repeatedly.
11259
11260 While simple applications may decide to not care about device loss,
11261 on the commonly used desktop platforms a device loss can happen
11262 due to a variety of reasons, including physically disconnecting the
11263 graphics adapter, disabling the device or driver, uninstalling or upgrading
11264 the graphics driver, or due to errors that lead to a graphics device reset.
11265 Some of these can happen under perfectly normal circumstances as well, for
11266 example the upgrade of the graphics driver to a newer version is a common
11267 task that can happen at any time while a Qt application is running. Users
11268 may very well expect applications to be able to survive this, even when the
11269 application is actively using an API like OpenGL or Direct3D.
11270
11271 Qt's own frameworks built on top of QRhi, such as, Qt Quick, can be
11272 expected to handle and take appropriate measures when a device loss occurs.
11273 If the data for graphics resources, such as textures and buffers, are still
11274 available on the CPU side, such an event may not be noticeable on the
11275 application level at all since graphics resources can seamlessly be
11276 reinitialized then. However, applications and libraries working directly
11277 with QRhi are expected to be prepared to check and handle device loss
11278 situations themselves.
11279
11280 \note With OpenGL, applications may need to opt-in to context reset
11281 notifications by setting QSurfaceFormat::ResetNotification on the
11282 QOpenGLContext. This is typically done by enabling the flag in
11283 QRhiGles2InitParams::format. Keep in mind however that some systems may
11284 generate context resets situations even when this flag is not set.
11285 */
11286bool QRhi::isDeviceLost() const
11287{
11288 return d->isDeviceLost();
11289}
11290
11291/*!
11292 \return a binary data blob with data collected from the
11293 QRhiGraphicsPipeline and QRhiComputePipeline successfully created during
11294 the lifetime of this QRhi.
11295
11296 By saving and then, in subsequent runs of the same application, reloading
11297 the cache data, pipeline and shader creation times can potentially be
11298 reduced. What exactly the cache and its serialized version includes is not
11299 specified, is always specific to the backend used, and in some cases also
11300 dependent on the particular implementation of the graphics API.
11301
11302 When the PipelineCacheDataLoadSave is reported as unsupported, the returned
11303 QByteArray is empty.
11304
11305 When the EnablePipelineCacheDataSave flag was not specified when calling
11306 create(), the returned QByteArray may be empty, even when the
11307 PipelineCacheDataLoadSave feature is supported.
11308
11309 When the returned data is non-empty, it is always specific to the Qt
11310 version and QRhi backend. In addition, in some cases there is a strong
11311 dependency to the graphics device and the exact driver version used. QRhi
11312 takes care of adding the appropriate header and safeguards that ensure that
11313 the data can always be passed safely to setPipelineCacheData(), therefore
11314 attempting to load data from a run on another version of a driver will be
11315 handled safely and gracefully.
11316
11317 \note Calling releaseCachedResources() may, depending on the backend, clear
11318 the pipeline data collected. A subsequent call to this function may then
11319 not return any data.
11320
11321 See EnablePipelineCacheDataSave for further details about this feature.
11322
11323 \note Minimize the number of calls to this function. Retrieving the blob is
11324 not always a cheap operation, and therefore this function should only be
11325 called at a low frequency, ideally only once e.g. when closing the
11326 application.
11327
11328 \sa setPipelineCacheData(), create(), isFeatureSupported()
11329 */
11330QByteArray QRhi::pipelineCacheData()
11331{
11332 return d->pipelineCacheData();
11333}
11334
11335/*!
11336 Loads \a data into the pipeline cache, when applicable.
11337
11338 When the PipelineCacheDataLoadSave is reported as unsupported, the function
11339 is safe to call, but has no effect.
11340
11341 The blob returned by pipelineCacheData() is always specific to the Qt
11342 version, the QRhi backend, and, in some cases, also to the graphics device,
11343 and a given version of the graphics driver. QRhi takes care of adding the
11344 appropriate header and safeguards that ensure that the data can always be
11345 passed safely to this function. If there is a mismatch, e.g. because the
11346 driver has been upgraded to a newer version, or because the data was
11347 generated from a different QRhi backend, a warning is printed and \a data
11348 is safely ignored.
11349
11350 With Vulkan, this maps directly to VkPipelineCache. Calling this function
11351 creates a new Vulkan pipeline cache object, with its initial data sourced
11352 from \a data. The pipeline cache object is then used by all subsequently
11353 created QRhiGraphicsPipeline and QRhiComputePipeline objects, thus
11354 accelerating, potentially, the pipeline creation.
11355
11356 With other APIs there is no real pipeline cache, but they may provide a
11357 cache with bytecode from shader compilations (D3D) or program binaries
11358 (OpenGL). In applications that perform a lot of shader compilation from
11359 source at run time this can provide a significant boost in subsequent runs
11360 if the "pipeline cache" is pre-seeded from an earlier run using this
11361 function.
11362
11363 \note QRhi cannot give any guarantees that \a data has an effect on the
11364 pipeline and shader creation performance. With APIs like Vulkan, it is up
11365 to the driver to decide if \a data is used for some purpose, or if it is
11366 ignored.
11367
11368 See EnablePipelineCacheDataSave for further details about this feature.
11369
11370 \note This mechanism offered by QRhi is independent of the drivers' own
11371 internal caching mechanism, if any. This means that, depending on the
11372 graphics API and its implementation, the exact effects of retrieving and
11373 then reloading \a data are not predictable. Improved performance may not be
11374 visible at all in case other caching mechanisms outside of Qt's control are
11375 already active.
11376
11377 \note Minimize the number of calls to this function. Loading the blob is
11378 not always a cheap operation, and therefore this function should only be
11379 called at a low frequency, ideally only once e.g. when starting the
11380 application.
11381
11382 \warning Serialized pipeline cache data is assumed to be trusted content. Qt
11383 performs robust parsing of the header and metadata included in \a data,
11384 application developers are however advised to never pass in data from
11385 untrusted sources.
11386
11387 \sa pipelineCacheData(), isFeatureSupported()
11388 */
11389void QRhi::setPipelineCacheData(const QByteArray &data)
11390{
11391 d->setPipelineCacheData(data);
11392}
11393
11394/*!
11395 \struct QRhiStats
11396 \inmodule QtGuiPrivate
11397 \inheaderfile rhi/qrhi.h
11398 \since 6.6
11399
11400 \brief Statistics provided from the underlying memory allocator.
11401
11402 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
11403 for details.
11404 */
11405
11406/*!
11407 \variable QRhiStats::totalPipelineCreationTime
11408
11409 The total time in milliseconds spent in graphics and compute pipeline
11410 creation, which usually involves shader compilation or cache lookups, and
11411 potentially expensive processing.
11412
11413 \note The value should not be compared between different backends since the
11414 concept of "pipelines" and what exactly happens under the hood during, for
11415 instance, a call to QRhiGraphicsPipeline::create(), differ greatly between
11416 graphics APIs and their implementations.
11417
11418 \sa QRhi::statistics()
11419*/
11420
11421/*!
11422 \variable QRhiStats::blockCount
11423
11424 Statistic reported from the Vulkan or D3D12 memory allocator.
11425
11426 \sa QRhi::statistics()
11427*/
11428
11429/*!
11430 \variable QRhiStats::allocCount
11431
11432 Statistic reported from the Vulkan or D3D12 memory allocator.
11433
11434 \sa QRhi::statistics()
11435*/
11436
11437/*!
11438 \variable QRhiStats::usedBytes
11439
11440 Statistic reported from the Vulkan or D3D12 memory allocator.
11441
11442 \sa QRhi::statistics()
11443*/
11444
11445/*!
11446 \variable QRhiStats::unusedBytes
11447
11448 Statistic reported from the Vulkan or D3D12 memory allocator.
11449
11450 \sa QRhi::statistics()
11451*/
11452
11453/*!
11454 \variable QRhiStats::totalUsageBytes
11455
11456 Valid only with D3D12 currently. Matches IDXGIAdapter3::QueryVideoMemoryInfo().
11457
11458 \sa QRhi::statistics()
11459*/
11460
11461#ifndef QT_NO_DEBUG_STREAM
11462QDebug operator<<(QDebug dbg, const QRhiStats &info)
11463{
11464 QDebugStateSaver saver(dbg);
11465 dbg.nospace() << "QRhiStats("
11466 << "totalPipelineCreationTime=" << info.totalPipelineCreationTime
11467 << " blockCount=" << info.blockCount
11468 << " allocCount=" << info.allocCount
11469 << " usedBytes=" << info.usedBytes
11470 << " unusedBytes=" << info.unusedBytes
11471 << " totalUsageBytes=" << info.totalUsageBytes
11472 << ')';
11473 return dbg;
11474}
11475#endif
11476
11477/*!
11478 Gathers and returns statistics about the timings and allocations of
11479 graphics resources.
11480
11481 Data about memory allocations is only available with some backends, where
11482 such operations are under Qt's control. With graphics APIs where there is
11483 no lower level control over resource memory allocations, this will never be
11484 supported and all relevant fields in the results are 0.
11485
11486 With Vulkan in particular, the values are valid always, and are queried
11487 from the underlying memory allocator library. This gives an insight into
11488 the memory requirements of the active buffers and textures.
11489
11490 The same is true for Direct 3D 12. In addition to the memory allocator
11491 library's statistics, here the result also includes a \c totalUsageBytes
11492 field which reports the total size including additional resources that are
11493 not under the memory allocator library's control (swapchain buffers,
11494 descriptor heaps, etc.), as reported by DXGI.
11495
11496 The values correspond to all types of memory used, combined. (i.e. video +
11497 system in case of a discreet GPU)
11498
11499 Additional data, such as the total time in milliseconds spent in graphics
11500 and compute pipeline creation (which usually involves shader compilation or
11501 cache lookups, and potentially expensive processing) is available with most
11502 backends.
11503
11504 \note The elapsed times for operations such as pipeline creation may be
11505 affected by various factors. The results should not be compared between
11506 different backends since the concept of "pipelines" and what exactly
11507 happens under the hood during, for instance, a call to
11508 QRhiGraphicsPipeline::create(), differ greatly between graphics APIs and
11509 their implementations.
11510
11511 \note Additionally, many drivers will likely employ various caching
11512 strategies for shaders, programs, pipelines. (independently of Qt's own
11513 similar facilities, such as setPipelineCacheData() or the OpenGL-specific
11514 program binary disk cache). Because such internal behavior is transparent
11515 to the API client, Qt and QRhi have no knowledge or control over the exact
11516 caching strategy, persistency, invalidation of the cached data, etc. When
11517 reading timings, such as the time spent on pipeline creation, the potential
11518 presence and unspecified behavior of driver-level caching mechanisms should
11519 be kept in mind.
11520 */
11521QRhiStats QRhi::statistics() const
11522{
11523 return d->statistics();
11524}
11525
11526/*!
11527 \return a new graphics pipeline resource.
11528
11529 \sa QRhiResource::destroy()
11530 */
11531QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
11532{
11533 return d->createGraphicsPipeline();
11534}
11535
11536/*!
11537 \return a new compute pipeline resource.
11538
11539 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
11540 is reported as supported.
11541
11542 \sa QRhiResource::destroy()
11543 */
11544QRhiComputePipeline *QRhi::newComputePipeline()
11545{
11546 return d->createComputePipeline();
11547}
11548
11549/*!
11550 \return a new shader resource binding collection resource.
11551
11552 \sa QRhiResource::destroy()
11553 */
11554QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
11555{
11556 return d->createShaderResourceBindings();
11557}
11558
11559/*!
11560 \return a new buffer with the specified \a type, \a usage, and \a size.
11561
11562 \note Some \a usage and \a type combinations may not be supported by all
11563 backends. See \l{QRhiBuffer::UsageFlag}{UsageFlags} and
11564 \l{QRhi::NonDynamicUniformBuffers}{the feature flags}.
11565
11566 \note Backends may choose to allocate buffers bigger than \a size. This is
11567 done transparently to applications, so there are no special restrictions on
11568 the value of \a size. QRhiBuffer::size() will always report back the value
11569 that was requested in \a size.
11570
11571 \sa QRhiResource::destroy()
11572 */
11573QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type,
11574 QRhiBuffer::UsageFlags usage,
11575 quint32 size)
11576{
11577 return d->createBuffer(type, usage, size);
11578}
11579
11580/*!
11581 \return a new renderbuffer with the specified \a type, \a pixelSize, \a
11582 sampleCount, and \a flags.
11583
11584 When \a backingFormatHint is set to a texture format other than
11585 QRhiTexture::UnknownFormat, it may be used by the backend to decide what
11586 format to use for the storage backing the renderbuffer.
11587
11588 \note \a backingFormatHint becomes relevant typically when multisampling
11589 and floating point texture formats are involved: rendering into a
11590 multisample QRhiRenderBuffer and then resolving into a non-RGBA8
11591 QRhiTexture implies (with some graphics APIs) that the storage backing the
11592 QRhiRenderBuffer uses the matching non-RGBA8 format. That means that
11593 passing a format like QRhiTexture::RGBA32F is important, because backends
11594 will typically opt for QRhiTexture::RGBA8 by default, which would then
11595 break later on due to attempting to set up RGBA8->RGBA32F multisample
11596 resolve in the color attachment(s) of the QRhiTextureRenderTarget.
11597
11598 \sa QRhiResource::destroy()
11599 */
11600QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type,
11601 const QSize &pixelSize,
11602 int sampleCount,
11603 QRhiRenderBuffer::Flags flags,
11604 QRhiTexture::Format backingFormatHint)
11605{
11606 return d->createRenderBuffer(type, pixelSize, sampleCount, flags, backingFormatHint);
11607}
11608
11609/*!
11610 \return a new 1D or 2D texture with the specified \a format, \a pixelSize, \a
11611 sampleCount, and \a flags.
11612
11613 A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This
11614 function will implicitly set this flag if the \a pixelSize height is 0.
11615
11616 \note \a format specifies the requested internal and external format,
11617 meaning the data to be uploaded to the texture will need to be in a
11618 compatible format, while the native texture may (but is not guaranteed to,
11619 in case of OpenGL at least) use this format internally.
11620
11621 \note 1D textures are only functional when the OneDimensionalTextures feature is
11622 reported as supported at run time. Further, mipmaps on 1D textures are only
11623 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
11624
11625 \sa QRhiResource::destroy()
11626 */
11627QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
11628 const QSize &pixelSize,
11629 int sampleCount,
11630 QRhiTexture::Flags flags)
11631{
11632 if (pixelSize.height() == 0)
11633 flags |= QRhiTexture::OneDimensional;
11634
11635 return d->createTexture(format, pixelSize, 1, 0, sampleCount, flags);
11636}
11637
11638/*!
11639 \return a new 1D, 2D or 3D texture with the specified \a format, \a width, \a
11640 height, \a depth, \a sampleCount, and \a flags.
11641
11642 This overload is suitable for 3D textures because it allows specifying \a
11643 depth. A 3D texture must have QRhiTexture::ThreeDimensional set in \a
11644 flags, but using this overload that can be omitted because the flag is set
11645 implicitly whenever \a depth is greater than 0. For 1D, 2D and cube textures \a
11646 depth should be set to 0.
11647
11648 A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This overload
11649 will implicitly set this flag if both \a height and \a depth are 0.
11650
11651 \note 3D textures are only functional when the ThreeDimensionalTextures
11652 feature is reported as supported at run time.
11653
11654 \note 1D textures are only functional when the OneDimensionalTextures feature is
11655 reported as supported at run time. Further, mipmaps on 1D textures are only
11656 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
11657
11658 \overload
11659 */
11660QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
11661 int width, int height, int depth,
11662 int sampleCount,
11663 QRhiTexture::Flags flags)
11664{
11665 if (depth > 0)
11666 flags |= QRhiTexture::ThreeDimensional;
11667
11668 if (height == 0 && depth == 0)
11669 flags |= QRhiTexture::OneDimensional;
11670
11671 return d->createTexture(format, QSize(width, height), depth, 0, sampleCount, flags);
11672}
11673
11674/*!
11675 \return a new 1D or 2D texture array with the specified \a format, \a arraySize,
11676 \a pixelSize, \a sampleCount, and \a flags.
11677
11678 This function implicitly sets QRhiTexture::TextureArray in \a flags.
11679
11680 A 1D texture array must have QRhiTexture::OneDimensional set in \a flags. This
11681 function will implicitly set this flag if the \a pixelSize height is 0.
11682
11683 \note Do not confuse texture arrays with arrays of textures. A QRhiTexture
11684 created by this function is usable with 1D or 2D array samplers in the shader, for
11685 example: \c{layout(binding = 1) uniform sampler2DArray texArr;}. Arrays of
11686 textures refers to a list of textures that are exposed to the shader via
11687 QRhiShaderResourceBinding::sampledTextures() and a count > 1, and declared
11688 in the shader for example like this: \c{layout(binding = 1) uniform
11689 sampler2D textures[4];}
11690
11691 \note This is only functional when the TextureArrays feature is reported as
11692 supported at run time.
11693
11694 \note 1D textures are only functional when the OneDimensionalTextures feature is
11695 reported as supported at run time. Further, mipmaps on 1D textures are only
11696 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
11697
11698
11699 \sa newTexture()
11700 */
11701QRhiTexture *QRhi::newTextureArray(QRhiTexture::Format format,
11702 int arraySize,
11703 const QSize &pixelSize,
11704 int sampleCount,
11705 QRhiTexture::Flags flags)
11706{
11707 flags |= QRhiTexture::TextureArray;
11708
11709 if (pixelSize.height() == 0)
11710 flags |= QRhiTexture::OneDimensional;
11711
11712 return d->createTexture(format, pixelSize, 1, arraySize, sampleCount, flags);
11713}
11714
11715/*!
11716 \return a new sampler with the specified magnification filter \a magFilter,
11717 minification filter \a minFilter, mipmapping mode \a mipmapMode, and the
11718 addressing (wrap) modes \a addressU, \a addressV, and \a addressW.
11719
11720 \note Setting \a mipmapMode to a value other than \c None implies that
11721 images for all relevant mip levels will be provided either via
11722 \l{QRhiResourceUpdateBatch::uploadTexture()}{texture uploads} or by calling
11723 \l{QRhiResourceUpdateBatch::generateMips()}{generateMips()} on the texture
11724 that is used with this sampler. Attempting to use the sampler with a
11725 texture that has no data for all relevant mip levels will lead to rendering
11726 errors, with the exact behavior dependent on the underlying graphics API.
11727
11728 \sa QRhiResource::destroy()
11729 */
11730QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter,
11731 QRhiSampler::Filter minFilter,
11732 QRhiSampler::Filter mipmapMode,
11733 QRhiSampler::AddressMode addressU,
11734 QRhiSampler::AddressMode addressV,
11735 QRhiSampler::AddressMode addressW)
11736{
11737 return d->createSampler(magFilter, minFilter, mipmapMode, addressU, addressV, addressW);
11738}
11739
11740/*!
11741 \return a new shading rate map object.
11742
11743 \since 6.9
11744 */
11745QRhiShadingRateMap *QRhi::newShadingRateMap()
11746{
11747 return d->createShadingRateMap();
11748}
11749
11750/*!
11751 \return a new texture render target with color and depth/stencil
11752 attachments given in \a desc, and with the specified \a flags.
11753
11754 \sa QRhiResource::destroy()
11755 */
11756
11757QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
11758 QRhiTextureRenderTarget::Flags flags)
11759{
11760 return d->createTextureRenderTarget(desc, flags);
11761}
11762
11763/*!
11764 \return a new swapchain.
11765
11766 \sa QRhiResource::destroy(), QRhiSwapChain::createOrResize()
11767 */
11768QRhiSwapChain *QRhi::newSwapChain()
11769{
11770 return d->createSwapChain();
11771}
11772
11773/*!
11774 Starts a new frame targeting the next available buffer of \a swapChain.
11775
11776 A frame consists of resource updates and one or more render and compute
11777 passes.
11778
11779 \a flags can indicate certain special cases.
11780
11781 The high level pattern of rendering into a QWindow using a swapchain:
11782
11783 \list
11784
11785 \li Create a swapchain.
11786
11787 \li Call QRhiSwapChain::createOrResize() whenever the surface size is
11788 different than before.
11789
11790 \li Call QRhiSwapChain::destroy() on
11791 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed.
11792
11793 \li Then on every frame:
11794 \badcode
11795 beginFrame(sc);
11796 updates = nextResourceUpdateBatch();
11797 updates->...
11798 QRhiCommandBuffer *cb = sc->currentFrameCommandBuffer();
11799 cb->beginPass(sc->currentFrameRenderTarget(), colorClear, dsClear, updates);
11800 ...
11801 cb->endPass();
11802 ... // more passes as necessary
11803 endFrame(sc);
11804 \endcode
11805
11806 \endlist
11807
11808 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
11809 value on failure. Some of these should be treated as soft, "try again
11810 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
11811 the swapchain is to be resized or updated by calling
11812 QRhiSwapChain::createOrResize(). The application should then attempt to
11813 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
11814 lost but this may also be recoverable by releasing all resources, including
11815 the QRhi itself, and then recreating all resources. See isDeviceLost() for
11816 further discussion.
11817
11818 \sa endFrame(), beginOffscreenFrame(), isDeviceLost()
11819 */
11820QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
11821{
11822 if (d->inFrame)
11823 qWarning("Attempted to call beginFrame() within a still active frame; ignored");
11824
11825 qCDebug(QRHI_LOG_RUB) << "[rub] new frame";
11826
11827 QRhi::FrameOpResult r = !d->inFrame ? d->beginFrame(swapChain, flags) : FrameOpSuccess;
11828 if (r == FrameOpSuccess)
11829 d->inFrame = true;
11830
11831 return r;
11832}
11833
11834/*!
11835 Ends, commits, and presents a frame that was started in the last
11836 beginFrame() on \a swapChain.
11837
11838 Double (or triple) buffering is managed internally by the QRhiSwapChain and
11839 QRhi.
11840
11841 \a flags can optionally be used to change the behavior in certain ways.
11842 Passing QRhi::SkipPresent skips queuing the Present command or calling
11843 swapBuffers.
11844
11845 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
11846 value on failure. Some of these should be treated as soft, "try again
11847 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
11848 the swapchain is to be resized or updated by calling
11849 QRhiSwapChain::createOrResize(). The application should then attempt to
11850 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
11851 lost but this may also be recoverable by releasing all resources, including
11852 the QRhi itself, and then recreating all resources. See isDeviceLost() for
11853 further discussion.
11854
11855 \sa beginFrame(), isDeviceLost()
11856 */
11857QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags)
11858{
11859 if (!d->inFrame)
11860 qWarning("Attempted to call endFrame() without an active frame; ignored");
11861
11862 QRhi::FrameOpResult r = d->inFrame ? d->endFrame(swapChain, flags) : FrameOpSuccess;
11863 d->inFrame = false;
11864 // deleteLater is a high level QRhi concept the backends know
11865 // nothing about - handle it here.
11866 qDeleteAll(d->pendingDeleteResources);
11867 d->pendingDeleteResources.clear();
11868
11869 return r;
11870}
11871
11872/*!
11873 \return true when there is an active frame, meaning there was a
11874 beginFrame() (or beginOffscreenFrame()) with no corresponding endFrame()
11875 (or endOffscreenFrame()) yet.
11876
11877 \sa currentFrameSlot(), beginFrame(), endFrame()
11878 */
11879bool QRhi::isRecordingFrame() const
11880{
11881 return d->inFrame;
11882}
11883
11884/*!
11885 \return the current frame slot index while recording a frame. Unspecified
11886 when called outside an active frame (that is, when isRecordingFrame() is \c
11887 false).
11888
11889 With backends like Vulkan or Metal, it is the responsibility of the QRhi
11890 backend to block whenever starting a new frame and finding the CPU is
11891 already \c{FramesInFlight - 1} frames ahead of the GPU (because the command
11892 buffer submitted in frame no. \c{current} - \c{FramesInFlight} has not yet
11893 completed).
11894
11895 Resources that tend to change between frames (such as, the native buffer
11896 object backing a QRhiBuffer with type QRhiBuffer::Dynamic) exist in
11897 multiple versions, so that each frame, that can be submitted while a
11898 previous one is still being processed, works with its own copy, thus
11899 avoiding the need to stall the pipeline when preparing the frame. (The
11900 contents of a resource that may still be in use in the GPU should not be
11901 touched, but simply always waiting for the previous frame to finish would
11902 reduce GPU utilization and ultimately, performance and efficiency.)
11903
11904 Conceptually this is somewhat similar to copy-on-write schemes used by some
11905 C++ containers and other types. It may also be similar to what an OpenGL or
11906 Direct 3D 11 implementation performs internally for certain type of objects.
11907
11908 In practice, such double (or triple) buffering resources is realized in
11909 the Vulkan, Metal, and similar QRhi backends by having a fixed number of
11910 native resource (such as, VkBuffer) \c slots behind a QRhiResource. That
11911 can then be indexed by a frame slot index running 0, 1, ..,
11912 FramesInFlight-1, and then wrapping around.
11913
11914 All this is managed transparently to the users of QRhi. However,
11915 applications that integrate rendering done directly with the graphics API
11916 may want to perform a similar double or triple buffering of their own
11917 graphics resources. That is then most easily achieved by knowing the values
11918 of the maximum number of in-flight frames (retrievable via resourceLimit())
11919 and the current frame (slot) index (returned by this function).
11920
11921 \sa isRecordingFrame(), beginFrame(), endFrame()
11922 */
11923int QRhi::currentFrameSlot() const
11924{
11925 return d->currentFrameSlot;
11926}
11927
11928/*!
11929 Starts a new offscreen frame. Provides a command buffer suitable for
11930 recording rendering commands in \a cb. \a flags is used to indicate
11931 certain special cases, just like with beginFrame().
11932
11933 \note The QRhiCommandBuffer stored to *cb is not owned by the caller.
11934
11935 Rendering without a swapchain is possible as well. The typical use case is
11936 to use it in completely offscreen applications, e.g. to generate image
11937 sequences by rendering and reading back without ever showing a window.
11938
11939 Usage in on-screen applications (so beginFrame, endFrame,
11940 beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) is possible too.
11941
11942 When a \l{QRhiResourceUpdateBatch::readBackTexture()}{texture} or
11943 \l{QRhiResourceUpdateBatch::readBackBuffer()}{buffer} readback was
11944 scheduled, offscreen frames do not let the CPU potentially generate another
11945 frame while the GPU is still processing the previous one. This has the side
11946 effect that if readbacks are scheduled, the results are guaranteed to be
11947 available once endOffscreenFrame() returns. That is not the case with frames
11948 targeting a swapchain: there the GPU is potentially better utilized, but
11949 working with readback operations needs more care from the application
11950 because endFrame(), unlike endOffscreenFrame(), does not guarantee that the
11951 results from the readback are available at that point.
11952
11953 The skeleton of rendering a frame without a swapchain and then reading the
11954 frame contents back could look like the following:
11955
11956 \code
11957 QRhiReadbackResult rbResult;
11958 QRhiCommandBuffer *cb;
11959 rhi->beginOffscreenFrame(&cb);
11960 cb->beginPass(rt, colorClear, dsClear);
11961 // ...
11962 u = nextResourceUpdateBatch();
11963 u->readBackTexture(rb, &rbResult);
11964 cb->endPass(u);
11965 rhi->endOffscreenFrame();
11966 // image data available in rbResult
11967 \endcode
11968
11969 \sa endOffscreenFrame(), beginFrame()
11970 */
11971QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags)
11972{
11973 if (d->inFrame)
11974 qWarning("Attempted to call beginOffscreenFrame() within a still active frame; ignored");
11975
11976 qCDebug(QRHI_LOG_RUB) << "[rub] new offscreen frame";
11977
11978 QRhi::FrameOpResult r = !d->inFrame ? d->beginOffscreenFrame(cb, flags) : FrameOpSuccess;
11979 if (r == FrameOpSuccess)
11980 d->inFrame = true;
11981
11982 return r;
11983}
11984
11985/*!
11986 Ends, submits, and potentially waits for the offscreen frame.
11987
11988 Unlike endFrame(), this function will block and wait for completion of the
11989 GPU-side work when there are active buffer or texture readbacks.
11990
11991 \a flags is not currently used.
11992
11993 \sa beginOffscreenFrame()
11994 */
11995QRhi::FrameOpResult QRhi::endOffscreenFrame(EndFrameFlags flags)
11996{
11997 if (!d->inFrame)
11998 qWarning("Attempted to call endOffscreenFrame() without an active frame; ignored");
11999
12000 QRhi::FrameOpResult r = d->inFrame ? d->endOffscreenFrame(flags) : FrameOpSuccess;
12001 d->inFrame = false;
12002 qDeleteAll(d->pendingDeleteResources);
12003 d->pendingDeleteResources.clear();
12004
12005 return r;
12006}
12007
12008/*!
12009 Waits for any work on the graphics queue (where applicable) to complete,
12010 then executes all deferred operations, like completing readbacks and
12011 resource releases. Can be called inside and outside of a frame, but not
12012 inside a pass. Inside a frame it implies submitting any work on the
12013 command buffer.
12014
12015 \note Avoid this function. One case where it may be needed is when the
12016 results of an enqueued readback in a swapchain-based frame are needed at a
12017 fixed given point and so waiting for the results is desired.
12018 */
12019QRhi::FrameOpResult QRhi::finish()
12020{
12021 return d->finish();
12022}
12023
12024/*!
12025 \return the list of supported sample counts.
12026
12027 A typical example would be (1, 2, 4, 8).
12028
12029 With some backend this list of supported values is fixed in advance, while
12030 with some others the (physical) device properties indicate what is
12031 supported at run time.
12032
12033 \sa QRhiRenderBuffer::setSampleCount(), QRhiTexture::setSampleCount(),
12034 QRhiGraphicsPipeline::setSampleCount(), QRhiSwapChain::setSampleCount()
12035 */
12036QList<int> QRhi::supportedSampleCounts() const
12037{
12038 return d->supportedSampleCounts();
12039}
12040
12041/*!
12042 \return the minimum uniform buffer offset alignment in bytes. This is
12043 typically 256.
12044
12045 Attempting to bind a uniform buffer region with an offset not aligned to
12046 this value will lead to failures depending on the backend and the
12047 underlying graphics API.
12048
12049 \sa ubufAligned()
12050 */
12051int QRhi::ubufAlignment() const
12052{
12053 return d->ubufAlignment();
12054}
12055
12056/*!
12057 \return The list of supported variable shading rates for the specified \a sampleCount.
12058
12059 1x1 is always supported.
12060
12061 \since 6.9
12062 */
12063QList<QSize> QRhi::supportedShadingRates(int sampleCount) const
12064{
12065 return d->supportedShadingRates(sampleCount);
12066}
12067
12068Q_CONSTINIT static QBasicAtomicInteger<QRhiGlobalObjectIdGenerator::Type> counter = Q_BASIC_ATOMIC_INITIALIZER(0);
12069
12070QRhiGlobalObjectIdGenerator::Type QRhiGlobalObjectIdGenerator::newId()
12071{
12072 return counter.fetchAndAddRelaxed(1) + 1;
12073}
12074
12076{
12077 return m_buffers.isEmpty() && m_textures.isEmpty();
12078}
12079
12081{
12082 m_buffers.clear();
12083 m_textures.clear();
12084}
12085
12091
12092void QRhiPassResourceTracker::registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
12093 const UsageState &state)
12094{
12095 auto it = m_buffers.find(buf);
12096 if (it != m_buffers.end()) {
12097 Buffer &b = it->second;
12098 if (Q_UNLIKELY(b.access != *access)) {
12099 const QByteArray name = buf->name();
12100 qWarning("Buffer %p (%s) used with different accesses within the same pass, this is not allowed.",
12101 buf, name.constData());
12102 return;
12103 }
12104 if (b.stage != *stage) {
12105 b.stage = earlierStage(b.stage, *stage);
12106 *stage = b.stage;
12107 }
12108 return;
12109 }
12110
12111 Buffer b;
12112 b.slot = slot;
12113 b.access = *access;
12114 b.stage = *stage;
12115 b.stateAtPassBegin = state; // first use -> initial state
12116 m_buffers.insert(buf, b);
12117}
12118
12124
12131
12133 const UsageState &state)
12134{
12135 auto it = m_textures.find(tex);
12136 if (it != m_textures.end()) {
12137 Texture &t = it->second;
12138 if (t.access != *access) {
12139 // Different subresources of a texture may be used for both load
12140 // and store in the same pass. (think reading from one mip level
12141 // and writing to another one in a compute shader) This we can
12142 // handle by treating the entire resource as read-write.
12143 if (Q_LIKELY(isImageLoadStore(t.access) && isImageLoadStore(*access))) {
12145 *access = t.access;
12146 } else {
12147 const QByteArray name = tex->name();
12148 qWarning("Texture %p (%s) used with different accesses within the same pass, this is not allowed.",
12149 tex, name.constData());
12150 }
12151 }
12152 if (t.stage != *stage) {
12153 t.stage = earlierStage(t.stage, *stage);
12154 *stage = t.stage;
12155 }
12156 return;
12157 }
12158
12159 Texture t;
12160 t.access = *access;
12161 t.stage = *stage;
12162 t.stateAtPassBegin = state; // first use -> initial state
12163 m_textures.insert(tex, t);
12164}
12165
12166QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
12167{
12168 // pick the earlier stage (as this is going to be dstAccessMask)
12169 if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
12171 if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
12173 if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
12175 if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
12177 if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
12179 if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
12181
12182 Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::BufVertexStage);
12183}
12184
12185QRhiPassResourceTracker::TextureStage QRhiPassResourceTracker::toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
12186{
12187 // pick the earlier stage (as this is going to be dstAccessMask)
12188 if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
12190 if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
12192 if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
12194 if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
12196 if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
12198 if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
12200
12201 Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::TexVertexStage);
12202}
12203
12204QSize QRhiImplementation::clampedSubResourceUploadSize(QSize size, QPoint dstPos, int level, QSize textureSizeAtLevelZero, bool warn)
12205{
12206 const QSize subResSize = q->sizeForMipLevel(level, textureSizeAtLevelZero);
12207 const bool outOfBoundsHoriz = dstPos.x() + size.width() > subResSize.width();
12208 const bool outOfBoundsVert = dstPos.y() + size.height() > subResSize.height();
12209 if (Q_UNLIKELY(outOfBoundsHoriz || outOfBoundsVert)) {
12210 if (warn) {
12211 qWarning("Invalid texture upload issued; size %dx%d dst.position %d,%d dst.subresource size %dx%d; size will be clamped",
12212 size.width(), size.height(), dstPos.x(), dstPos.y(), subResSize.width(), subResSize.height());
12213 }
12214 if (outOfBoundsHoriz)
12215 size.setWidth(subResSize.width() - dstPos.x());
12216 if (outOfBoundsVert)
12217 size.setHeight(subResSize.height() - dstPos.y());
12218 }
12219 return size;
12220}
12221
12222// Clamps size so that reading the image with a source row stride of bpl does
12223// not go past dataSize bytes. bpl may be 0, meaning the data is tightly packed.
12224// Returns a size with a height of 0 when not even a single row can be
12225// satisfied, in which case the caller is expected to skip the copy.
12226QSize QRhiImplementation::clampedSubResourceUploadSizeForSourceData(QSize size, quint32 bpl,
12227 quint32 bytesPerPixel,
12228 qsizetype dataSize, bool warn)
12229{
12230 if (size.isEmpty() || !bytesPerPixel)
12231 return size;
12232
12233 const quint64 rowBytes = quint64(bytesPerPixel) * quint64(size.width());
12234 if (!bpl)
12235 bpl = quint32(qMin(rowBytes, quint64(std::numeric_limits<quint32>::max())));
12236
12237 if (quint64(bpl) < rowBytes) {
12238 if (warn) {
12239 qWarning("Invalid texture upload issued; source row stride %u is smaller than the %llu "
12240 "bytes a row of %d pixels needs; upload will be skipped",
12241 bpl, rowBytes, size.width());
12242 }
12243 return QSize(size.width(), 0);
12244 }
12245
12246 // Row y is read from y * bpl and needs rowBytes bytes, so the last row ends
12247 // at (height - 1) * bpl + rowBytes.
12248 const quint64 needed = quint64(bpl) * quint64(size.height() - 1) + rowBytes;
12249 if (quint64(dataSize) >= needed)
12250 return size;
12251
12252 int rows = 0;
12253 if (quint64(dataSize) >= rowBytes)
12254 rows = int((quint64(dataSize) - rowBytes) / quint64(bpl)) + 1;
12255
12256 if (warn) {
12257 qWarning("Invalid texture upload issued; %lld bytes of data cannot back a %dx%d upload with "
12258 "source row stride %u (needs %llu bytes); height will be clamped to %d",
12259 qint64(dataSize), size.width(), size.height(), bpl, needed, rows);
12260 }
12261
12262 return QSize(size.width(), rows);
12263}
12264
12265QT_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:815
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:826
bool isEmpty() const
Definition qrhi.cpp:12075
void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage, const UsageState &state)
Definition qrhi.cpp:12092
void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage, const UsageState &state)
Definition qrhi.cpp:12132
QRhiImplementation * rhi
Definition qrhi_p.h:591
static const int BUFFER_OPS_STATIC_ALLOC
Definition qrhi_p.h:583
void merge(QRhiResourceUpdateBatchPrivate *other)
Definition qrhi.cpp:10243
QRhiResourceUpdateBatch * q
Definition qrhi_p.h:590
static const int TEXTURE_OPS_STATIC_ALLOC
Definition qrhi_p.h:587
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
static const char * resourceTypeStr(const QRhiResource *res)
Definition qrhi.cpp:8554
static QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a, QRhiPassResourceTracker::BufferStage b)
Definition qrhi.cpp:12086
QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
Definition qrhi.cpp:8301
static bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess access)
Definition qrhi.cpp:12125
static const char * deviceTypeStr(QRhiDriverInfo::DeviceType type)
\variable QRhiDriverInfo::deviceName
Definition qrhi.cpp:9531
static QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a, QRhiPassResourceTracker::TextureStage b)
Definition qrhi.cpp:12119
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:1562
LimitsType limitsType
Definition qrhi.h:1573
float maxPotentialColorComponentValue
Definition qrhi.h:1581
LuminanceBehavior luminanceBehavior
Definition qrhi.h:1584
float maxColorComponentValue
Definition qrhi.h:1580