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
37Q_CONSTINIT QRhiDebugHooks qrhiDebugHooks;
38
39/*!
40 \class QRhi
41 \ingroup painting-3D
42 \inmodule QtGuiPrivate
43 \inheaderfile rhi/qrhi.h
44 \since 6.6
45
46 \brief Accelerated 2D/3D graphics API abstraction.
47
48 The Qt Rendering Hardware Interface is an abstraction for hardware accelerated
49 graphics APIs, such as, \l{https://www.khronos.org/opengl/}{OpenGL},
50 \l{https://www.khronos.org/opengles/}{OpenGL ES},
51 \l{https://docs.microsoft.com/en-us/windows/desktop/direct3d}{Direct3D},
52 \l{https://developer.apple.com/metal/}{Metal}, and
53 \l{https://www.khronos.org/vulkan/}{Vulkan}.
54
55 \warning The QRhi family of classes in the Qt Gui module, including QShader
56 and QShaderDescription, offer limited compatibility guarantees. There are
57 no source or binary compatibility guarantees for these classes, meaning the
58 API is only guaranteed to work with the Qt version the application was
59 developed against. Source incompatible changes are however aimed to be kept
60 at a minimum and will only be made in minor releases (6.7, 6.8, and so on).
61 To use these classes in an application, link to
62 \c{Qt::GuiPrivate} (if using CMake), and include the headers with the \c
63 rhi prefix, for example \c{#include <rhi/qrhi.h>}.
64
65 Each QRhi instance is backed by a backend for a specific graphics API. The
66 selection of the backend is a run time choice and is up to the application
67 or library that creates the QRhi instance. Some backends are available on
68 multiple platforms (OpenGL, Vulkan, Null), while APIs specific to a given
69 platform are only available when running on the platform in question (Metal
70 on macOS/iOS, Direct3D on Windows).
71
72 The available backends currently are:
73
74 \list
75
76 \li OpenGL 2.1 / OpenGL ES 2.0 or newer. Some extensions and newer core
77 specification features are utilized when present, for example to enable
78 multisample framebuffers or compute shaders. Operating in core profile
79 contexts is supported as well. If necessary, applications can query the
80 \l{QRhi::Feature}{feature flags} at runtime to check for features that are
81 not supported in the OpenGL context backing the QRhi. The OpenGL backend
82 builds on QOpenGLContext, QOpenGLFunctions, and the related cross-platform
83 infrastructure of the Qt GUI module.
84
85 \li Direct3D 11.2 and newer (with DXGI 1.3 and newer), using Shader Model
86 5.0 or newer. When the D3D runtime has no support for 11.2 features or
87 Shader Model 5.0, initialization using an accelerated graphics device will
88 fail, but using the
89 \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/directx-warp}{software
90 adapter} is still an option.
91
92 \li Direct3D 12 on Windows 10 version 1703 and newer, with Shader Model 5.0
93 or newer. Qt requires ID3D12Device2 to be present, hence the requirement
94 for at least version 1703 of Windows 10. The D3D12 device is by default
95 created with specifying a minimum feature level of
96 \c{D3D_FEATURE_LEVEL_11_0}.
97
98 \li Metal 1.2 or newer.
99
100 \li Vulkan 1.0 or newer, optionally utilizing some Vulkan 1.1 level
101 features.
102
103 \li Null, a "dummy" backend that issues no graphics calls at all.
104
105 \endlist
106
107 In order to allow shader code to be written once in Qt applications and
108 libraries, all shaders are expected to be written in a single language
109 which is then compiled into SPIR-V. Versions for various shading language
110 are then generated from that, together with reflection information (inputs,
111 outputs, shader resources). This is then packed into easily and efficiently
112 serializable QShader instances. The compilers and tools to generate such
113 shaders are not part of QRhi and the Qt GUI module, but the core classes
114 for using such shaders, QShader and QShaderDescription, are. The APIs and
115 tools for performing compilation and translation are part of the Qt Shader
116 Tools module.
117
118 See the \l{RHI Window Example} for an introductory example of creating a
119 portable, cross-platform application that performs accelerated 3D rendering
120 onto a QWindow using QRhi.
121
122 \section1 An Impression of the API
123
124 To provide a quick look at the API with a short yet complete example that
125 does not involve window-related setup, the following is a complete,
126 runnable cross-platform application that renders 20 frames off-screen, and
127 then saves the generated images to files after reading back the texture
128 contents from the GPU. For an example that renders on-screen, which then
129 involves setting up a QWindow and a swapchain, refer to the
130 \l{RHI Window Example}.
131
132 For brevity, the initialization of the QRhi is done based on the platform:
133 the sample code here chooses Direct 3D 12 on Windows, Metal on macOS and
134 iOS, and Vulkan otherwise. OpenGL and Direct 3D 11 are never used by this
135 application, but support for those could be introduced with a few
136 additional lines.
137
138 \snippet rhioffscreen/main.cpp 0
139
140 The result of the application is 20 \c PNG images (frame0.png -
141 frame19.png). These contain a rotating triangle with varying opacity over a
142 green background.
143
144 The vertex and fragment shaders are expected to be processed and packaged
145 into \c{.qsb} files. The Vulkan-compatible GLSL source code is the
146 following:
147
148 \e color.vert
149 \snippet rhioffscreen/color.vert 0
150
151 \e color.frag
152 \snippet rhioffscreen/color.frag 0
153
154 To manually compile and transpile these shaders to a number of targets
155 (SPIR-V, HLSL, MSL, GLSL) and generate the \c{.qsb} files the application
156 loads at run time, run \c{qsb --qt6 color.vert -o color.vert.qsb} and
157 \c{qsb --qt6 color.frag -o color.frag.qsb}. Alternatively, the Qt Shader
158 Tools module offers build system integration for CMake, the
159 \c qt_add_shaders() CMake function, that can achieve the same at build time.
160
161 \section1 Security Considerations
162
163 All data consumed by QRhi and related classes such as QShader are considered
164 trusted content.
165
166 \warning Application developers are advised to carefully consider the
167 potential implications before allowing the feeding of user-provided content
168 that is not part of the application and is not under the developers'
169 control. (this includes all vertex/index data, shaders, pipeline and draw
170 call parameters, etc.)
171
172 \section1 Design Fundamentals
173
174 A QRhi cannot be instantiated directly. Instead, use the create()
175 function. Delete the QRhi instance normally to release the graphics device.
176
177 \section2 Resources
178
179 Instances of classes deriving from QRhiResource, such as, QRhiBuffer,
180 QRhiTexture, etc., encapsulate zero, one, or more native graphics
181 resources. Instances of such classes are always created via the \c new
182 functions of the QRhi, such as, newBuffer(), newTexture(),
183 newTextureRenderTarget(), newSwapChain().
184
185 \code
186 QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
187 if (!vbuf->create()) { error(); }
188 // ...
189 delete vbuf;
190 \endcode
191
192 \list
193
194 \li The returned value from functions like newBuffer() is always owned by
195 the caller.
196
197 \li Just creating an instance of a QRhiResource subclass never allocates or
198 initializes any native resources. That is only done when calling the
199 \c create() function of a subclass, for example, QRhiBuffer::create() or
200 QRhiTexture::create().
201
202 \li The exceptions are
203 QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor(),
204 QRhiSwapChain::newCompatibleRenderPassDescriptor(), and
205 QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor(). There is no
206 \c create() operation for these and the returned object is immediately
207 active.
208
209 \li The resource objects themselves are treated as immutable: once a
210 resource has create() called, changing any parameters via the setters, such as,
211 QRhiTexture::setPixelSize(), has no effect, unless the underlying native
212 resource is released and \c create() is called again. See more about resource
213 reuse in the sections below.
214
215 \li The underlying native resources are scheduled for releasing by the
216 QRhiResource destructor, or by calling QRhiResource::destroy(). Backends
217 often queue release requests and defer executing them to an unspecified
218 time, this is hidden from the applications. This way applications do not
219 have to worry about releasing native resources that may still be in use by
220 an in-flight frame.
221
222 \li Note that this does not mean that a QRhiResource can freely be
223 destroy()'ed or deleted within a frame (that is, in a
224 \l{QRhi::beginFrame()}{beginFrame()} - \l{QRhi::endFrame()}{endFrame()}
225 section). As a general rule, all referenced QRhiResource objects must stay
226 unchanged until the frame is submitted by calling
227 \l{QRhi::endFrame()}{endFrame()}. To ease this,
228 QRhiResource::deleteLater() is provided as a convenience.
229
230 \endlist
231
232 \section2 Command buffers and deferred command execution
233
234 Regardless of the design and capabilities of the underlying graphics API,
235 all QRhi backends implement some level of command buffers. No
236 QRhiCommandBuffer function issues any native bind or draw command (such as,
237 \c glDrawElements) directly. Commands are always recorded in a queue,
238 either native or provided by the QRhi backend. The command buffer is
239 submitted, and so execution starts only upon QRhi::endFrame() or
240 QRhi::finish().
241
242 The deferred nature has consequences for some types of objects. For example,
243 writing to a dynamic buffer multiple times within a frame, in case such
244 buffers are backed by host-visible memory, will result in making the
245 results of all writes are visible to all draw calls in the command buffer
246 of the frame, regardless of when the dynamic buffer update was recorded
247 relative to a draw call.
248
249 Furthermore, instances of QRhiResource subclasses must be treated immutable
250 within a frame in which they are referenced in any way. Create
251 all resources upfront, before starting to record commands for the next
252 frame. Reusing a QRhiResource instance within a frame (by calling \c create()
253 then referencing it again in the same \c{beginFrame - endFrame} section)
254 should be avoided as it may lead to unexpected results, depending on the
255 backend.
256
257 As a general rule, all referenced QRhiResource objects must stay valid and
258 unmodified until the frame is submitted by calling
259 \l{QRhi::endFrame()}{endFrame()}. On the other hand, calling
260 \l{QRhiResource::destroy()}{destroy()} or deleting the QRhiResource are
261 always safe once the frame is submitted, regardless of the status of the
262 underlying native resources (which may still be in use by the GPU - but
263 that is taken care of internally).
264
265 Unlike APIs like OpenGL, upload and copy type of commands cannot be mixed
266 with draw commands. The typical renderer will involve a sequence similar to
267 the following:
268
269 \list
270 \li (re)create resources
271 \li begin frame
272 \li record/issue uploads and copies
273 \li start recording a render pass
274 \li record draw calls
275 \li end render pass
276 \li end frame
277 \endlist
278
279 Recording copy type of operations happens via QRhiResourceUpdateBatch. Such
280 operations are committed typically on
281 \l{QRhiCommandBuffer::beginPass()}{beginPass()}.
282
283 When working with legacy rendering engines designed for OpenGL, the
284 migration to QRhi often involves redesigning from having a single \c render
285 step (that performs copies and uploads, clears buffers, and issues draw
286 calls, all mixed together) to a clearly separated, two phase \c prepare -
287 \c render setup where the \c render step only starts a renderpass and
288 records draw calls, while all resource creation and queuing of updates,
289 uploads and copies happens beforehand, in the \c prepare step.
290
291 QRhi does not at the moment allow freely creating and submitting command
292 buffers. This may be lifted in the future to some extent, in particular if
293 compute support is introduced, but the model of well defined
294 \c{frame-start} and \c{frame-end} points, combined with a dedicated,
295 "frame" command buffer, where \c{frame-end} implies presenting, is going to
296 remain the primary way of operating since this is what fits Qt's various UI
297 technologies best.
298
299 \section2 Threading
300
301 A QRhi instance and the associated resources can be created and used on any
302 thread but all usage must be limited to that one single thread. When
303 rendering to multiple QWindows in an application, having a dedicated thread
304 and QRhi instance for each window is often advisable, as this can eliminate
305 issues with unexpected throttling caused by presenting to multiple windows.
306 Conceptually that is then the same as how Qt Quick scene graph's threaded
307 render loop operates when working directly with OpenGL: one thread for each
308 window, one QOpenGLContext for each thread. When moving onto QRhi,
309 QOpenGLContext is replaced by QRhi, making the migration straightforward.
310
311 When it comes to externally created native objects, such as OpenGL contexts
312 passed in via QRhiGles2NativeHandles, it is up to the application to ensure
313 they are not misused by other threads.
314
315 Resources are not shareable between QRhi instances. This is an intentional
316 choice since QRhi hides most queue, command buffer, and resource
317 synchronization related tasks, and provides no API for them. Safe and
318 efficient concurrent use of graphics resources from multiple threads is
319 tied to those concepts, however, and is thus a topic that is currently out
320 of scope, but may be introduced in the future.
321
322 \note The Metal backend requires that an autorelease pool is available on
323 the rendering thread, ideally wrapping each iteration of the render loop.
324 This needs no action from the users of QRhi when rendering on the main
325 (gui) thread, but becomes important when a separate, dedicated render
326 thread is used.
327
328 \section2 Resource synchronization
329
330 QRhi does not expose APIs for resource barriers or image layout
331 transitions. Such synchronization is done implicitly by the backends, where
332 applicable (for example, Vulkan), by tracking resource usage as necessary.
333 Buffer and image barriers are inserted before render or compute passes
334 transparently to the application.
335
336 \note Resources within a render or compute pass are expected to be bound to
337 a single usage during that pass. For example, a buffer can be used as
338 vertex, index, uniform, or storage buffer, but not a combination of them
339 within a single pass. However, it is perfectly fine to use a buffer as a
340 storage buffer in a compute pass, and then as a vertex buffer in a render
341 pass, for example, assuming the buffer declared both usages upon creation.
342
343 \note Textures have this rule relaxed in certain cases, because using two
344 subresources (typically two different mip levels) of the same texture for
345 different access (one for load, one for store) is supported even within the
346 same pass.
347
348 \section2 Resource reuse
349
350 From the user's point of view a QRhiResource is reusable immediately after
351 calling QRhiResource::destroy(). With the exception of swapchains, calling
352 \c create() on an already created object does an implicit \c destroy(). This
353 provides a handy shortcut to reuse a QRhiResource instance with different
354 parameters, with a new native graphics object underneath.
355
356 The importance of reusing the same object lies in the fact that some
357 objects reference other objects: for example, a QRhiShaderResourceBindings
358 can reference QRhiBuffer, QRhiTexture, and QRhiSampler instances. If in a
359 later frame one of these buffers need to be resized or a sampler parameter
360 needs changing, destroying and creating a whole new QRhiBuffer or
361 QRhiSampler would invalidate all references to the old instance. By just
362 changing the appropriate parameters via QRhiBuffer::setSize() or similar
363 and then calling QRhiBuffer::create(), everything works as expected and
364 there is no need to touch the QRhiShaderResourceBindings at all, even
365 though there is a good chance that under the hood the QRhiBuffer is now
366 backed by a whole new native buffer.
367
368 \code
369 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 256);
370 ubuf->create();
371
372 QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings()
373 srb->setBindings({
374 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf)
375 });
376 srb->create();
377
378 // ...
379
380 // now in a later frame we need to grow the buffer to a larger size
381 ubuf->setSize(512);
382 ubuf->create(); // same as ubuf->destroy(); ubuf->create();
383
384 // srb needs no changes whatsoever, any references in it to ubuf
385 // stay valid. When it comes to internal details, such as that
386 // ubuf may now be backed by a completely different native buffer
387 // resource, that is is recognized and handled automatically by the
388 // next setShaderResources().
389 \endcode
390
391 QRhiTextureRenderTarget offers the same contract: calling
392 QRhiCommandBuffer::beginPass() is safe even when one of the render target's
393 associated textures or renderbuffers has been rebuilt (by calling \c
394 create() on it) since the creation of the render target object. This allows
395 the application to resize a texture by setting a new pixel size on the
396 QRhiTexture and calling create(), thus creating a whole new native texture
397 resource underneath, without having to update the QRhiTextureRenderTarget
398 as that will be done implicitly in beginPass().
399
400 \section2 Pooled objects
401
402 In addition to resources, there are pooled objects as well, such as,
403 QRhiResourceUpdateBatch. An instance is retrieved via a \c next function,
404 such as, nextResourceUpdateBatch(). The caller does not own the returned
405 instance in this case. The only valid way of operating here is calling
406 functions on the QRhiResourceUpdateBatch and then passing it to
407 QRhiCommandBuffer::beginPass() or QRhiCommandBuffer::endPass(). These
408 functions take care of returning the batch to the pool. Alternatively, a
409 batch can be "canceled" and returned to the pool without processing by
410 calling QRhiResourceUpdateBatch::release().
411
412 A typical pattern is thus:
413
414 \code
415 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
416 // ...
417 resUpdates->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
418 if (!image.isNull()) {
419 resUpdates->uploadTexture(texture, image);
420 image = QImage();
421 }
422 // ...
423 QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
424 // note the last argument
425 cb->beginPass(swapchain->currentFrameRenderTarget(), clearCol, clearDs, resUpdates);
426 \endcode
427
428 \section2 Swapchain specifics
429
430 QRhiSwapChain features some special semantics due to the peculiar nature of
431 swapchains.
432
433 \list
434
435 \li It has no \c create() but rather a QRhiSwapChain::createOrResize().
436 Repeatedly calling this function is \b not the same as calling
437 QRhiSwapChain::destroy() followed by QRhiSwapChain::createOrResize(). This
438 is because swapchains often have ways to handle the case where buffers need
439 to be resized in a manner that is more efficient than a brute force
440 destroying and recreating from scratch.
441
442 \li An active QRhiSwapChain must be released by calling
443 \l{QRhiSwapChain::destroy()}{destroy()}, or by destroying the object, before
444 the QWindow's underlying QPlatformWindow, and so the associated native
445 window object, is destroyed. It should not be postponed because releasing
446 the swapchain may become problematic (and with some APIs, like Vulkan, is
447 explicitly disallowed) when the native window is not around anymore, for
448 example because the QPlatformWindow got destroyed upon getting a
449 QWindow::close(). Therefore, releasing the swapchain must happen whenever
450 the targeted QWindow sends the
451 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed event. If the event does
452 not arrive before the destruction of the QWindow - this can happen when
453 using QCoreApplication::quit() -, then check QWindow::handle() after the
454 event loop exits and invoke the swapchain release when non-null (meaning
455 the underlying native window is still around).
456
457 \endlist
458
459 \section2 Ownership
460
461 The general rule is no ownership transfer. Creating a QRhi with an already
462 existing graphics device does not mean the QRhi takes ownership of the
463 device object. Similarly, ownership is not given away when a device or
464 texture object is "exported" via QRhi::nativeHandles() or
465 QRhiTexture::nativeTexture(). Most importantly, passing pointers in structs
466 and via setters does not transfer ownership.
467
468 \section1 Troubleshooting and Profiling
469
470 \section2 Error reporting
471
472 Functions such as \l QRhi::create() and the resource classes' \c create()
473 member functions (e.g., \l QRhiBuffer::create()) indicate failure with the
474 return value (\nullptr or
475 \c false, respectively). When working with QShader, \l QShader::fromSerialized()
476 returns an invalid QShader (for which \l{QShader::isValid()}{isValid()} returns
477 \c false) when the data passed to the function cannot be successfully deserialized.
478 Some functions, beginFrame() in particular, may also sometimes report "soft failures",
479 such as \l FrameOpSwapChainOutOfDate, which do not indicate an unrecoverable error,
480 but rather should be seen as a "try again later" response.
481
482 Warnings and errors may get printed at any time to the debug output via
483 qWarning(). It is therefore always advisable to inspect the output of the
484 application.
485
486 Additional debug messages can be enabled via the following logging
487 categories. Messages from these categories are not printed by default
488 unless explicitly enabled via QLoggingCategory or the \c QT_LOGGING_RULES
489 environment variable. For better interoperation with Qt Quick, the
490 environment variable \c{QSG_INFO} also enables these debug prints.
491
492 \list
493 \li \c{qt.rhi.general}
494 \endlist
495
496 Additionally, applications can query the \l{QRhi::backendName()}{QRhi
497 backend name} and
498 \l{QRhi::driverInfo()}{graphics device information} from a successfully
499 initialized QRhi. This can then be printed to the user or stored in the
500 application logs even in production builds, if desired.
501
502 \section2 Investigating rendering problems
503
504 When the rendering results are not as expected, or the application is
505 experiencing problems, always consider checking with the native 3D
506 APIs' debug and validation facilities. QRhi itself features limited error
507 checking since replicating the already existing, vast amount of
508 functionality in the underlying layers is not reasonable.
509
510 \list
511
512 \li For Vulkan, controlling the
513 \l{https://github.com/KhronosGroup/Vulkan-ValidationLayers}{Vulkan
514 Validation Layers} is not in the scope of the QRhi, but rather can be
515 achieved by configuring the \l QVulkanInstance with the appropriate layers.
516 For example, call \c{instance.setLayers({ "VK_LAYER_KHRONOS_validation" });}
517 before invoking \l{QVulkanInstance::create()}{create()} on the QVulkanInstance.
518 (note that this assumes that the validation layers are actually installed
519 and available, e.g. from the Vulkan SDK) By default, QVulkanInstance conveniently
520 redirects the Vulkan debug messages to qDebug, meaning the validation messages get
521 printed just like other Qt warnings.
522
523 \li With Direct 3D 11 and 12, a graphics device with the debug layer
524 enabled can be requested by toggling the \c enableDebugLayer flag in the
525 appropriate \l{QRhiD3D11InitParams}{init params struct}. With Direct 3D 12 the
526 messages are then printed via qDebug, just like the Vulkan validation
527 messages, as long as the debug layer supports message callbacks. Otherwise,
528 and always with Direct 3D 11, the messages appear on the debug output, which
529 is visible in Qt Creator's messages panel or via a tool such as
530 \l{https://learn.microsoft.com/en-us/sysinternals/downloads/debugview}{DebugView}.
531
532 \li For Metal, controlling Metal Validation is outside of QRhi's scope.
533 Rather, to enable validation, run the application with the environment
534 variable \c{METAL_DEVICE_WRAPPER_TYPE=1} set, or run the application within
535 XCode. There may also be further settings and environment variable in modern
536 XCode and macOS versions. See for instance
537 \l{https://developer.apple.com/documentation/metal/diagnosing_metal_programming_issues_early}{this
538 page}.
539
540 \endlist
541
542 \section2 Frame captures and performance profiling
543
544 A Qt application rendering with QRhi to a window while relying on a 3D API
545 under the hood, is, from the windowing and graphics pipeline perspective at
546 least, no different from any other (non-Qt) applications using the same 3D
547 API. This means that tools and practices for debugging and profiling
548 applications involving 3D graphics, such as games, all apply to such a Qt
549 application as well.
550
551 A few examples of tools that can provide insights into the rendering
552 internals of Qt applications that use QRhi, which includes Qt Quick and Qt
553 Quick 3D based projects as well:
554
555 \list
556
557 \li \l{https://renderdoc.org/}{RenderDoc} allows taking frame captures and
558 introspecting the recorded commands and pipeline state on Windows and Linux
559 for applications using OpenGL, Vulkan, D3D11, or D3D12. When trying to
560 figure out why some parts of the 3D scene do not show up as expected,
561 RenderDoc is often a fast and efficient way to check the pipeline stages
562 and the related state and discover the missing or incorrect value. It is
563 also a tool that is actively used when developing Qt itself.
564
565 \li For NVIDIA-based systems,
566 \l{https://developer.nvidia.com/nsight-graphics}{Nsight Graphics} provides
567 a graphics debugger tool on Windows and Linux. In addition to investigating the commands
568 in the frame and the pipeline, the vendor-specific tools allow looking at timings and
569 hardware performance information, which is not something simple frame captures can provide.
570
571 \li For AMD-based systems, the \l{https://gpuopen.com/rgp/}{Radeon GPU
572 Profiler} can be used to gain deeper insights into the application's
573 rendering and its performance.
574
575 \li Overlays showing live performance information can be highly useful as well, and
576 are often preferable to implementing simple frames-per-second counters within the
577 application itself, since they are more reliable and show more information. An example
578 is \l{https://game.intel.com/us/intel-presentmon/}{PresentMon}, which supports
579 graphics hardware from multiple vendors.
580
581 \li As QRhi supports Direct 3D 12, using
582 \l{https://devblogs.microsoft.com/pix/download/}{PIX}, a performance tuning
583 and debugging tool for DirectX 12 games on Windows is an option as well.
584
585 \li On macOS,
586 \l{https://developer.apple.com/documentation/metal/debugging_tools/viewing_your_gpu_workload_with_the_metal_debugger}{the
587 XCode Metal debugger} can be used to take and introspect frame
588 captures, to investigate performance details, and debug shaders. In macOS 13 it is also possible
589 to enable an overlay that displays frame rate and other information for any Metal-based window by
590 setting the environment variable \c{MTL_HUD_ENABLED=1}.
591
592 \endlist
593
594 On mobile and embedded platforms, there may be vendor and platform-specific
595 tools, provided by the GPU or SoC vendor, available to perform performance
596 profiling of application using OpenGL ES or Vulkan.
597
598 When capturing frames, remember that objects and groups of commands can be
599 named via debug markers, as long as \l{QRhi::EnableDebugMarkers}{debug
600 markers were enabled} for the QRhi, and the graphics API in use supports
601 this. To annotate the command stream, call
602 \l{QRhiCommandBuffer::debugMarkBegin()}{debugMarkBegin()},
603 \l{QRhiCommandBuffer::debugMarkEnd()}{debugMarkEnd()} and/or
604 \l{QRhiCommandBuffer::debugMarkMsg()}{debugMarkMsg()}.
605 This can be particularly useful in larger frames with multiple render passes.
606 Resources are named by calling \l{QRhiResource::setName()}{setName()} before create().
607
608 To perform basic timing measurements on the CPU and GPU side within the
609 application, \l QElapsedTimer and
610 \l QRhiCommandBuffer::lastCompletedGpuTime() can be used. The latter is
611 only available with select graphics APIs at the moment and requires opting
612 in via the \l QRhi::EnableTimestamps flag.
613
614 \section2 Resource leak checking
615
616 When destroying a QRhi object without properly destroying all buffers,
617 textures, and other resources created from it, warnings about this are
618 printed to the debug output whenever the application is a debug build, or
619 when the \c QT_RHI_LEAK_CHECK environment variable is set to a non-zero
620 value. This is a simple way to discover design issues around resource
621 handling within the application rendering logic. Note however that some
622 platforms and underlying graphics APIs may perform their own allocation and
623 resource leak detection as well, over which Qt will have no direct control.
624 For example, when using Vulkan, the memory allocator may raise failing
625 assertions in debug builds when resources that own graphics memory
626 allocations are not destroyed before the QRhi. In addition, the Vulkan
627 validation layer, when enabled, will issue warnings about native graphics
628 resources that were not released. Similarly, with Direct 3D warnings may
629 get printed about unreleased COM objects when the application does not
630 destroy the QRhi and its resources in the correct order.
631
632 \sa {RHI Window Example}, QRhiCommandBuffer, QRhiResourceUpdateBatch,
633 QRhiShaderResourceBindings, QShader, QRhiBuffer, QRhiTexture,
634 QRhiRenderBuffer, QRhiSampler, QRhiTextureRenderTarget,
635 QRhiGraphicsPipeline, QRhiComputePipeline, QRhiSwapChain
636 */
637
638/*!
639 \enum QRhi::Implementation
640 Describes which graphics API-specific backend gets used by a QRhi instance.
641
642 \value Null
643 \value Vulkan
644 \value OpenGLES2
645 \value D3D11
646 \value D3D12
647 \value Metal
648 */
649
650/*!
651 \enum QRhi::Flag
652 Describes what special features to enable.
653
654 \value EnableDebugMarkers Enables debug marker groups. Without this frame
655 debugging features like making debug groups and custom resource name
656 visible in external GPU debugging tools will not be available and functions
657 like QRhiCommandBuffer::debugMarkBegin() will become no-ops. Avoid enabling
658 in production builds as it may involve a small performance impact. Has no
659 effect when the QRhi::DebugMarkers feature is not reported as supported.
660
661 \value EnableTimestamps Enables GPU timestamp collection. When not set,
662 QRhiCommandBuffer::lastCompletedGpuTime() always returns 0. Enable this
663 only when needed since there may be a small amount of extra work involved
664 (e.g. timestamp queries), depending on the underlying graphics API. Has no
665 effect when the QRhi::Timestamps feature is not reported as supported.
666
667 \value PreferSoftwareRenderer Indicates that backends should prefer
668 choosing an adapter or physical device that renders in software on the CPU.
669 For example, with Direct3D there is typically a "Basic Render Driver"
670 adapter available with \c{DXGI_ADAPTER_FLAG_SOFTWARE}. Setting this flag
671 requests the backend to choose that adapter over any other, as long as no
672 specific adapter was forced by other backend-specific means. With Vulkan
673 this maps to preferring physical devices with
674 \c{VK_PHYSICAL_DEVICE_TYPE_CPU}. When not available, or when it is not
675 possible to decide if an adapter/device is software-based, this flag is
676 ignored. It may also be ignored with graphics APIs that have no concept and
677 means of enumerating adapters/devices.
678
679 \value EnablePipelineCacheDataSave Enables retrieving the pipeline cache
680 contents, where applicable. When not set, pipelineCacheData() will return
681 an empty blob always. With backends where retrieving and restoring the
682 pipeline cache contents is not supported, the flag has no effect and the
683 serialized cache data is always empty. The flag provides an opt-in
684 mechanism because the cost of maintaining the related data structures is
685 not insignificant with some backends. With Vulkan this feature maps
686 directly to VkPipelineCache, vkGetPipelineCacheData and
687 VkPipelineCacheCreateInfo::pInitialData. With Direct3D 11 there is no real
688 pipline cache, but the results of HLSL->DXBC compilations are stored and
689 can be serialized/deserialized via this mechanism. This allows skipping the
690 time consuming D3DCompile() in future runs of the applications for shaders
691 that come with HLSL source instead of offline pre-compiled bytecode. This
692 can provide a huge boost in startup and load times, if there is a lot of
693 HLSL source compilation happening. With OpenGL the "pipeline cache" is
694 simulated by retrieving and loading shader program binaries (if supported
695 by the driver). With OpenGL there are additional, disk-based caching
696 mechanisms for shader/program binaries provided by Qt. Writing to those may
697 get disabled whenever this flag is set since storing program binaries to
698 multiple caches is not sensible.
699
700 \value SuppressSmokeTestWarnings Indicates that, with backends where this
701 is relevant, certain, non-fatal QRhi::create() failures should not
702 produce qWarning() calls. For example, with D3D11, passing this flag
703 makes a number of warning messages (that appear due to QRhi::create()
704 failing) to become categorized debug prints instead under the commonly used
705 \c{qt.rhi.general} logging category. This can be used by engines, such as
706 Qt Quick, that feature fallback logic, i.e. they retry calling create()
707 with a different set of flags (such as, \l PreferSoftwareRenderer), in order
708 to hide the unconditional warnings from the output that would be printed
709 when the first create() attempt had failed.
710 */
711
712/*!
713 \enum QRhi::FrameOpResult
714 Describes the result of operations that can have a soft failure.
715
716 \value FrameOpSuccess Success
717
718 \value FrameOpError Unspecified error
719
720 \value FrameOpSwapChainOutOfDate The swapchain is in an inconsistent state
721 internally. This can be recoverable by attempting to repeat the operation
722 (such as, beginFrame()) later.
723
724 \value FrameOpDeviceLost The graphics device was lost. This can be
725 recoverable by attempting to repeat the operation (such as, beginFrame())
726 after releasing and reinitializing all objects backed by native graphics
727 resources. See isDeviceLost().
728 */
729
730/*!
731 \enum QRhi::Feature
732 Flag values to indicate what features are supported by the backend currently in use.
733
734 \value MultisampleTexture Indicates that textures with a sample count larger
735 than 1 are supported. In practice this feature will be unsupported with
736 OpenGL ES versions older than 3.1, and OpenGL older than 3.0.
737
738 \value MultisampleRenderBuffer Indicates that renderbuffers with a sample
739 count larger than 1 are supported. In practice this feature will be
740 unsupported with OpenGL ES 2.0, and may also be unsupported with OpenGL 2.x
741 unless the relevant extensions are present.
742
743 \value DebugMarkers Indicates that debug marker groups (and so
744 QRhiCommandBuffer::debugMarkBegin()) are supported.
745
746 \value Timestamps Indicates that command buffer timestamps are supported.
747 Relevant for QRhiCommandBuffer::lastCompletedGpuTime(). This can be
748 expected to be supported on Metal, Vulkan, Direct 3D 11 and 12, and OpenGL
749 contexts of version 3.3 or newer. However, with some of these APIs support
750 for timestamp queries is technically optional, and therefore it cannot be
751 guaranteed that this feature is always supported with every implementation
752 of them.
753
754 \value Instancing Indicates that instanced drawing is supported. In
755 practice this feature will be unsupported with OpenGL ES 2.0 and OpenGL
756 3.2 or older.
757
758 \value CustomInstanceStepRate Indicates that instance step rates other
759 than 1 are supported. In practice this feature will always be unsupported
760 with OpenGL. In addition, running with Vulkan 1.0 without
761 VK_EXT_vertex_attribute_divisor will also lead to reporting false for this
762 feature.
763
764 \value PrimitiveRestart Indicates that restarting the assembly of
765 primitives when encountering an index value of 0xFFFF
766 (\l{QRhiCommandBuffer::IndexUInt16}{IndexUInt16}) or 0xFFFFFFFF
767 (\l{QRhiCommandBuffer::IndexUInt32}{IndexUInt32}) is enabled, for certain
768 primitive topologies at least. QRhi will try to enable this with all
769 backends, but in some cases it will not be supported. Dynamically
770 controlling primitive restart is not possible since with some APIs
771 primitive restart with a fixed index is always on. Applications must assume
772 that whenever this feature is reported as supported, the above mentioned
773 index values \c may be treated specially, depending on the topology. The
774 only two topologies where primitive restart is guaranteed to behave
775 identically across backends, as long as this feature is reported as
776 supported, are \l{QRhiGraphicsPipeline::LineStrip}{LineStrip} and
777 \l{QRhiGraphicsPipeline::TriangleStrip}{TriangleStrip}.
778
779 \value NonDynamicUniformBuffers Indicates that creating buffers with the
780 usage \l{QRhiBuffer::UniformBuffer}{UniformBuffer} and the types
781 \l{QRhiBuffer::Immutable}{Immutable} or \l{QRhiBuffer::Static}{Static} is
782 supported. When reported as unsupported, uniform (constant) buffers must be
783 created as \l{QRhiBuffer::Dynamic}{Dynamic}. (which is recommended
784 regardless)
785
786 \value NonFourAlignedEffectiveIndexBufferOffset Indicates that effective
787 index buffer offsets (\c{indexOffset + firstIndex * indexComponentSize})
788 that are not 4 byte aligned are supported. When not supported, attempting
789 to issue a \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} with a
790 non-aligned effective offset may lead to unspecified behavior. Relevant in
791 particular for Metal, where this will be reported as unsupported.
792
793 \value NPOTTextureRepeat Indicates that the
794 \l{QRhiSampler::Repeat}{Repeat} wrap mode and mipmap filtering modes are
795 supported for textures with a non-power-of-two size. In practice this can
796 only be false with OpenGL ES 2.0 implementations without
797 \c{GL_OES_texture_npot}.
798
799 \value RedOrAlpha8IsRed Indicates that the
800 \l{QRhiTexture::RED_OR_ALPHA8}{RED_OR_ALPHA8} format maps to a one
801 component 8-bit \c red format. This is the case for all backends except
802 OpenGL when using either OpenGL ES or a non-core profile context. There
803 \c{GL_ALPHA}, a one component 8-bit \c alpha format, is used
804 instead. Using the special texture format allows having a single code
805 path for creating textures, leaving it up to the backend to decide the
806 actual format, while the feature flag can be used to pick the
807 appropriate shader variant for sampling the texture.
808
809 \value ElementIndexUint Indicates that 32-bit unsigned integer elements are
810 supported in the index buffer. In practice this is true everywhere except
811 when running on plain OpenGL ES 2.0 implementations without the necessary
812 extension. When false, only 16-bit unsigned elements are supported in the
813 index buffer.
814
815 \value Compute Indicates that compute shaders, image load/store, and
816 storage buffers are supported. OpenGL older than 4.3 and OpenGL ES older
817 than 3.1 have no compute support. This does not imply support for writing
818 storage buffers in fragment shaders; see FragmentStoresAndAtomics.
819
820 \value [since 6.13] FragmentStoresAndAtomics Indicates that fragment
821 shaders support storage buffer writes and 32-bit integer atomic operations
822 on storage buffers. This does not imply support for texture atomics,
823 floating-point atomics, or 64-bit atomics. Applications must also respect
824 the MaxFragmentStorageBuffers resource limit and any resource binding
825 limits imposed by the graphics API. In particular, Direct3D 11 shares
826 unordered access view slots with render target outputs.
827
828 \value WideLines Indicates that lines with a width other than 1 are
829 supported. When reported as not supported, the line width set on the
830 graphics pipeline state is ignored. This can always be false with some
831 backends (D3D11, D3D12, Metal). With Vulkan, the value depends on the
832 implementation. With OpenGL, wide lines are not supported in core profile
833 contexts.
834
835 \value VertexShaderPointSize Indicates that the size of rasterized points
836 set via \c{gl_PointSize} in the vertex shader is taken into account. When
837 reported as not supported, drawing points with a size other than 1 is not
838 supported. Setting \c{gl_PointSize} in the shader is still valid then, but
839 is ignored. (for example, when generating HLSL, the assignment is silently
840 dropped from the generated code) Note that some APIs (Metal, Vulkan)
841 require the point size to be set in the shader explicitly whenever drawing
842 points, even when the size is 1, as they do not automatically default to 1.
843
844 \value BaseVertex Indicates that
845 \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} supports the \c
846 vertexOffset argument. When reported as not supported, the vertexOffset
847 value in an indexed draw is ignored. In practice this feature will be
848 unsupported with OpenGL and OpenGL ES versions lower than 3.2, and with
849 Metal on older iOS devices, including the iOS Simulator.
850
851 \value BaseInstance Indicates that instanced draw commands support the \c
852 firstInstance argument. When reported as not supported, the firstInstance
853 value is ignored and the instance ID starts from 0. In practice this feature
854 will be unsupported with Metal on older iOS devices, including the iOS
855 Simulator, and with OpenGL ES, which has no support for draw calls with a
856 base instance at all. With OpenGL it needs version 4.2 or newer, or
857 \c GL_ARB_base_instance. Applications relying on a non-zero base instance
858 should be aware of the InstanceIndexIncludesBaseInstance feature as well.
859
860 \value TriangleFanTopology Indicates that QRhiGraphicsPipeline::setTopology()
861 supports QRhiGraphicsPipeline::TriangleFan. In practice this feature will be
862 unsupported with Metal and Direct 3D 11/12.
863
864 \value ReadBackNonUniformBuffer Indicates that
865 \l{QRhiResourceUpdateBatch::readBackBuffer()}{reading buffer contents} is
866 supported for QRhiBuffer instances with a usage different than
867 UniformBuffer. In practice this feature will be unsupported with OpenGL ES
868 2.0.
869
870 \value ReadBackNonBaseMipLevel Indicates that specifying a mip level other
871 than 0 is supported when reading back texture contents. When not supported,
872 specifying a non-zero level in QRhiReadbackDescription leads to returning
873 an all-zero image. In practice this feature will be unsupported with OpenGL
874 ES 2.0.
875
876 \value TexelFetch Indicates that texelFetch() and textureLod() are available
877 in shaders. In practice this will be reported as unsupported with OpenGL ES
878 2.0 and OpenGL 2.x contexts, because GLSL 100 es and versions before 130 do
879 not support these functions.
880
881 \value RenderToNonBaseMipLevel Indicates that specifying a mip level other
882 than 0 is supported when creating a QRhiTextureRenderTarget with a
883 QRhiTexture as its color attachment. When not supported, create() will fail
884 whenever the target mip level is not zero. In practice this feature will be
885 unsupported with OpenGL ES 2.0.
886
887 \value IntAttributes Indicates that specifying input attributes with
888 signed and unsigned integer types for a shader pipeline is supported. When
889 not supported,
890 \l{QRhiGraphicsPipeline::create()}{QRhiGraphicsPipeline::create()} will
891 succeed but show a warning message and the values of the target attributes
892 will be broken. In practice this feature will be unsupported with OpenGL ES
893 2.0 and OpenGL 2.x.
894
895 \value ScreenSpaceDerivatives Indicates that functions such as dFdx(),
896 dFdy(), and fwidth() are supported in shaders. In practice this feature will
897 be unsupported with OpenGL ES 2.0 without the GL_OES_standard_derivatives
898 extension.
899
900 \value ReadBackAnyTextureFormat Indicates that reading back texture
901 contents can be expected to work for any QRhiTexture::Format. Backends
902 other than OpenGL can be expected to return true for this feature. When
903 reported as false, which will typically happen with OpenGL, only the
904 formats QRhiTexture::RGBA8 and QRhiTexture::BGRA8 are guaranteed to be
905 supported for readbacks. In addition, with OpenGL, but not OpenGL ES,
906 reading back the 1 byte per component formats QRhiTexture::R8 and
907 QRhiTexture::RED_OR_ALPHA8 are supported as well, and so are the depth and
908 depth-stencil formats QRhiTexture::D16, D24, D24S8, D32F and D32FS8, as long
909 as the format is supported in the first place. Reading back floating
910 point formats QRhiTexture::RGBA16F and RGBA32F may work too with OpenGL, as
911 long as the implementation provides support for these, but QRhi can give no
912 guarantees, as indicated by this flag.
913
914 \value PipelineCacheDataLoadSave Indicates that the pipelineCacheData() and
915 setPipelineCacheData() functions are functional. When not supported, the
916 functions will not perform any action, the retrieved blob is always empty,
917 and thus no benefits can be expected from retrieving and, during a
918 subsequent run of the application, reloading the pipeline cache content.
919
920 \value ImageDataStride Indicates that specifying a custom stride (row
921 length) for raw image data in texture uploads is supported. When not
922 supported (which can happen when the underlying API is OpenGL ES 2.0 without
923 support for GL_UNPACK_ROW_LENGTH),
924 QRhiTextureSubresourceUploadDescription::setDataStride() must not be used.
925
926 \value RenderBufferImport Indicates that QRhiRenderBuffer::createFrom() is
927 supported. For most graphics APIs this is not sensible because
928 QRhiRenderBuffer encapsulates texture objects internally, just like
929 QRhiTexture. With OpenGL however, renderbuffer object exist as a separate
930 object type in the API, and in certain environments (for example, where one
931 may want to associated a renderbuffer object with an EGLImage object) it is
932 important to allow wrapping an existing OpenGL renderbuffer object with a
933 QRhiRenderBuffer.
934
935 \value ThreeDimensionalTextures Indicates that 3D textures are supported.
936 In practice this feature will be unsupported with OpenGL and OpenGL ES
937 versions lower than 3.0.
938
939 \value RenderTo3DTextureSlice Indicates that rendering to a slice in a 3D
940 texture is supported. This can be unsupported with Vulkan 1.0 due to
941 relying on VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT which is a Vulkan 1.1
942 feature.
943
944 \value TextureArrays Indicates that texture arrays are supported and
945 QRhi::newTextureArray() is functional. Note that even when texture arrays
946 are not supported, arrays of textures are still available as those are two
947 independent features.
948
949 \value Tessellation Indicates that the tessellation control and evaluation
950 stages are supported. When reported as supported, the topology of a
951 QRhiGraphicsPipeline can be set to
952 \l{QRhiGraphicsPipeline::Patches}{Patches}, the number of control points
953 can be set via
954 \l{QRhiGraphicsPipeline::setPatchControlPointCount()}{setPatchControlPointCount()},
955 and shaders for tessellation control and evaluation can be specified in the
956 QRhiShaderStage list. Tessellation shaders have portability issues between
957 APIs (for example, translating GLSL/SPIR-V to HLSL is problematic due to
958 the way hull shaders are structured, whereas Metal uses a somewhat
959 different tessellation pipeline than others), and therefore unexpected
960 issues may still arise, even though basic functionality is implemented
961 across all the underlying APIs. For Direct 3D in particular, handwritten
962 HLSL hull and domain shaders must be injected into each QShader for the
963 tessellation control and evaluation stages, respectively, since qsb cannot
964 generate these from SPIR-V. Note that isoline tessellation should be
965 avoided as it will not be supported by all backends. The maximum patch
966 control point count portable between backends is 32.
967
968 \value GeometryShader Indicates that the geometry shader stage is supported.
969 When supported, a geometry shader can be specified in the QRhiShaderStage
970 list. Geometry Shaders are considered an experimental feature in QRhi and
971 can only be expected to be supported with Vulkan, Direct 3D 11 and 12,
972 OpenGL (3.2+) and OpenGL ES (3.2+), assuming the implementation reports it
973 as supported at run time. Starting with Qt 6.11 geometry shaders are
974 automatically translated to HLSL, and therefore no injection of handwritten
975 HLSL geometry shaders is necessary anymore (but note that gl_in and
976 expressions such as gl_in[0].gl_Position are not supported; rather, pass the
977 position as an output variable from the vertex shader). Geometry shaders are
978 not supported with Metal.
979
980 \value TextureArrayRange Indicates that for
981 \l{QRhi::newTextureArray()}{texture arrays} it is possible to specify a
982 range that is exposed to the shaders. Normally all array layers are exposed
983 and it is up to the shader to select the layer (via the third coordinate
984 passed to texture() when sampling the \c sampler2DArray). When supported,
985 calling QRhiTexture::setArrayRangeStart() and
986 QRhiTexture::setArrayRangeLength() before
987 \l{QRhiTexture::create()}{building} or
988 \l{QRhiTexture::createFrom()}{importing} the native texture has an effect,
989 and leads to selecting only the specified range from the array. This will
990 be necessary in special cases, such as when working with accelerated video
991 decoding and Direct 3D 11, because a texture array with both
992 \c{D3D11_BIND_DECODER} and \c{D3D11_BIND_SHADER_RESOURCE} on it is only
993 usable as a shader resource if a single array layer is selected. Note that
994 all this is applicable only when the texture is used as a
995 QRhiShaderResourceBinding::SampledTexture or
996 QRhiShaderResourceBinding::Texture shader resource, and is not compatible
997 with image load/store. This feature is only available with some backends as
998 it does not map well to all graphics APIs, and it is only meant to provide
999 support for special cases anyhow. In practice the feature can be expected to
1000 be supported with Direct3D 11/12, Vulkan and Metal.
1001
1002 \value NonFillPolygonMode Indicates that setting a PolygonMode other than
1003 the default Fill is supported for QRhiGraphicsPipeline. A common use case
1004 for changing the mode to Line is to get wireframe rendering. This however
1005 is not available as a core OpenGL ES feature, and is optional with Vulkan
1006 as well as some mobile GPUs may not offer the feature.
1007
1008 \value OneDimensionalTextures Indicates that 1D textures are supported.
1009 In practice this feature will be unsupported on OpenGL ES.
1010
1011 \value OneDimensionalTextureMipmaps Indicates that generating 1D texture
1012 mipmaps is supported. In practice this feature will be unsupported on
1013 backends that do not report support for
1014 \l{OneDimensionalTextures}, Metal, and Direct 3D 12.
1015
1016 \value HalfAttributes Indicates that specifying input attributes with half
1017 precision (16bit) floating point types for a shader pipeline is supported.
1018 When not supported,
1019 \l{QRhiGraphicsPipeline::create()}{QRhiGraphicsPipeline::create()} will
1020 succeed but show a warning message and the values of the target attributes
1021 will be broken. In practice this feature will be unsupported in some OpenGL
1022 ES 2.0 and OpenGL 2.x
1023 implementations. Note that while Direct3D 11/12 does support half precision
1024 input attributes, it does not support the half3 type. The D3D backends pass
1025 half3 attributes as half4. To ensure cross platform compatibility, half3
1026 inputs should be padded to 8 bytes.
1027
1028 \value RenderToOneDimensionalTexture Indicates that 1D texture render
1029 targets are supported. In practice this feature will be unsupported on
1030 backends that do not report support for
1031 \l{OneDimensionalTextures}, and Metal.
1032
1033 \value ThreeDimensionalTextureMipmaps Indicates that generating 3D texture
1034 mipmaps is supported. This is typically supported with all backends starting
1035 with Qt 6.10.
1036
1037 \value MultiView Indicates that multiview, see e.g.
1038 \l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_multiview.html}{VK_KHR_multiview}
1039 is supported. With OpenGL ES 2.0, Direct 3D 11, and OpenGL (ES)
1040 implementations without \c{GL_OVR_multiview2} this feature will not be
1041 supported. With Vulkan 1.1 and newer, and Direct 3D 12 multiview is
1042 typically supported. When reported as supported, creating a
1043 QRhiTextureRenderTarget with a QRhiColorAttachment that references a texture
1044 array and has \l{QRhiColorAttachment::setMultiViewCount()}{multiViewCount}
1045 set enables recording a render pass that uses multiview rendering. In addition,
1046 any QRhiGraphicsPipeline used in that render pass must have
1047 \l{QRhiGraphicsPipeline::setMultiViewCount()}{the same view count set}. Note that
1048 multiview is only available in combination with 2D texture arrays. It cannot
1049 be used to optimize the rendering into individual textures (e.g. two, for
1050 the left and right eyes). Rather, the target of a multiview render pass is
1051 always a texture array, automatically rendering to the layer (array element)
1052 corresponding to each view. Therefore this feature implies \l TextureArrays
1053 as well. Multiview rendering is not supported in combination with
1054 tessellation or geometry shaders. See QRhiColorAttachment::setMultiViewCount()
1055 for further details on multiview rendering. This enum value has been introduced in Qt 6.7.
1056
1057 \value TextureViewFormat Indicates that setting a
1058 \l{QRhiTexture::setWriteViewFormat()}{view format} on a QRhiTexture is
1059 effective. When reported as supported, setting the read (sampling) or write
1060 (render target / image load-store) view mode changes the texture's viewing
1061 format. When unsupported, setting a view format has no effect. Note that Qt
1062 has no knowledge or control over format compatibility or resource view rules
1063 in the underlying 3D API and its implementation. Passing in unsuitable,
1064 incompatible formats may lead to errors and unspecified behavior. This is
1065 provided mainly to allow "casting" rendering into a texture created with an
1066 sRGB format to non-sRGB to avoid the unwanted linear->sRGB conversion on
1067 shader writes. Other types of casting may or may not be functional,
1068 depending on the underlying API. Currently implemented for Vulkan and Direct
1069 3D 12 and Metal. With D3D12 the feature is available only if
1070 \c CastingFullyTypedFormatSupported is supported, see
1071 \l{https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html} (and
1072 note that QRhi always uses fully typed formats for textures.) This enum
1073 value has been introduced in Qt 6.8.
1074
1075 \value ResolveDepthStencil Indicates that resolving a multisample depth or
1076 depth-stencil texture is supported. Otherwise,
1077 \l{QRhiTextureRenderTargetDescription::setDepthResolveTexture()}{setting a
1078 depth resolve texture} is not functional and must be avoided. Direct 3D 11
1079 and 12 have no support for resolving depth/depth-stencil formats, and
1080 therefore this feature will never be supported with those. Vulkan 1.0 has no
1081 API to request resolving a depth-stencil attachment. Therefore, with Vulkan
1082 this feature will only be supported with Vulkan 1.2 and up, and on 1.1
1083 implementations with the appropriate extensions present. This feature is
1084 provided for the rare case when resolving into a non-multisample depth
1085 texture becomes necessary, for example when rendering into an
1086 OpenXR-provided depth texture (XR_KHR_composition_layer_depth). This enum
1087 value has been introduced in Qt 6.8.
1088
1089 \value VariableRateShading Indicates that per-draw (per-pipeline) variable
1090 rate shading is supported. When reported as supported, \l
1091 QRhiCommandBuffer::setShadingRate() is functional and has an effect for
1092 QRhiGraphicsPipeline objects that declared \l
1093 QRhiGraphicsPipeline::UsesShadingRate in their flags. Call \l
1094 QRhi::supportedShadingRates() to check which rates are supported. (1x1 is
1095 always supported, other typical values are 2x2, 1x2, 2x1, 2x4, 4x2, 4x4).
1096 This feature can be expected to be supported with Direct 3D 12 and Vulkan,
1097 assuming the implementation and GPU used at run time supports VRS. This enum
1098 value has been introduced in Qt 6.9.
1099
1100 \value VariableRateShadingMap Indicates that image-based specification of
1101 the shading rate is possible. The "image" is not necessarily a texture, it
1102 may be a native 3D API object, depending on the underlying backend and
1103 graphics API at run time. In practice this feature can be expected to be
1104 supported with Direct 3D 12, Vulkan, and Metal, assuming the GPU is modern
1105 enough to support VRS. To check if D3D12/Vulkan-style image-based VRS is
1106 supported, use VariableRateShadingMapWithTexture instead. When this feature
1107 is reported as supported, there are two possibilities: when
1108 VariableRateShadingMapWithTexture is also true, then QRhiShadingRateMap
1109 consumes QRhiTexture objects via the createFrom() overload taking a
1110 QRhiTexture argument. When VariableRateShadingMapWithTexture is false, then
1111 QRhiShadingRateMap consumes some other type of native objects, for example
1112 an MTLRasterizationRateMap in case of Metal. Use the createFrom() overload
1113 taking a NativeShadingRateMap in this case. This enum value has been
1114 introduced in Qt 6.9.
1115
1116 \value VariableRateShadingMapWithTexture Indicates that image-based
1117 specification of the shading rate is supported via regular textures. In
1118 practice this may be supported with Direct 3D 12 and Vulkan. This enum value
1119 has been introduced in Qt 6.9.
1120
1121 \value PerRenderTargetBlending Indicates that per rendertarget blending is
1122 supported i.e. different render targets in MRT framebuffer can have different
1123 blending modes. In practice this can be expected to be supported everywhere
1124 except OpenGL ES, where it is only available with GLES 3.2 implementations.
1125 This enum value has been introduced in Qt 6.9.
1126
1127 \value SampleVariables Indicates that gl_SampleID, gl_SamplePosition,
1128 gl_SampleMaskIn and gl_SampleMask variables are available in fragment shaders.
1129 In practice this can be expected to be supported everywhere except OpenGL ES,
1130 where it is only available with GLES 3.2 implementations.
1131 This enum value has been introduced in Qt 6.9.
1132
1133 \value InstanceIndexIncludesBaseInstance Indicates that \c gl_InstanceIndex
1134 includes the base instance (the \c firstInstance argument in draw calls) in
1135 its value. When this feature is unsupported, but BaseInstance is, it
1136 indicates that \c gl_InstanceIndex always starts at 0, not the base value.
1137 In practice this will be the case for Direct 3D 11 and 12 at the moment.
1138 With Vulkan and Metal this feature is expected to be reported as supported
1139 always. This enum value has been introduced in Qt 6.11.
1140
1141 \value [since 6.11] DepthClamp Indicates that enabling depth clamping is
1142 supported. When reported as unsupported, which will be the case with OpenGL
1143 ES, OpenGL versions before 3.2 without the relevant extension present, and
1144 Metal on the iOS Simulator, calling \l{QRhiGraphicsPipeline::setDepthClamp()}
1145 with an argument of \c true has no effect.
1146
1147 \value [since 6.12] DrawIndirect Indicates that the
1148 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
1149 and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}
1150 functions are available.
1151 In practice this can be expected to be supported everywhere except on
1152 OpenGL ES < 3.1.
1153
1154 \value [since 6.12] DrawIndirectMulti Indicates that a drawCount > 1 is natively
1155 supported by the backend in \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
1156 and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}.
1157 Otherwise, multiple draw calls are issued on the CPU by the RHI.
1158 In practice this can be expected to be supported on Vulkan 1.1+, OpenGL
1159 4.3+, D3D12, and Metal.
1160
1161 \value [since 6.12] ShaderDrawParameters Indicates that the \c{gl_BaseInstance},
1162 \c{gl_BaseVertex} and \c{gl_DrawID} built-in variables are available in shaders.
1163 In practice this can be expected to be supported on Vulkan 1.1+ and with desktop OpenGL
1164 4.6 or \c{GL_ARB_shader_draw_parameters}.
1165
1166 \value [since 6.13] DispatchIndirect Indicates that the
1167 \l{QRhiCommandBuffer::dispatchIndirect()}{dispatchIndirect()} function is
1168 available, allowing compute work group counts to be sourced from a
1169 \l QRhiBuffer at execution time. In practice this can be expected to be
1170 supported wherever the \l Compute feature is reported as supported, that is,
1171 on Vulkan, OpenGL 4.3+ / OpenGL ES 3.1+, Direct3D 11/12, and Metal.
1172
1173 \value [since 6.13] DrawIndirectCount Indicates that the
1174 \l{QRhiCommandBuffer::drawIndirectCount()}{drawIndirectCount()} and
1175 \l{QRhiCommandBuffer::drawIndexedIndirectCount()}{drawIndexedIndirectCount()}
1176 functions are available. These are GPU-driven multi-draw variants where the
1177 actual draw count is read from a buffer at execution time, capped to a
1178 CPU-supplied \c maxDrawCount. In practice this can be expected to be
1179 supported with Vulkan 1.2 and newer, when both the \c drawIndirectCount and
1180 \c multiDrawIndirect device features are present, with OpenGL 4.6 or when
1181 \c GL_ARB_indirect_parameters is available, with Direct3D 12, and with Metal
1182 on devices supporting Metal 3 and indirect command buffers. Direct3D 11 does
1183 not expose an equivalent entry point. Note that with Vulkan the two device
1184 features are queried from the physical device. When importing an existing
1185 VkDevice, the application must make sure the features were enabled when that
1186 device was created, because this cannot be queried afterwards. With Metal
1187 there is a further requirement that this feature flag cannot reflect: the
1188 graphics pipeline must have
1189 \l{QRhiGraphicsPipeline::UsesIndirectDraws}{UsesIndirectDraws} set, without
1190 which the draw is skipped with a warning.
1191
1192 \value [since 6.13] BufferToBufferCopy Indicates that the
1193 \l{QRhiResourceUpdateBatch::copyBuffer()}{copyBuffer()} function is
1194 available, allowing the contents of a QRhiBuffer to be copied into another
1195 QRhiBuffer on the GPU, without a readback to the CPU. In practice this can
1196 be expected to be supported everywhere except with OpenGL ES 2.0 and
1197 desktop OpenGL versions before 3.1 without \c GL_ARB_copy_buffer, which
1198 have no \c glCopyBufferSubData. There is no fallback on such systems
1199 because OpenGL ES 2.0 provides no way of reading back the contents of a
1200 buffer either.
1201
1202 \value [since 6.13] PushConstants Indicates that
1203 \l{QRhiCommandBuffer::setPushConstants()}{setPushConstants()} is
1204 functional, meaning shaders can declare a \c{layout(push_constant)} block
1205 and the data for it can be updated between draw calls without involving a
1206 QRhiShaderResourceBindings. The maximum size of the block is reported by
1207 the \l{QRhi::MaxPushConstantsSize}{MaxPushConstantsSize} resource limit.
1208 Vulkan, Metal and Direct3D 12 have a native equivalent. OpenGL and
1209 Direct3D 11 emulate it, with plain uniforms and with a small dynamic
1210 constant buffer, respectively, so there an update costs about as much as
1211 updating a small uniform buffer; what is gained is not having to have a
1212 QRhiShaderResourceBindings per draw call. There is one case where the
1213 feature is reported as supported but does not apply: with Metal, push
1214 constants are not supported with a graphics pipeline that uses
1215 tessellation.
1216
1217 \value [since 6.13] StaticBuffersOnGpuTimeline Indicates that updates of
1218 QRhiBuffer objects with a type of QRhiBuffer::Immutable or
1219 QRhiBuffer::Static are recorded into the command stream, and so are
1220 executed on the GPU timeline, in the order they were recorded in. In
1221 particular this means that
1222 \l{QRhiResourceUpdateBatch::uploadStaticBuffer()}{uploadStaticBuffer()} and
1223 \l{QRhiResourceUpdateBatch::copyBuffer()}{copyBuffer()} targeting the same
1224 buffer within one \l QRhiResourceUpdateBatch take effect in the recorded
1225 order. When this is reported as not supported, uploads are implemented by
1226 writing to host visible memory on an unrelated timeline, and the ordering
1227 between the two kinds of updates is undefined. In practice this is only
1228 relevant with Metal: the feature is not supported there when the Metal
1229 device does not report an Apple GPU, which is the case on Intel-based Macs,
1230 and also in virtual machines where the paravirtualized device does not
1231 advertise an Apple GPU family. Note that this says nothing about when the
1232 contents become visible to the CPU or to subsequent draw calls, which is
1233 always taken care of by QRhi.
1234 */
1235
1236/*!
1237 \enum QRhi::BeginFrameFlag
1238 Flag values for QRhi::beginFrame()
1239 */
1240
1241/*!
1242 \enum QRhi::EndFrameFlag
1243 Flag values for QRhi::endFrame()
1244
1245 \value SkipPresent Specifies that no present command is to be queued or no
1246 swapBuffers call is to be made. This way no image is presented. Generating
1247 multiple frames with all having this flag set is not recommended (except,
1248 for example, for benchmarking purposes - but keep in mind that backends may
1249 behave differently when it comes to waiting for command completion without
1250 presenting so the results are not comparable between them)
1251 */
1252
1253/*!
1254 \enum QRhi::ResourceLimit
1255 Describes the resource limit to query.
1256
1257 \value TextureSizeMin Minimum texture width and height. This is typically
1258 1. The minimum texture size is handled gracefully, meaning attempting to
1259 create a texture with an empty size will instead create a texture with the
1260 minimum size.
1261
1262 \value TextureSizeMax Maximum texture width and height. This depends on the
1263 graphics API and sometimes the platform or implementation as well.
1264 Typically the value is in the range 4096 - 16384. Attempting to create
1265 textures larger than this is expected to fail.
1266
1267 \value MaxColorAttachments The maximum number of color attachments for a
1268 QRhiTextureRenderTarget, in case multiple render targets are supported. When
1269 MRT is not supported, the value is 1. Otherwise this is typically 8, but
1270 watch out for the fact that OpenGL only mandates 4 as the minimum, and that
1271 is what some OpenGL ES implementations provide.
1272
1273 \value FramesInFlight The number of frames the backend may keep "in
1274 flight": with backends like Vulkan or Metal, it is the responsibility of
1275 QRhi to block whenever starting a new frame and finding the CPU is already
1276 \c{N - 1} frames ahead of the GPU (because the command buffer submitted in
1277 frame no. \c{current} - \c{N} has not yet completed). The value N is what
1278 is returned from here, and is typically 2. This can be relevant to
1279 applications that integrate rendering done directly with the graphics API,
1280 as such rendering code may want to perform double (if the value is 2)
1281 buffering for resources, such as, buffers, similarly to the QRhi backends
1282 themselves. The current frame slot index (a value running 0, 1, .., N-1,
1283 then wrapping around) is retrievable from QRhi::currentFrameSlot(). The
1284 value is 1 for backends where the graphics API offers no such low level
1285 control over the command submission process. Note that pipelining may still
1286 happen even when this value is 1 (some backends, such as D3D11, are
1287 designed to attempt to enable this, for instance, by using an update
1288 strategy for uniform buffers that does not stall the pipeline), but that is
1289 then not controlled by QRhi and so not reflected here in the API.
1290
1291 \value MaxAsyncReadbackFrames The number of \l{QRhi::endFrame()}{submitted}
1292 frames (including the one that contains the readback) after which an
1293 asynchronous texture or buffer readback is guaranteed to complete upon
1294 \l{QRhi::beginFrame()}{starting a new frame}.
1295
1296 \value MaxThreadGroupsPerDimension The maximum number of compute
1297 work/thread groups that can be dispatched. Effectively the maximum value
1298 for the arguments of QRhiCommandBuffer::dispatch(). Typically 65535.
1299
1300 \value MaxThreadsPerThreadGroup The maximum number of invocations in a
1301 single local work group, or in other terminology, the maximum number of
1302 threads in a thread group. Effectively the maximum value for the product of
1303 \c local_size_x, \c local_size_y, and \c local_size_z in the compute
1304 shader. Typical values are 128, 256, 512, 1024, or 1536. Watch out that
1305 both OpenGL ES and Vulkan specify only 128 as the minimum required limit
1306 for implementations. While uncommon for Vulkan, some OpenGL ES 3.1
1307 implementations for mobile/embedded devices only support the spec-mandated
1308 minimum value.
1309
1310 \value MaxThreadGroupX The maximum size of a work/thread group in the X
1311 dimension. Effectively the maximum value of \c local_size_x in the compute
1312 shader. Typically 256 or 1024.
1313
1314 \value MaxThreadGroupY The maximum size of a work/thread group in the Y
1315 dimension. Effectively the maximum value of \c local_size_y in the compute
1316 shader. Typically 256 or 1024.
1317
1318 \value MaxThreadGroupZ The maximum size of a work/thread group in the Z
1319 dimension. Effectively the maximum value of \c local_size_z in the compute
1320 shader. Typically 64 or 256.
1321
1322 \value TextureArraySizeMax Maximum texture array size. Typically in range
1323 256 - 2048. Attempting to \l{QRhi::newTextureArray()}{create a texture
1324 array} with more elements will likely fail.
1325
1326 \value MaxUniformBufferRange The number of bytes that can be exposed from a
1327 uniform buffer to the shaders at once. On OpenGL ES 2.0 and 3.0
1328 implementations this may be as low as 3584 bytes (224 four component, 32
1329 bits per component vectors). Elsewhere the value is typically 16384 (1024
1330 vec4s) or 65536 (4096 vec4s).
1331
1332 \value MaxVertexInputs The number of input attributes to the vertex shader.
1333 The location in a QRhiVertexInputAttribute must be in range \c{[0,
1334 MaxVertexInputs-1]}. The value may be as low as 8 with OpenGL ES 2.0.
1335 Elsewhere, typical values are 16, 31, or 32.
1336
1337 \value MaxVertexOutputs The maximum number of outputs (4 component vector
1338 \c out variables) from the vertex shader. The value may be as low as 8 with
1339 OpenGL ES 2.0, and 15 with OpenGL ES 3.0 and some Metal devices. Elsewhere,
1340 a typical value is 32.
1341
1342 \value ShadingRateImageTileSize The tile size for shading rate textures. 0
1343 if the QRhi::VariableRateShadingMapWithTexture feature is not supported.
1344 Otherwise a value such as 16, indicating, for example, a tile size of 16x16.
1345 Each byte in the (R8UI) shading rate texture defines then the shading rate
1346 for a tile of 16x16 pixels. See \l QRhiShadingRateMap for details.
1347
1348 \value [since 6.13] MaxVertexStorageBuffers The maximum number of
1349 storage buffers that can be bound for reading (bufferLoad) in the
1350 vertex stage. Can legitimately be 0: OpenGL ES makes vertex-stage
1351 storage blocks optional even on 3.1 and newer, and many mobile
1352 drivers report 0 while supporting them via Vulkan on the same GPU;
1353 Direct 3D 11 has no vertex-stage storage buffer support at all.
1354 Clients reading storage buffers in the vertex shader must therefore
1355 check this even when QRhi::Compute is supported. Write access can be
1356 more restricted than this value suggests: with Vulkan it additionally
1357 requires the vertexPipelineStoresAndAtomics device feature, and with
1358 Direct 3D 12 unordered access has lower, resource-binding-tier
1359 dependent limits. With Metal the value is the size of the buffer
1360 argument table, which is shared with vertex inputs and uniform
1361 buffers, so the full count is not available in combination with them.
1362
1363 \value [since 6.13] MaxFragmentStorageBuffers The maximum number of
1364 storage buffers that can be bound for reading (bufferLoad) in the
1365 fragment stage. Like the vertex stage, this is optional in OpenGL ES
1366 (only compute-stage storage blocks are mandatory), so 0 is a
1367 legitimate value. The write access and Metal argument table notes
1368 from MaxVertexStorageBuffers apply here as well; with Direct 3D 11
1369 the value reflects the unordered access view slots, which are shared
1370 with render target outputs. Writing storage buffers in fragment shaders
1371 additionally requires the FragmentStoresAndAtomics feature.
1372
1373 \value [since 6.13] MaxPushConstantsSize The maximum size in bytes of the
1374 push constant block a shader can declare. 0 when the
1375 \l{QRhi::PushConstants}{PushConstants} feature is not supported.
1376 Portable code should stay within 128 bytes: that is what Direct3D 11 and
1377 12 and OpenGL report and what Vulkan guarantees, whereas Metal reports
1378 4096. Note that with Direct3D 12 even 128 is optimistic, because a block
1379 that size takes 32 of the 64 root signature DWORDs, so with a
1380 sufficiently large QRhiShaderResourceBindings the root signature can
1381 still fail to build. With OpenGL the block competes for the uniform
1382 budget with everything else in the shader.
1383 */
1384
1385/*!
1386 \class QRhiInitParams
1387 \inmodule QtGuiPrivate
1388 \inheaderfile rhi/qrhi.h
1389 \since 6.6
1390 \brief Base class for backend-specific initialization parameters.
1391
1392 Contains fields that are relevant to all backends.
1393
1394 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1395 for details.
1396 */
1397
1398/*!
1399 \class QRhiDepthStencilClearValue
1400 \inmodule QtGuiPrivate
1401 \inheaderfile rhi/qrhi.h
1402 \since 6.6
1403 \brief Specifies clear values for a depth or stencil buffer.
1404
1405 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1406 for details.
1407 */
1408
1409/*!
1410 \fn QRhiDepthStencilClearValue::QRhiDepthStencilClearValue() = default
1411
1412 Constructs a depth/stencil clear value with depth clear value 1.0f and
1413 stencil clear value 0.
1414 */
1415
1416/*!
1417 Constructs a depth/stencil clear value with depth clear value \a d and
1418 stencil clear value \a s.
1419 */
1420QRhiDepthStencilClearValue::QRhiDepthStencilClearValue(float d, quint32 s)
1421 : m_d(d),
1422 m_s(s)
1423{
1424}
1425
1426/*!
1427 \fn float QRhiDepthStencilClearValue::depthClearValue() const
1428 \return the depth clear value. In most cases this is 1.0f.
1429 */
1430
1431/*!
1432 \fn void QRhiDepthStencilClearValue::setDepthClearValue(float d)
1433 Sets the depth clear value to \a d.
1434 */
1435
1436/*!
1437 \fn quint32 QRhiDepthStencilClearValue::stencilClearValue() const
1438 \return the stencil clear value. In most cases this is 0.
1439 */
1440
1441/*!
1442 \fn void QRhiDepthStencilClearValue::setStencilClearValue(quint32 s)
1443 Sets the stencil clear value to \a s.
1444 */
1445
1446/*!
1447 \fn bool QRhiDepthStencilClearValue::operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1448
1449 \return \c true if the values in the two QRhiDepthStencilClearValue objects
1450 \a a and \a b are equal.
1451 */
1452
1453/*!
1454 \fn bool QRhiDepthStencilClearValue::operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1455
1456 \return \c false if the values in the two QRhiDepthStencilClearValue
1457 objects \a a and \a b are equal; otherwise returns \c true.
1458
1459*/
1460
1461/*!
1462 \fn size_t QRhiDepthStencilClearValue::qHash(const QRhiDepthStencilClearValue &key, size_t seed)
1463 \qhash{QRhiDepthStencilClearValue}
1464 */
1465
1466#ifndef QT_NO_DEBUG_STREAM
1467QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
1468{
1469 QDebugStateSaver saver(dbg);
1470 dbg.nospace() << "QRhiDepthStencilClearValue(depth-clear=" << v.depthClearValue()
1471 << " stencil-clear=" << v.stencilClearValue()
1472 << ')';
1473 return dbg;
1474}
1475#endif
1476
1477/*!
1478 \class QRhiViewport
1479 \inmodule QtGuiPrivate
1480 \inheaderfile rhi/qrhi.h
1481 \since 6.6
1482 \brief Specifies a viewport rectangle.
1483
1484 Used with QRhiCommandBuffer::setViewport().
1485
1486 QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
1487 bottom-left. Negative width or height are not allowed.
1488
1489 Typical usage is like the following:
1490
1491 \code
1492 const QSize outputSizeInPixels = swapchain->currentPixelSize();
1493 const QRhiViewport viewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height());
1494 cb->beginPass(swapchain->currentFrameRenderTarget(), Qt::black, { 1.0f, 0 });
1495 cb->setGraphicsPipeline(ps);
1496 cb->setViewport(viewport);
1497 // ...
1498 \endcode
1499
1500 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1501 for details.
1502
1503 \sa QRhiCommandBuffer::setViewport(), QRhi::clipSpaceCorrMatrix(), QRhiScissor
1504 */
1505
1506/*!
1507 \fn QRhiViewport::QRhiViewport() = default
1508
1509 Constructs a viewport description with an empty rectangle and a depth range
1510 of 0.0f - 1.0f.
1511
1512 \sa QRhi::clipSpaceCorrMatrix()
1513 */
1514
1515/*!
1516 Constructs a viewport description with the rectangle specified by \a x, \a
1517 y, \a w, \a h and the depth range \a minDepth and \a maxDepth.
1518
1519 \note \a x and \a y are assumed to be the bottom-left position. \a w and \a
1520 h should not be negative, the viewport will be ignored by
1521 QRhiCommandBuffer::setViewport() otherwise.
1522
1523 \sa QRhi::clipSpaceCorrMatrix()
1524 */
1525QRhiViewport::QRhiViewport(float x, float y, float w, float h, float minDepth, float maxDepth)
1526 : m_rect { { x, y, w, h } },
1527 m_minDepth(minDepth),
1528 m_maxDepth(maxDepth)
1529{
1530}
1531
1532/*!
1533 \fn std::array<float, 4> QRhiViewport::viewport() const
1534 \return the viewport x, y, width, and height.
1535 */
1536
1537/*!
1538 \fn void QRhiViewport::setViewport(float x, float y, float w, float h)
1539 Sets the viewport's position and size to \a x, \a y, \a w, and \a h.
1540
1541 \note Viewports are specified in a coordinate system that has its origin in
1542 the bottom-left.
1543 */
1544
1545/*!
1546 \fn float QRhiViewport::minDepth() const
1547 \return the minDepth value of the depth range of the viewport.
1548 */
1549
1550/*!
1551 \fn void QRhiViewport::setMinDepth(float minDepth)
1552 Sets the \a minDepth of the depth range of the viewport.
1553 By default this is set to 0.0f.
1554 */
1555
1556/*!
1557 \fn float QRhiViewport::maxDepth() const
1558 \return the maxDepth value of the depth range of the viewport.
1559 */
1560
1561/*!
1562 \fn void QRhiViewport::setMaxDepth(float maxDepth)
1563 Sets the \a maxDepth of the depth range of the viewport.
1564 By default this is set to 1.0f.
1565 */
1566
1567/*!
1568 \fn bool QRhiViewport::operator==(const QRhiViewport &a, const QRhiViewport &b) noexcept
1569
1570 \return \c true if the values in the two QRhiViewport objects
1571 \a a and \a b are equal.
1572 */
1573
1574/*!
1575 \fn bool QRhiViewport::operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept
1576
1577 \return \c false if the values in the two QRhiViewport
1578 objects \a a and \a b are equal; otherwise returns \c true.
1579*/
1580
1581/*!
1582 \fn size_t QRhiViewport::qHash(const QRhiViewport &key, size_t seed)
1583 \qhash{QRhiViewport}
1584 */
1585
1586#ifndef QT_NO_DEBUG_STREAM
1587QDebug operator<<(QDebug dbg, const QRhiViewport &v)
1588{
1589 QDebugStateSaver saver(dbg);
1590 const std::array<float, 4> r = v.viewport();
1591 dbg.nospace() << "QRhiViewport(bottom-left-x=" << r[0]
1592 << " bottom-left-y=" << r[1]
1593 << " width=" << r[2]
1594 << " height=" << r[3]
1595 << " minDepth=" << v.minDepth()
1596 << " maxDepth=" << v.maxDepth()
1597 << ')';
1598 return dbg;
1599}
1600#endif
1601
1602/*!
1603 \class QRhiScissor
1604 \inmodule QtGuiPrivate
1605 \inheaderfile rhi/qrhi.h
1606 \since 6.6
1607 \brief Specifies a scissor rectangle.
1608
1609 Used with QRhiCommandBuffer::setScissor(). Setting a scissor rectangle is
1610 only possible with a QRhiGraphicsPipeline that has
1611 QRhiGraphicsPipeline::UsesScissor set.
1612
1613 QRhi assumes OpenGL-style scissor coordinates, meaning x and y are
1614 bottom-left. Negative width or height are not allowed. However, apart from
1615 that, the flexible OpenGL semantics apply: negative x and y, partially out
1616 of bounds rectangles, etc. will be handled gracefully, clamping as
1617 appropriate. Therefore, any rendering logic targeting OpenGL can feed
1618 scissor rectangles into QRhiScissor as-is, without any adaptation.
1619
1620 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1621 for details.
1622
1623 \sa QRhiCommandBuffer::setScissor(), QRhiViewport
1624 */
1625
1626/*!
1627 \fn QRhiScissor::QRhiScissor() = default
1628
1629 Constructs an empty scissor.
1630 */
1631
1632/*!
1633 Constructs a scissor with the rectangle specified by \a x, \a y, \a w, and
1634 \a h.
1635
1636 \note \a x and \a y are assumed to be the bottom-left position. Negative \a w
1637 or \a h are not allowed, such scissor rectangles will be ignored by
1638 QRhiCommandBuffer. Other than that, the flexible OpenGL semantics apply:
1639 negative x and y, partially out of bounds rectangles, etc. will be handled
1640 gracefully, clamping as appropriate.
1641 */
1642QRhiScissor::QRhiScissor(int x, int y, int w, int h)
1643 : m_rect { { x, y, w, h } }
1644{
1645}
1646
1647/*!
1648 \fn std::array<int, 4> QRhiScissor::scissor() const
1649 \return the scissor position and size.
1650 */
1651
1652/*!
1653 \fn void QRhiScissor::setScissor(int x, int y, int w, int h)
1654 Sets the scissor position and size to \a x, \a y, \a w, \a h.
1655
1656 \note The position is always expected to be specified in a coordinate
1657 system that has its origin in the bottom-left corner, like OpenGL.
1658 */
1659
1660/*!
1661 \fn bool QRhiScissor::operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept
1662
1663 \return \c true if the values in the two QRhiScissor objects
1664 \a a and \a b are equal.
1665 */
1666
1667/*!
1668 \fn bool QRhiScissor::operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept
1669
1670 \return \c false if the values in the two QRhiScissor
1671 objects \a a and \a b are equal; otherwise returns \c true.
1672*/
1673
1674/*!
1675 \fn size_t QRhiScissor::qHash(const QRhiScissor &key, size_t seed)
1676 \qhash{QRhiScissor}
1677 */
1678
1679#ifndef QT_NO_DEBUG_STREAM
1680QDebug operator<<(QDebug dbg, const QRhiScissor &s)
1681{
1682 QDebugStateSaver saver(dbg);
1683 const std::array<int, 4> r = s.scissor();
1684 dbg.nospace() << "QRhiScissor(bottom-left-x=" << r[0]
1685 << " bottom-left-y=" << r[1]
1686 << " width=" << r[2]
1687 << " height=" << r[3]
1688 << ')';
1689 return dbg;
1690}
1691#endif
1692
1693/*!
1694 \class QRhiVertexInputBinding
1695 \inmodule QtGuiPrivate
1696 \inheaderfile rhi/qrhi.h
1697 \since 6.6
1698 \brief Describes a vertex input binding.
1699
1700 Specifies the stride (in bytes, must be a multiple of 4), the
1701 classification and optionally the instance step rate.
1702
1703 As an example, assume a vertex shader with the following inputs:
1704
1705 \badcode
1706 layout(location = 0) in vec4 position;
1707 layout(location = 1) in vec2 texcoord;
1708 \endcode
1709
1710 Now let's assume also that 3 component vertex positions \c{(x, y, z)} and 2
1711 component texture coordinates \c{(u, v)} are provided in a non-interleaved
1712 format in a buffer (or separate buffers even). Defining two bindings
1713 could then be done like this:
1714
1715 \code
1716 QRhiVertexInputLayout inputLayout;
1717 inputLayout.setBindings({
1718 { 3 * sizeof(float) },
1719 { 2 * sizeof(float) }
1720 });
1721 \endcode
1722
1723 Only the stride is interesting here since instancing is not used. The
1724 binding number is given by the index of the QRhiVertexInputBinding
1725 element in the bindings vector of the QRhiVertexInputLayout.
1726
1727 Once a graphics pipeline with this vertex input layout is bound, the vertex
1728 inputs could be set up like the following for drawing a cube with 36
1729 vertices, assuming we have a single buffer with first the positions and
1730 then the texture coordinates:
1731
1732 \code
1733 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1734 { cubeBuf, 0 },
1735 { cubeBuf, 36 * 3 * sizeof(float) }
1736 };
1737 cb->setVertexInput(0, 2, vbufBindings);
1738 \endcode
1739
1740 Note how the index defined by \c {startBinding + i}, where \c i is the
1741 index in the second argument of
1742 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}, matches the
1743 index of the corresponding entry in the \c bindings vector of the
1744 QRhiVertexInputLayout.
1745
1746 \note the stride must always be a multiple of 4.
1747
1748 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1749 for details.
1750
1751 \sa QRhiCommandBuffer::setVertexInput()
1752 */
1753
1754/*!
1755 \enum QRhiVertexInputBinding::Classification
1756 Describes the input data classification.
1757
1758 \value PerVertex Data is per-vertex
1759 \value PerInstance Data is per-instance
1760 */
1761
1762/*!
1763 \fn QRhiVertexInputBinding::QRhiVertexInputBinding() = default
1764
1765 Constructs a default vertex input binding description.
1766 */
1767
1768/*!
1769 Constructs a vertex input binding description with the specified \a stride,
1770 classification \a cls, and instance step rate \a stepRate.
1771
1772 \note \a stepRate other than 1 is only supported when
1773 QRhi::CustomInstanceStepRate is reported to be supported.
1774 */
1775QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cls, quint32 stepRate)
1776 : m_stride(stride),
1777 m_classification(cls),
1778 m_instanceStepRate(stepRate)
1779{
1780}
1781
1782/*!
1783 \fn quint32 QRhiVertexInputBinding::stride() const
1784 \return the stride in bytes.
1785 */
1786
1787/*!
1788 \fn void QRhiVertexInputBinding::setStride(quint32 s)
1789 Sets the stride to \a s.
1790 */
1791
1792/*!
1793 \fn QRhiVertexInputBinding::Classification QRhiVertexInputBinding::classification() const
1794 \return the input data classification.
1795 */
1796
1797/*!
1798 \fn void QRhiVertexInputBinding::setClassification(Classification c)
1799 Sets the input data classification \a c. By default this is set to PerVertex.
1800 */
1801
1802/*!
1803 \fn quint32 QRhiVertexInputBinding::instanceStepRate() const
1804 \return the instance step rate.
1805 */
1806
1807/*!
1808 \fn void QRhiVertexInputBinding::setInstanceStepRate(quint32 rate)
1809 Sets the instance step \a rate. By default this is set to 1.
1810 */
1811
1812/*!
1813 \fn bool QRhiVertexInputBinding::operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1814
1815 \return \c true if the values in the two QRhiVertexInputBinding objects
1816 \a a and \a b are equal.
1817 */
1818
1819/*!
1820 \fn bool QRhiVertexInputBinding::operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1821
1822 \return \c false if the values in the two QRhiVertexInputBinding
1823 objects \a a and \a b are equal; otherwise returns \c true.
1824*/
1825
1826/*!
1827 \fn size_t QRhiVertexInputBinding::qHash(const QRhiVertexInputBinding &key, size_t seed)
1828 \qhash{QRhiVertexInputBinding}
1829 */
1830
1831#ifndef QT_NO_DEBUG_STREAM
1832QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
1833{
1834 QDebugStateSaver saver(dbg);
1835 dbg.nospace() << "QRhiVertexInputBinding(stride=" << b.stride()
1836 << " cls=" << b.classification()
1837 << " step-rate=" << b.instanceStepRate()
1838 << ')';
1839 return dbg;
1840}
1841#endif
1842
1843/*!
1844 \class QRhiVertexInputAttribute
1845 \inmodule QtGuiPrivate
1846 \inheaderfile rhi/qrhi.h
1847 \since 6.6
1848 \brief Describes a single vertex input element.
1849
1850 The members specify the binding number, location, format, and offset for a
1851 single vertex input element.
1852
1853 \note For HLSL it is assumed that the vertex shader translated from SPIR-V
1854 uses
1855 \c{TEXCOORD<location>} as the semantic for each input. Hence no separate
1856 semantic name and index.
1857
1858 As an example, assume a vertex shader with the following inputs:
1859
1860 \badcode
1861 layout(location = 0) in vec4 position;
1862 layout(location = 1) in vec2 texcoord;
1863 \endcode
1864
1865 Now let's assume that we have 3 component vertex positions \c{(x, y, z)}
1866 and 2 component texture coordinates \c{(u, v)} are provided in a
1867 non-interleaved format in a buffer (or separate buffers even). Once two
1868 bindings are defined, the attributes could be specified as:
1869
1870 \code
1871 QRhiVertexInputLayout inputLayout;
1872 inputLayout.setBindings({
1873 { 3 * sizeof(float) },
1874 { 2 * sizeof(float) }
1875 });
1876 inputLayout.setAttributes({
1877 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1878 { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
1879 });
1880 \endcode
1881
1882 Once a graphics pipeline with this vertex input layout is bound, the vertex
1883 inputs could be set up like the following for drawing a cube with 36
1884 vertices, assuming we have a single buffer with first the positions and
1885 then the texture coordinates:
1886
1887 \code
1888 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1889 { cubeBuf, 0 },
1890 { cubeBuf, 36 * 3 * sizeof(float) }
1891 };
1892 cb->setVertexInput(0, 2, vbufBindings);
1893 \endcode
1894
1895 When working with interleaved data, there will typically be just one
1896 binding, with multiple attributes referring to that same buffer binding
1897 point:
1898
1899 \code
1900 QRhiVertexInputLayout inputLayout;
1901 inputLayout.setBindings({
1902 { 5 * sizeof(float) }
1903 });
1904 inputLayout.setAttributes({
1905 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1906 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
1907 });
1908 \endcode
1909
1910 and then:
1911
1912 \code
1913 const QRhiCommandBuffer::VertexInput vbufBinding(interleavedCubeBuf, 0);
1914 cb->setVertexInput(0, 1, &vbufBinding);
1915 \endcode
1916
1917 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1918 for details.
1919
1920 \sa QRhiCommandBuffer::setVertexInput()
1921 */
1922
1923/*!
1924 \enum QRhiVertexInputAttribute::Format
1925 Specifies the type of the element data.
1926
1927 \value Float4 Four component float vector
1928 \value Float3 Three component float vector
1929 \value Float2 Two component float vector
1930 \value Float Float
1931 \value UNormByte4 Four component normalized unsigned byte vector
1932 \value UNormByte2 Two component normalized unsigned byte vector
1933 \value UNormByte Normalized unsigned byte
1934 \value UInt4 Four component unsigned integer vector
1935 \value UInt3 Three component unsigned integer vector
1936 \value UInt2 Two component unsigned integer vector
1937 \value UInt Unsigned integer
1938 \value SInt4 Four component signed integer vector
1939 \value SInt3 Three component signed integer vector
1940 \value SInt2 Two component signed integer vector
1941 \value SInt Signed integer
1942 \value Half4 Four component half precision (16 bit) float vector
1943 \value Half3 Three component half precision (16 bit) float vector
1944 \value Half2 Two component half precision (16 bit) float vector
1945 \value Half Half precision (16 bit) float
1946 \value UShort4 Four component unsigned short (16 bit) integer vector
1947 \value UShort3 Three component unsigned short (16 bit) integer vector
1948 \value UShort2 Two component unsigned short (16 bit) integer vector
1949 \value UShort Unsigned short (16 bit) integer
1950 \value SShort4 Four component signed short (16 bit) integer vector
1951 \value SShort3 Three component signed short (16 bit) integer vector
1952 \value SShort2 Two component signed short (16 bit) integer vector
1953 \value SShort Signed short (16 bit) integer
1954
1955 \note Support for half precision floating point attributes is indicated at
1956 run time by the QRhi::Feature::HalfAttributes feature flag.
1957
1958 \note Direct3D 11/12 supports 16 bit input attributes, but does not support
1959 the Half3, UShort3 or SShort3 types. The D3D backends pass through Half3 as
1960 Half4, UShort3 as UShort4, and SShort3 as SShort4. To ensure cross platform
1961 compatibility, 16 bit inputs should be padded to 8 bytes.
1962 */
1963
1964/*!
1965 \fn QRhiVertexInputAttribute::QRhiVertexInputAttribute() = default
1966
1967 Constructs a default vertex input attribute description.
1968 */
1969
1970/*!
1971 Constructs a vertex input attribute description with the specified \a
1972 binding number, \a location, \a format, and \a offset.
1973
1974 \a matrixSlice should be -1 except when this attribute corresponds to a row
1975 or column of a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming
1976 4 consecutive vertex input locations), in which case it is the index of the
1977 row or column. \c{location - matrixSlice} must always be equal to the \c
1978 location for the first row or column of the unrolled matrix.
1979 */
1980QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset, int matrixSlice)
1981 : m_binding(binding),
1982 m_location(location),
1983 m_format(format),
1984 m_offset(offset),
1985 m_matrixSlice(matrixSlice)
1986{
1987}
1988
1989/*!
1990 \fn int QRhiVertexInputAttribute::binding() const
1991 \return the binding point index.
1992 */
1993
1994/*!
1995 \fn void QRhiVertexInputAttribute::setBinding(int b)
1996 Sets the binding point index to \a b.
1997 By default this is set to 0.
1998 */
1999
2000/*!
2001 \fn int QRhiVertexInputAttribute::location() const
2002 \return the location of the vertex input element.
2003 */
2004
2005/*!
2006 \fn void QRhiVertexInputAttribute::setLocation(int loc)
2007 Sets the location of the vertex input element to \a loc.
2008 By default this is set to 0.
2009 */
2010
2011/*!
2012 \fn QRhiVertexInputAttribute::Format QRhiVertexInputAttribute::format() const
2013 \return the format of the vertex input element.
2014 */
2015
2016/*!
2017 \fn void QRhiVertexInputAttribute::setFormat(Format f)
2018 Sets the format of the vertex input element to \a f.
2019 By default this is set to Float4.
2020 */
2021
2022/*!
2023 \fn quint32 QRhiVertexInputAttribute::offset() const
2024 \return the byte offset for the input element.
2025 */
2026
2027/*!
2028 \fn void QRhiVertexInputAttribute::setOffset(quint32 ofs)
2029 Sets the byte offset for the input element to \a ofs.
2030 */
2031
2032/*!
2033 \fn int QRhiVertexInputAttribute::matrixSlice() const
2034
2035 \return the matrix slice if the input element corresponds to a row or
2036 column of a matrix, or -1 if not relevant.
2037 */
2038
2039/*!
2040 \fn void QRhiVertexInputAttribute::setMatrixSlice(int slice)
2041
2042 Sets the matrix \a slice. By default this is set to -1, and should be set
2043 to a >= 0 value only when this attribute corresponds to a row or column of
2044 a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming 4
2045 consecutive vertex input locations), in which case it is the index of the
2046 row or column. \c{location - matrixSlice} must always be equal to the \c
2047 location for the first row or column of the unrolled matrix.
2048 */
2049
2050/*!
2051 \fn bool QRhiVertexInputAttribute::operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
2052
2053 \return \c true if the values in the two QRhiVertexInputAttribute objects
2054 \a a and \a b are equal.
2055 */
2056
2057/*!
2058 \fn bool QRhiVertexInputAttribute::operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
2059
2060 \return \c false if the values in the two QRhiVertexInputAttribute
2061 objects \a a and \a b are equal; otherwise returns \c true.
2062*/
2063
2064/*!
2065 \fn size_t QRhiVertexInputAttribute::qHash(const QRhiVertexInputAttribute &key, size_t seed)
2066 \qhash{QRhiVertexInputAttribute}
2067 */
2068
2069#ifndef QT_NO_DEBUG_STREAM
2070QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a)
2071{
2072 QDebugStateSaver saver(dbg);
2073 dbg.nospace() << "QRhiVertexInputAttribute(binding=" << a.binding()
2074 << " location=" << a.location()
2075 << " format=" << a.format()
2076 << " offset=" << a.offset()
2077 << ')';
2078 return dbg;
2079}
2080#endif
2081
2082QRhiVertexInputAttribute::Format QRhiImplementation::shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const
2083{
2084 switch (type) {
2085 case QShaderDescription::Vec4:
2086 return QRhiVertexInputAttribute::Float4;
2087 case QShaderDescription::Vec3:
2088 return QRhiVertexInputAttribute::Float3;
2089 case QShaderDescription::Vec2:
2090 return QRhiVertexInputAttribute::Float2;
2091 case QShaderDescription::Float:
2092 return QRhiVertexInputAttribute::Float;
2093
2094 case QShaderDescription::Int4:
2095 return QRhiVertexInputAttribute::SInt4;
2096 case QShaderDescription::Int3:
2097 return QRhiVertexInputAttribute::SInt3;
2098 case QShaderDescription::Int2:
2099 return QRhiVertexInputAttribute::SInt2;
2100 case QShaderDescription::Int:
2101 return QRhiVertexInputAttribute::SInt;
2102
2103 case QShaderDescription::Uint4:
2104 return QRhiVertexInputAttribute::UInt4;
2105 case QShaderDescription::Uint3:
2106 return QRhiVertexInputAttribute::UInt3;
2107 case QShaderDescription::Uint2:
2108 return QRhiVertexInputAttribute::UInt2;
2109 case QShaderDescription::Uint:
2110 return QRhiVertexInputAttribute::UInt;
2111
2112 case QShaderDescription::Half4:
2113 return QRhiVertexInputAttribute::Half4;
2114 case QShaderDescription::Half3:
2115 return QRhiVertexInputAttribute::Half3;
2116 case QShaderDescription::Half2:
2117 return QRhiVertexInputAttribute::Half2;
2118 case QShaderDescription::Half:
2119 return QRhiVertexInputAttribute::Half;
2120
2121 default:
2122 Q_UNREACHABLE_RETURN(QRhiVertexInputAttribute::Float);
2123 }
2124}
2125
2126quint32 QRhiImplementation::byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const
2127{
2128 switch (format) {
2129 case QRhiVertexInputAttribute::Float4:
2130 return 4 * sizeof(float);
2131 case QRhiVertexInputAttribute::Float3:
2132 return 4 * sizeof(float); // vec3 still takes 16 bytes
2133 case QRhiVertexInputAttribute::Float2:
2134 return 2 * sizeof(float);
2135 case QRhiVertexInputAttribute::Float:
2136 return sizeof(float);
2137
2138 case QRhiVertexInputAttribute::UNormByte4:
2139 return 4 * sizeof(quint8);
2140 case QRhiVertexInputAttribute::UNormByte2:
2141 return 2 * sizeof(quint8);
2142 case QRhiVertexInputAttribute::UNormByte:
2143 return sizeof(quint8);
2144
2145 case QRhiVertexInputAttribute::UInt4:
2146 return 4 * sizeof(quint32);
2147 case QRhiVertexInputAttribute::UInt3:
2148 return 4 * sizeof(quint32); // ivec3 still takes 16 bytes
2149 case QRhiVertexInputAttribute::UInt2:
2150 return 2 * sizeof(quint32);
2151 case QRhiVertexInputAttribute::UInt:
2152 return sizeof(quint32);
2153
2154 case QRhiVertexInputAttribute::SInt4:
2155 return 4 * sizeof(qint32);
2156 case QRhiVertexInputAttribute::SInt3:
2157 return 4 * sizeof(qint32); // uvec3 still takes 16 bytes
2158 case QRhiVertexInputAttribute::SInt2:
2159 return 2 * sizeof(qint32);
2160 case QRhiVertexInputAttribute::SInt:
2161 return sizeof(qint32);
2162
2163 case QRhiVertexInputAttribute::Half4:
2164 return 4 * sizeof(qfloat16);
2165 case QRhiVertexInputAttribute::Half3:
2166 return 4 * sizeof(qfloat16); // half3 still takes 8 bytes
2167 case QRhiVertexInputAttribute::Half2:
2168 return 2 * sizeof(qfloat16);
2169 case QRhiVertexInputAttribute::Half:
2170 return sizeof(qfloat16);
2171
2172 case QRhiVertexInputAttribute::UShort4:
2173 return 4 * sizeof(quint16);
2174 case QRhiVertexInputAttribute::UShort3:
2175 return 4 * sizeof(quint16); // ivec3 still takes 8 bytes
2176 case QRhiVertexInputAttribute::UShort2:
2177 return 2 * sizeof(quint16);
2178 case QRhiVertexInputAttribute::UShort:
2179 return sizeof(quint16);
2180
2181 case QRhiVertexInputAttribute::SShort4:
2182 return 4 * sizeof(qint16);
2183 case QRhiVertexInputAttribute::SShort3:
2184 return 4 * sizeof(qint16); // uvec3 still takes 8 bytes
2185 case QRhiVertexInputAttribute::SShort2:
2186 return 2 * sizeof(qint16);
2187 case QRhiVertexInputAttribute::SShort:
2188 return sizeof(qint16);
2189
2190 default:
2191 Q_UNREACHABLE_RETURN(1);
2192 }
2193}
2194
2195/*!
2196 \class QRhiVertexInputLayout
2197 \inmodule QtGuiPrivate
2198 \inheaderfile rhi/qrhi.h
2199 \since 6.6
2200 \brief Describes the layout of vertex inputs consumed by a vertex shader.
2201
2202 The vertex input layout is defined by the collections of
2203 QRhiVertexInputBinding and QRhiVertexInputAttribute.
2204
2205 As an example, let's assume that we have a single buffer with 3 component
2206 vertex positions and 2 component UV coordinates interleaved (\c x, \c y, \c
2207 z, \c u, \c v), that the position and UV are expected at input locations 0
2208 and 1 by the vertex shader, and that the vertex buffer will be bound at
2209 binding point 0 using
2210 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()} later on:
2211
2212 \code
2213 QRhiVertexInputLayout inputLayout;
2214 inputLayout.setBindings({
2215 { 5 * sizeof(float) }
2216 });
2217 inputLayout.setAttributes({
2218 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
2219 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
2220 });
2221 \endcode
2222
2223 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2224 for details.
2225 */
2226
2227/*!
2228 \fn QRhiVertexInputLayout::QRhiVertexInputLayout() = default
2229
2230 Constructs an empty vertex input layout description.
2231 */
2232
2233/*!
2234 \fn void QRhiVertexInputLayout::setBindings(std::initializer_list<QRhiVertexInputBinding> list)
2235 Sets the bindings from the specified \a list.
2236 */
2237
2238/*!
2239 \fn template<typename InputIterator> void QRhiVertexInputLayout::setBindings(InputIterator first, InputIterator last)
2240 Sets the bindings using the iterators \a first and \a last.
2241 */
2242
2243/*!
2244 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cbeginBindings() const
2245 \return a const iterator pointing to the first item in the binding list.
2246 */
2247
2248/*!
2249 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cendBindings() const
2250 \return a const iterator pointing just after the last item in the binding list.
2251 */
2252
2253/*!
2254 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::bindingAt(qsizetype index) const
2255 \return the binding at the given \a index.
2256 */
2257
2258/*!
2259 \fn qsizetype QRhiVertexInputLayout::bindingCount() const
2260 \return the number of bindings.
2261 */
2262
2263/*!
2264 \fn void QRhiVertexInputLayout::setAttributes(std::initializer_list<QRhiVertexInputAttribute> list)
2265 Sets the attributes from the specified \a list.
2266 */
2267
2268/*!
2269 \fn template<typename InputIterator> void QRhiVertexInputLayout::setAttributes(InputIterator first, InputIterator last)
2270 Sets the attributes using the iterators \a first and \a last.
2271 */
2272
2273/*!
2274 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cbeginAttributes() const
2275 \return a const iterator pointing to the first item in the attribute list.
2276 */
2277
2278/*!
2279 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cendAttributes() const
2280 \return a const iterator pointing just after the last item in the attribute list.
2281 */
2282
2283/*!
2284 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::attributeAt(qsizetype index) const
2285 \return the attribute at the given \a index.
2286 */
2287
2288/*!
2289 \fn qsizetype QRhiVertexInputLayout::attributeCount() const
2290 \return the number of attributes.
2291 */
2292
2293/*!
2294 \fn bool QRhiVertexInputLayout::operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2295
2296 \return \c true if the values in the two QRhiVertexInputLayout objects
2297 \a a and \a b are equal.
2298 */
2299
2300/*!
2301 \fn bool QRhiVertexInputLayout::operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2302
2303 \return \c false if the values in the two QRhiVertexInputLayout
2304 objects \a a and \a b are equal; otherwise returns \c true.
2305*/
2306
2307/*!
2308 \fn size_t QRhiVertexInputLayout::qHash(const QRhiVertexInputLayout &key, size_t seed)
2309 \qhash{QRhiVertexInputLayout}
2310 */
2311
2312#ifndef QT_NO_DEBUG_STREAM
2313QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
2314{
2315 QDebugStateSaver saver(dbg);
2316 dbg.nospace() << "QRhiVertexInputLayout(bindings=" << v.m_bindings
2317 << " attributes=" << v.m_attributes
2318 << ')';
2319 return dbg;
2320}
2321#endif
2322
2323/*!
2324 \class QRhiShaderStage
2325 \inmodule QtGuiPrivate
2326 \inheaderfile rhi/qrhi.h
2327 \since 6.6
2328 \brief Specifies the type and the shader code for a shader stage in the pipeline.
2329
2330 When setting up a QRhiGraphicsPipeline, a collection of shader stages are
2331 specified. The QRhiShaderStage contains a QShader and some associated
2332 metadata, such as the graphics pipeline stage, and the
2333 \l{QShader::Variant}{shader variant} to select. There is no need to specify
2334 the shader language or version because the QRhi backend in use at runtime
2335 will take care of choosing the appropriate shader version from the
2336 collection within the QShader.
2337
2338 The typical usage is in combination with
2339 QRhiGraphicsPipeline::setShaderStages(), shown here with a simple approach
2340 to load the QShader from \c{.qsb} files generated offline or at build time:
2341
2342 \code
2343 QShader getShader(const QString &name)
2344 {
2345 QFile f(name);
2346 return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
2347 }
2348
2349 QShader vs = getShader("material.vert.qsb");
2350 QShader fs = getShader("material.frag.qsb");
2351 pipeline->setShaderStages({
2352 { QRhiShaderStage::Vertex, vs },
2353 { QRhiShaderStage::Fragment, fs }
2354 });
2355 \endcode
2356
2357 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2358 for details.
2359 */
2360
2361/*!
2362 \enum QRhiShaderStage::Type
2363 Specifies the type of the shader stage.
2364
2365 \value Vertex Vertex stage
2366
2367 \value TessellationControl Tessellation control (hull shader) stage. Must
2368 be used only when the QRhi::Tessellation feature is supported.
2369
2370 \value TessellationEvaluation Tessellation evaluation (domain shader)
2371 stage. Must be used only when the QRhi::Tessellation feature is supported.
2372
2373 \value Fragment Fragment (pixel shader) stage
2374
2375 \value Compute Compute stage. Must be used only when the QRhi::Compute
2376 feature is supported.
2377
2378 \value Geometry Geometry stage. Must be used only when the
2379 QRhi::GeometryShader feature is supported.
2380 */
2381
2382/*!
2383 \fn QRhiShaderStage::QRhiShaderStage() = default
2384
2385 Constructs a shader stage description for the vertex stage with an empty
2386 QShader.
2387 */
2388
2389/*!
2390 \fn QRhiShaderStage::Type QRhiShaderStage::type() const
2391 \return the type of the stage.
2392 */
2393
2394/*!
2395 \fn void QRhiShaderStage::setType(Type t)
2396
2397 Sets the type of the stage to \a t. Setters should rarely be needed in
2398 pratice. Most applications will likely use the QRhiShaderStage constructor
2399 in most cases.
2400 */
2401
2402/*!
2403 \fn QShader QRhiShaderStage::shader() const
2404 \return the QShader to be used for this stage in the graphics pipeline.
2405 */
2406
2407/*!
2408 \fn void QRhiShaderStage::setShader(const QShader &s)
2409 Sets the shader collection \a s.
2410 */
2411
2412/*!
2413 \fn QShader::Variant QRhiShaderStage::shaderVariant() const
2414 \return the requested shader variant.
2415 */
2416
2417/*!
2418 \fn void QRhiShaderStage::setShaderVariant(QShader::Variant v)
2419 Sets the requested shader variant \a v.
2420 */
2421
2422/*!
2423 Constructs a shader stage description with the \a type of the stage and the
2424 \a shader.
2425
2426 The shader variant \a v defaults to QShader::StandardShader. A
2427 QShader contains multiple source and binary versions of a shader.
2428 In addition, it can also contain variants of the shader with slightly
2429 modified code. \a v can then be used to select the desired variant.
2430 */
2431QRhiShaderStage::QRhiShaderStage(Type type, const QShader &shader, QShader::Variant v)
2432 : m_type(type),
2433 m_shader(shader),
2434 m_shaderVariant(v)
2435{
2436}
2437
2438/*!
2439 \fn bool QRhiShaderStage::operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2440
2441 \return \c true if the values in the two QRhiShaderStage objects
2442 \a a and \a b are equal.
2443 */
2444
2445/*!
2446 \fn bool QRhiShaderStage::operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2447
2448 \return \c false if the values in the two QRhiShaderStage
2449 objects \a a and \a b are equal; otherwise returns \c true.
2450*/
2451
2452/*!
2453 \fn size_t QRhiShaderStage::qHash(const QRhiShaderStage &key, size_t seed)
2454 \qhash{QRhiShaderStage}
2455 */
2456
2457#ifndef QT_NO_DEBUG_STREAM
2458QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
2459{
2460 QDebugStateSaver saver(dbg);
2461 dbg.nospace() << "QRhiShaderStage(type=" << s.type()
2462 << " shader=" << s.shader()
2463 << " variant=" << s.shaderVariant()
2464 << ')';
2465 return dbg;
2466}
2467#endif
2468
2469/*!
2470 \class QRhiColorAttachment
2471 \inmodule QtGuiPrivate
2472 \inheaderfile rhi/qrhi.h
2473 \since 6.6
2474 \brief Describes the a single color attachment of a render target.
2475
2476 A color attachment is either a QRhiTexture or a QRhiRenderBuffer. The
2477 former, i.e. when texture() is set, is used in most cases.
2478 QRhiColorAttachment is commonly used in combination with
2479 QRhiTextureRenderTargetDescription.
2480
2481 \note texture() and renderBuffer() cannot be both set (be non-null at the
2482 same time).
2483
2484 Setting renderBuffer instead is recommended only when multisampling is
2485 needed. Relying on QRhi::MultisampleRenderBuffer is a better choice than
2486 QRhi::MultisampleTexture in practice since the former is available in more
2487 run time configurations (e.g. when running on OpenGL ES 3.0 which has no
2488 support for multisample textures, but does support multisample
2489 renderbuffers).
2490
2491 When targeting a non-multisample texture, the layer() and level() indicate
2492 the targeted layer (face index \c{0-5} for cubemaps) and mip level. For 3D
2493 textures layer() specifies the slice (one 2D image within the 3D texture)
2494 to render to. For texture arrays layer() is the array index.
2495
2496 When texture() or renderBuffer() is multisample, resolveTexture() can be
2497 set optionally. When set, samples are resolved automatically into that
2498 (non-multisample) texture at the end of the render pass. When rendering
2499 into a multisample renderbuffers, this is the only way to get resolved,
2500 non-multisample content out of them. Multisample textures allow sampling in
2501 shaders so for them this is just one option.
2502
2503 \note when resolving is enabled, the multisample data may not be written
2504 out at all. This means that the multisample texture() must not be used
2505 afterwards with shaders for sampling when resolveTexture() is set.
2506
2507 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2508 for details.
2509
2510 \sa QRhiTextureRenderTargetDescription
2511 */
2512
2513/*!
2514 \fn QRhiColorAttachment::QRhiColorAttachment() = default
2515
2516 Constructs an empty color attachment description.
2517 */
2518
2519/*!
2520 Constructs a color attachment description that specifies \a texture as the
2521 associated color buffer.
2522 */
2523QRhiColorAttachment::QRhiColorAttachment(QRhiTexture *texture)
2524 : m_texture(texture)
2525{
2526}
2527
2528/*!
2529 Constructs a color attachment description that specifies \a renderBuffer as
2530 the associated color buffer.
2531 */
2532QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
2533 : m_renderBuffer(renderBuffer)
2534{
2535}
2536
2537/*!
2538 \fn QRhiTexture *QRhiColorAttachment::texture() const
2539
2540 \return the texture this attachment description references, or \nullptr if
2541 there is none.
2542 */
2543
2544/*!
2545 \fn void QRhiColorAttachment::setTexture(QRhiTexture *tex)
2546
2547 Sets the texture \a tex.
2548
2549 \note texture() and renderBuffer() cannot be both set (be non-null at the
2550 same time).
2551 */
2552
2553/*!
2554 \fn QRhiRenderBuffer *QRhiColorAttachment::renderBuffer() const
2555
2556 \return the renderbuffer this attachment description references, or
2557 \nullptr if there is none.
2558
2559 In practice associating a QRhiRenderBuffer with a QRhiColorAttachment makes
2560 the most sense when setting up multisample rendering via a multisample
2561 \l{QRhiRenderBuffer::Type}{color} renderbuffer that is then resolved into a
2562 non-multisample texture at the end of the render pass.
2563 */
2564
2565/*!
2566 \fn void QRhiColorAttachment::setRenderBuffer(QRhiRenderBuffer *rb)
2567
2568 Sets the renderbuffer \a rb.
2569
2570 \note texture() and renderBuffer() cannot be both set (be non-null at the
2571 same time).
2572 */
2573
2574/*!
2575 \fn int QRhiColorAttachment::layer() const
2576 \return the layer index (cubemap face or array layer). 0 by default.
2577 */
2578
2579/*!
2580 \fn void QRhiColorAttachment::setLayer(int layer)
2581 Sets the \a layer index.
2582 */
2583
2584/*!
2585 \fn int QRhiColorAttachment::level() const
2586 \return the mip level. 0 by default.
2587 */
2588
2589/*!
2590 \fn void QRhiColorAttachment::setLevel(int level)
2591 Sets the mip \a level.
2592 */
2593
2594/*!
2595 \fn QRhiTexture *QRhiColorAttachment::resolveTexture() const
2596
2597 \return the resolve texture this attachment description references, or
2598 \nullptr if there is none.
2599
2600 Setting a non-null resolve texture is applicable when the attachment
2601 references a multisample texture or renderbuffer. The QRhiTexture in the
2602 resolveTexture() is then a non-multisample 2D texture (or texture array)
2603 with the same size (but a sample count of 1). The multisample content is
2604 automatically resolved into this texture at the end of each render pass.
2605 */
2606
2607/*!
2608 \fn void QRhiColorAttachment::setResolveTexture(QRhiTexture *tex)
2609
2610 Sets the resolve texture \a tex.
2611
2612 \a tex is expected to be a 2D texture or a 2D texture array. In either
2613 case, resolving targets a single mip level of a single layer (array
2614 element) of \a tex. The mip level and array layer are specified by
2615 resolveLevel() and resolveLayer().
2616
2617 An exception is \l{setMultiViewCount()}{multiview}: when the color
2618 attachment is associated with a texture array and multiview is enabled, the
2619 resolve texture must also be a texture array with sufficient elements for
2620 all views. In this case all elements that correspond to views are resolved
2621 automatically; the behavior is similar to the following pseudo-code:
2622 \badcode
2623 for (i = 0; i < multiViewCount(); ++i)
2624 resolve texture's layer() + i into resolveTexture's resolveLayer() + i
2625 \endcode
2626
2627 Setting a non-multisample texture to resolve a multisample texture or
2628 renderbuffer automatically at the end of the render pass is often
2629 preferable to working with multisample textures (and not setting a resolve
2630 texture), because it avoids the need for writing dedicated fragment shaders
2631 that work exclusively with multisample textures (\c sampler2DMS, \c
2632 texelFetch, etc.), and rather allows using the same shader as one would if
2633 the attachment's texture was not multisampled to begin with. This comes at
2634 the expense of an additional resource (the non-multisample \a tex).
2635 */
2636
2637/*!
2638 \fn int QRhiColorAttachment::resolveLayer() const
2639 \return the currently set resolve texture layer. Defaults to 0.
2640 */
2641
2642/*!
2643 \fn void QRhiColorAttachment::setResolveLayer(int layer)
2644 Sets the resolve texture \a layer to use.
2645 */
2646
2647/*!
2648 \fn int QRhiColorAttachment::resolveLevel() const
2649 \return the currently set resolve texture mip level. Defaults to 0.
2650 */
2651
2652/*!
2653 \fn void QRhiColorAttachment::setResolveLevel(int level)
2654 Sets the resolve texture mip \a level to use.
2655 */
2656
2657/*!
2658 \fn int QRhiColorAttachment::multiViewCount() const
2659
2660 \return the currently set number of views. Defaults to 0 which indicates
2661 the render target with this color attachment is not going to be used with
2662 multiview rendering.
2663
2664 \since 6.7
2665 */
2666
2667/*!
2668 \fn void QRhiColorAttachment::setMultiViewCount(int count)
2669
2670 Sets the view \a count. Setting a value larger than 1 indicates that the
2671 render target with this color attachment is going to be used with multiview
2672 rendering. The default value is 0. Values smaller than 2 indicate no
2673 multiview rendering.
2674
2675 When \a count is set to \c 2 or greater, the color attachment must be
2676 associated with a 2D texture array. layer() and multiViewCount() together
2677 define the range of texture array elements that are targeted during
2678 multiview rendering.
2679
2680 For example, if \c layer is \c 0 and \c multiViewCount is \c 2, the texture
2681 array must have 2 (or more) elements, and the multiview rendering will
2682 target elements 0 and 1. The \c{gl_ViewIndex} variable in the shaders has a
2683 value of \c 0 or \c 1 then, where view \c 0 corresponds to the texture array
2684 element \c 0, and view \c 1 to the array element \c 1.
2685
2686 \note Setting a \a count larger than 1, using a texture array as texture(),
2687 and calling \l{QRhiCommandBuffer::beginPass()}{beginPass()} on a
2688 QRhiTextureRenderTarget with this color attachment implies multiview
2689 rendering for the entire render pass. multiViewCount() should not be set
2690 unless multiview rendering is wanted. Multiview cannot be used with texture
2691 types other than 2D texture arrays. (although 3D textures may work,
2692 depending on the graphics API and backend; applications are nonetheless
2693 advised not to rely on that and only use 2D texture arrays as the render
2694 targets of multiview rendering)
2695
2696 See
2697 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2698 for more details regarding multiview rendering. Do note that Qt requires
2699 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview2.txt}{GL_OVR_multiview2}
2700 as well, when running on OpenGL (ES).
2701
2702 Multiview rendering is available only when the
2703 \l{QRhi::MultiView}{MultiView} feature is reported as supported from
2704 \l{QRhi::isFeatureSupported()}{isFeatureSupported()}.
2705
2706 \note For portability, be aware of limitations that exist for multiview
2707 rendering with some of the graphics APIs. It is recommended that multiview
2708 render passes do not rely on any of the features that
2709 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2710 declares as unsupported. The one exception is shader stage outputs other
2711 than \c{gl_Position} depending on \c{gl_ViewIndex}: that can be relied on
2712 (even with OpenGL) because QRhi never reports multiview as supported without
2713 \c{GL_OVR_multiview2} also being present.
2714
2715 \note Multiview rendering is not supported in combination with tessellation
2716 or geometry shaders, even though some implementations of some graphics APIs
2717 may allow this.
2718
2719 \since 6.7
2720 */
2721
2722/*!
2723 \class QRhiTextureRenderTargetDescription
2724 \inmodule QtGuiPrivate
2725 \inheaderfile rhi/qrhi.h
2726 \since 6.6
2727 \brief Describes the color and depth or depth/stencil attachments of a render target.
2728
2729 A texture render target has zero or more textures as color attachments,
2730 zero or one renderbuffer as combined depth/stencil buffer or zero or one
2731 texture as depth buffer.
2732
2733 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2734 non-null at the same time).
2735
2736 Let's look at some example usages in combination with
2737 QRhiTextureRenderTarget.
2738
2739 Due to the constructors, the targeting a texture (and no depth/stencil
2740 buffer) is simple:
2741
2742 \code
2743 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256), 1, QRhiTexture::RenderTarget);
2744 texture->create();
2745 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture }));
2746 \endcode
2747
2748 The following creates a texture render target that is set up to target mip
2749 level #2 of a texture:
2750
2751 \code
2752 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget | QRhiTexture::MipMapped);
2753 texture->create();
2754 QRhiColorAttachment colorAtt(texture);
2755 colorAtt.setLevel(2);
2756 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt });
2757 \endcode
2758
2759 Another example, this time to render into a depth texture:
2760
2761 \code
2762 QRhiTexture *shadowMap = rhi->newTexture(QRhiTexture::D32F, QSize(1024, 1024), 1, QRhiTexture::RenderTarget);
2763 shadowMap->create();
2764 QRhiTextureRenderTargetDescription rtDesc;
2765 rtDesc.setDepthTexture(shadowMap);
2766 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2767 \endcode
2768
2769 A very common case, having a texture as the color attachment and a
2770 renderbuffer as depth/stencil to enable depth testing:
2771
2772 \code
2773 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2774 texture->create();
2775 QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512));
2776 depthStencil->create();
2777 QRhiTextureRenderTargetDescription rtDesc({ texture }, depthStencil);
2778 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2779 \endcode
2780
2781 Finally, to enable multisample rendering in a portable manner (so also
2782 supporting OpenGL ES 3.0), using a QRhiRenderBuffer as the (multisample)
2783 color buffer and then resolving into a regular (non-multisample) 2D
2784 texture. To enable depth testing, a depth-stencil buffer, which also must
2785 use the same sample count, is used as well:
2786
2787 \code
2788 QRhiRenderBuffer *colorBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4); // 4x MSAA
2789 colorBuffer->create();
2790 QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512), 4);
2791 depthStencil->create();
2792 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2793 texture->create();
2794 QRhiColorAttachment colorAtt(colorBuffer);
2795 colorAtt.setResolveTexture(texture);
2796 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt, depthStencil });
2797 \endcode
2798
2799 \note when multisample resolving is enabled, the multisample data may not be
2800 written out at all. This means that the multisample texture in a color
2801 attachment must not be used afterwards with shaders for sampling (or other
2802 purposes) whenever a resolve texture is set, since the multisample color
2803 buffer is merely an intermediate storage then that gets no data written back
2804 on some GPU architectures at all. See
2805 \l{QRhiTextureRenderTarget::Flag}{PreserveColorContents} for more details.
2806
2807 \note When using setDepthTexture(), not setDepthStencilBuffer(), and the
2808 depth (stencil) data is not of interest afterwards, set the
2809 DoNotStoreDepthStencilContents flag on the QRhiTextureRenderTarget. This
2810 allows indicating to the underlying 3D API that the depth/stencil data can
2811 be discarded, leading potentially to better performance with tiled GPU
2812 architectures. When the depth-stencil buffer is a QRhiRenderBuffer (and also
2813 for the multisample color texture, see previous note) this is implicit, but
2814 with a depth (stencil) QRhiTexture the intention needs to be declared
2815 explicitly. By default QRhi assumes that the data is of interest (e.g., the
2816 depth texture is sampled in a shader afterwards).
2817
2818 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2819 for details.
2820
2821 \sa QRhiColorAttachment, QRhiTextureRenderTarget
2822 */
2823
2824/*!
2825 \fn QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription() = default
2826
2827 Constructs an empty texture render target description.
2828 */
2829
2830/*!
2831 Constructs a texture render target description with one attachment
2832 described by \a colorAttachment.
2833 */
2834QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment)
2835{
2836 m_colorAttachments.append(colorAttachment);
2837}
2838
2839/*!
2840 Constructs a texture render target description with two attachments, a
2841 color attachment described by \a colorAttachment, and a depth/stencil
2842 attachment with \a depthStencilBuffer.
2843 */
2844QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2845 QRhiRenderBuffer *depthStencilBuffer)
2846 : m_depthStencilBuffer(depthStencilBuffer)
2847{
2848 m_colorAttachments.append(colorAttachment);
2849}
2850
2851/*!
2852 Constructs a texture render target description with two attachments, a
2853 color attachment described by \a colorAttachment, and a depth attachment
2854 with \a depthTexture.
2855
2856 \note \a depthTexture must have a suitable format, such as QRhiTexture::D16
2857 or QRhiTexture::D32F.
2858 */
2859QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2860 QRhiTexture *depthTexture)
2861 : m_depthTexture(depthTexture)
2862{
2863 m_colorAttachments.append(colorAttachment);
2864}
2865
2866/*!
2867 \fn void QRhiTextureRenderTargetDescription::setColorAttachments(std::initializer_list<QRhiColorAttachment> list)
2868 Sets the \a list of color attachments.
2869 */
2870
2871/*!
2872 \fn template<typename InputIterator> void QRhiTextureRenderTargetDescription::setColorAttachments(InputIterator first, InputIterator last)
2873 Sets the list of color attachments via the iterators \a first and \a last.
2874 */
2875
2876/*!
2877 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cbeginColorAttachments() const
2878 \return a const iterator pointing to the first item in the attachment list.
2879 */
2880
2881/*!
2882 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cendColorAttachments() const
2883 \return a const iterator pointing just after the last item in the attachment list.
2884 */
2885
2886/*!
2887 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::colorAttachmentAt(qsizetype index) const
2888 \return the color attachment at the specified \a index.
2889 */
2890
2891/*!
2892 \fn qsizetype QRhiTextureRenderTargetDescription::colorAttachmentCount() const
2893 \return the number of currently set color attachments.
2894 */
2895
2896/*!
2897 \fn QRhiRenderBuffer *QRhiTextureRenderTargetDescription::depthStencilBuffer() const
2898 \return the renderbuffer used as depth-stencil buffer, or \nullptr if none was set.
2899 */
2900
2901/*!
2902 \fn void QRhiTextureRenderTargetDescription::setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer)
2903
2904 Sets the \a renderBuffer for depth-stencil. Not mandatory, e.g. when no
2905 depth test/write or stencil-related features are used within any graphics
2906 pipelines in any of the render passes for this render target, it can be
2907 left set to \nullptr.
2908
2909 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2910 non-null at the same time).
2911
2912 Using a QRhiRenderBuffer over a 2D QRhiTexture as the depth or
2913 depth/stencil buffer is very common, and is the recommended approach for
2914 applications. Using a QRhiTexture, and so setDepthTexture() becomes
2915 relevant if the depth data is meant to be accessed (e.g. sampled in a
2916 shader) afterwards, or when
2917 \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering} is
2918 involved (because then the depth texture must be a texture array).
2919
2920 \sa setDepthTexture()
2921 */
2922
2923/*!
2924 \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthTexture() const
2925 \return the currently referenced depth texture, or \nullptr if none was set.
2926 */
2927
2928/*!
2929 \fn void QRhiTextureRenderTargetDescription::setDepthTexture(QRhiTexture *texture)
2930
2931 Sets the \a texture for depth-stencil. This is an alternative to
2932 setDepthStencilBuffer(), where instead of a QRhiRenderBuffer a QRhiTexture
2933 with a suitable type (e.g., QRhiTexture::D32F) is provided.
2934
2935 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2936 non-null at the same time).
2937
2938 \a texture can either be a 2D texture or a 2D texture array (when texture
2939 arrays are supported). Specifying a texture array is relevant in particular
2940 with
2941 \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering}.
2942
2943 \note If \a texture is a format with a stencil component, such as
2944 \l QRhiTexture::D24S8, it will serve as the stencil buffer as well.
2945
2946 \sa setDepthStencilBuffer()
2947 */
2948
2949/*!
2950 \fn int QRhiTextureRenderTargetDescription::depthLayer() const
2951 \return the array slice index to be used for the depth/stencil attachment,
2952 or -1 by default.
2953
2954 \since 6.12
2955 \sa setDepthLayer(), setDepthTexture()
2956 */
2957
2958/*!
2959 \fn void QRhiTextureRenderTargetDescription::setDepthLayer(int depthLayer)
2960
2961 Sets the array slice index to be used for the depth/stencil attachment.
2962
2963 Pass -1 (the default) to not target a particular layer. When set to a
2964 non-negative value, the render target attaches a view that targets exactly
2965 that layer (slice) of the depth texture. This is only effective when a 2D
2966 array depth texture is provided via setDepthTexture(); otherwise the value
2967 is ignored.
2968
2969 The value must be within the array size of the depth texture; passing an
2970 out-of-range index leads to undefined behavior. The index is absolute
2971 with respect to the underlying texture, regardless of any array range
2972 that may have been specified when creating the texture.
2973
2974 Specifying a \a depthLayer disables layered/multiview rendering for the
2975 depth attachment.
2976
2977 \since 6.12
2978 \sa depthLayer(), setDepthTexture()
2979 */
2980
2981/*!
2982 \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthResolveTexture() const
2983
2984 \return the texture to which a multisample depth (or depth-stencil) texture
2985 (or texture array) is resolved to. \nullptr if there is none, which is the
2986 most common case.
2987
2988 \since 6.8
2989 \sa QRhiColorAttachment::resolveTexture(), depthTexture()
2990 */
2991
2992/*!
2993 \fn void QRhiTextureRenderTargetDescription::setDepthResolveTexture(QRhiTexture *tex)
2994
2995 Sets the depth (or depth-stencil) resolve texture \a tex.
2996
2997 \a tex is expected to be a 2D texture or a 2D texture array with a format
2998 matching the texture set via setDepthTexture().
2999
3000 \note Resolving depth (or depth-stencil) data is only functional when the
3001 \l QRhi::ResolveDepthStencil feature is reported as supported at run time.
3002 Support for depth-stencil resolve is not universally available among the
3003 graphics APIs. Designs assuming unconditional availability of depth-stencil
3004 resolve are therefore non-portable, and should be avoided.
3005
3006 \note As an additional limitation for OpenGL ES in particular, setting a
3007 depth resolve texture may only be functional in combination with
3008 setDepthTexture(), not with setDepthStencilBuffer().
3009
3010 \since 6.8
3011 \sa QRhiColorAttachment::setResolveTexture(), setDepthTexture()
3012 */
3013
3014/*!
3015 \fn QRhiShadingRateMap *QRhiTextureRenderTargetDescription::shadingRateMap() const
3016 \return the currently set QRhiShadingRateMap. By default this is \nullptr.
3017 \since 6.9
3018 */
3019
3020/*!
3021 \fn void QRhiTextureRenderTargetDescription::setShadingRateMap(QRhiShadingRateMap *map)
3022
3023 Associates with the specified QRhiShadingRateMap \a map. This is functional
3024 only when the \l QRhi::VariableRateShadingMap feature is reported as
3025 supported.
3026
3027 When QRhiCommandBuffer::setShadingRate() is also called, the higher of the
3028 two shading rates is used for each tile. There is currently no control
3029 offered over the combiner behavior.
3030
3031 \note When the render target had already been built (create() was called
3032 successfully), setting a shading rate map implies that a different, new
3033 QRhiRenderPassDescriptor is needed and thus a rebuild is needed. Call
3034 setRenderPassDescriptor() again (outside of a render pass) and then rebuild
3035 by calling create(). This has other rolling consequences as well, for
3036 example for graphics pipelines: those also need to be associated with the
3037 new QRhiRenderPassDescriptor and then rebuilt. See \l
3038 QRhiRenderPassDescriptor::serializedFormat() for some suggestions on how to
3039 deal with this. Remember to set the QRhiGraphicsPipeline::UsesShadingRate
3040 flag as well.
3041
3042 \since 6.9
3043 */
3044
3045/*!
3046 \class QRhiTextureSubresourceUploadDescription
3047 \inmodule QtGuiPrivate
3048 \inheaderfile rhi/qrhi.h
3049 \since 6.6
3050 \brief Describes the source for one mip level in a layer in a texture upload operation.
3051
3052 The source content is specified either as a QImage or as a raw blob. The
3053 former is only allowed for uncompressed textures with a format that can be
3054 mapped to QImage, while the latter is supported for all formats, including
3055 floating point and compressed.
3056
3057 \note image() and data() cannot be both set at the same time.
3058
3059 destinationTopLeft() specifies the top-left corner of the target
3060 rectangle. Defaults to (0, 0).
3061
3062 An empty sourceSize() (the default) indicates that size is assumed to be
3063 the size of the subresource. With QImage-based uploads this implies that
3064 the size of the source image() must match the subresource. When providing
3065 raw data instead, sufficient number of bytes must be provided in data().
3066
3067 sourceTopLeft() is supported only for QImage-based uploads, and specifies
3068 the top-left corner of the source rectangle.
3069
3070 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3071 internally, depending on the format and the backend.
3072
3073 When providing raw data, and the stride is not specified via
3074 setDataStride(), the stride (row pitch, row length in bytes) of the
3075 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
3076 the number of bytes used for one pixel, and there must be no additional
3077 padding between rows. There is no row start alignment requirement.
3078
3079 When there is unused data at the end of each row in the input raw data,
3080 call setDataStride() with the total number of bytes per row. The stride
3081 must always be a multiple of the number of bytes for one pixel. The row
3082 stride is only applicable to image data for textures with an uncompressed
3083 format.
3084
3085 \note The format of the source data must be compatible with the texture
3086 format. With many graphics APIs the data is copied as-is into a staging
3087 buffer, there is no intermediate format conversion provided by QRhi. This
3088 applies to floating point formats as well, with, for example, RGBA16F
3089 requiring half floats in the source data.
3090
3091 \note Setting the stride via setDataStride() is only functional when
3092 QRhi::ImageDataStride is reported as
3093 \l{QRhi::isFeatureSupported()}{supported}. In practice this can be expected
3094 to be supported everywhere except for OpenGL ES 2.0.
3095
3096 \note When a QImage is given, the stride returned from
3097 QImage::bytesPerLine() is taken into account automatically.
3098
3099 \warning When a QImage is given and the QImage does not own the underlying
3100 pixel data, it is up to the caller to ensure that the associated data stays
3101 valid until the end of the frame. (just submitting the resource update batch
3102 is not sufficient, the data must stay valid until QRhi::endFrame() is called
3103 in order to be portable across all backends) If this cannot be ensured, the
3104 caller is strongly encouraged to call QImage::detach() on the image before
3105 passing it to uploadTexture().
3106
3107 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3108 for details.
3109
3110 \sa QRhiTextureUploadDescription
3111 */
3112
3113/*!
3114 \fn QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription() = default
3115
3116 Constructs an empty subresource description.
3117
3118 \note an empty QRhiTextureSubresourceUploadDescription is not useful on its
3119 own and should not be submitted to a QRhiTextureUploadEntry. At minimum
3120 image or data must be set first.
3121 */
3122
3123/*!
3124 Constructs a mip level description with a \a image.
3125
3126 The \l{QImage::size()}{size} of \a image must match the size of the mip
3127 level. For level 0 that is the \l{QRhiTexture::pixelSize()}{texture size}.
3128
3129 The bit depth of \a image must be compatible with the
3130 \l{QRhiTexture::Format}{texture format}.
3131
3132 To describe a partial upload, call setSourceSize(), setSourceTopLeft(), or
3133 setDestinationTopLeft() afterwards.
3134 */
3135QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QImage &image)
3136 : m_image(image)
3137{
3138}
3139
3140/*!
3141 Constructs a mip level description with the image data is specified by \a
3142 data and \a size. This is suitable for floating point and compressed
3143 formats as well.
3144
3145 \a data can safely be destroyed or changed once this function returns.
3146 */
3147QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const void *data, quint32 size)
3148 : m_data(reinterpret_cast<const char *>(data), size)
3149{
3150}
3151
3152/*!
3153 Constructs a mip level description with the image data specified by \a
3154 data. This is suitable for floating point and compressed formats as well.
3155 */
3156QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QByteArray &data)
3157 : m_data(data)
3158{
3159}
3160
3161/*!
3162 \fn QImage QRhiTextureSubresourceUploadDescription::image() const
3163 \return the currently set QImage.
3164 */
3165
3166/*!
3167 \fn void QRhiTextureSubresourceUploadDescription::setImage(const QImage &image)
3168
3169 Sets \a image.
3170 Upon textures loading, the image data will be read as is, with no formats conversions.
3171
3172 \note image() and data() cannot be both set at the same time.
3173 */
3174
3175/*!
3176 \fn QByteArray QRhiTextureSubresourceUploadDescription::data() const
3177 \return the currently set raw pixel data.
3178 */
3179
3180/*!
3181 \fn void QRhiTextureSubresourceUploadDescription::setData(const QByteArray &data)
3182
3183 Sets \a data.
3184
3185 \note image() and data() cannot be both set at the same time.
3186 */
3187
3188/*!
3189 \fn quint32 QRhiTextureSubresourceUploadDescription::dataStride() const
3190 \return the currently set data stride.
3191 */
3192
3193/*!
3194 \fn void QRhiTextureSubresourceUploadDescription::setDataStride(quint32 stride)
3195
3196 Sets the data \a stride in bytes. By default this is 0 and not always
3197 relevant. When providing raw data(), and the stride is not specified via
3198 setDataStride(), the stride (row pitch, row length in bytes) of the
3199 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
3200 the number of bytes used for one pixel, and there must be no additional
3201 padding between rows. Otherwise, if there is additional space between the
3202 lines, set a non-zero \a stride. All this is applicable only when raw image
3203 data is provided, and is not necessary when working QImage since that has
3204 its own \l{QImage::bytesPerLine()}{stride} value.
3205
3206 \note When a non-zero \a stride is set, make sure the data contains the
3207 trailing padding for the last row as well, i.e. at least \c{stride * height}
3208 bytes in total. While providing the data without the last row's padding
3209 (i.e., interpreting stride as not applicable to the last row) could be safe,
3210 and is in fact safe with Vulkan, OpenGL, and D3D12, this cannot be
3211 guaranteed for all backends, so the safe approach is to avoid this and treat
3212 the last line like all others.
3213
3214 \note Setting the stride via setDataStride() is only functional when
3215 QRhi::ImageDataStride is reported as
3216 \l{QRhi::isFeatureSupported()}{supported}.
3217
3218 \note When a QImage is given, the stride returned from
3219 QImage::bytesPerLine() is taken into account automatically and therefore
3220 there is no need to set the data stride manually.
3221 */
3222
3223/*!
3224 \fn QPoint QRhiTextureSubresourceUploadDescription::destinationTopLeft() const
3225 \return the currently set destination top-left position. Defaults to (0, 0).
3226 */
3227
3228/*!
3229 \fn void QRhiTextureSubresourceUploadDescription::setDestinationTopLeft(const QPoint &p)
3230 Sets the destination top-left position \a p.
3231
3232 \note In the most common case of sourcing the image data from a QImage, Qt
3233 performs clamping of invalid texture upload sizes when the destination
3234 position + the source size exceeds the size of the targeted texture
3235 subresource (i.e, the size at the given mip level). There is also a
3236 qWarning() message printed on the debug output in this case. This is done in
3237 order to avoid confusion when the underlying 3D APIs crash and lead to GPU
3238 device removals at a later point when submitting the commands. Regardless,
3239 developers are encouraged to always validate applications by running with the
3240 Vulkan, D3D12, or Metal validation/debug layers enabled, since those offer a
3241 much wider range of checks on API usage.
3242 */
3243
3244/*!
3245 \fn QSize QRhiTextureSubresourceUploadDescription::sourceSize() const
3246
3247 \return the source size in pixels. Defaults to a default-constructed QSize,
3248 which indicates the entire subresource.
3249 */
3250
3251/*!
3252 \fn void QRhiTextureSubresourceUploadDescription::setSourceSize(const QSize &size)
3253
3254 Sets the source \a size in pixels.
3255
3256 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3257 internally, depending on the format and the backend.
3258 */
3259
3260/*!
3261 \fn QPoint QRhiTextureSubresourceUploadDescription::sourceTopLeft() const
3262 \return the currently set source top-left position. Defaults to (0, 0).
3263 */
3264
3265/*!
3266 \fn void QRhiTextureSubresourceUploadDescription::setSourceTopLeft(const QPoint &p)
3267
3268 Sets the source top-left position \a p.
3269
3270 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3271 internally, depending on the format and the backend.
3272 */
3273
3274/*!
3275 \class QRhiTextureUploadEntry
3276 \inmodule QtGuiPrivate
3277 \inheaderfile rhi/qrhi.h
3278 \since 6.6
3279
3280 \brief Describes one layer (face for cubemaps, slice for 3D textures,
3281 element for texture arrays) in a texture upload operation.
3282
3283 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3284 for details.
3285 */
3286
3287/*!
3288 \fn QRhiTextureUploadEntry::QRhiTextureUploadEntry()
3289
3290 Constructs an empty QRhiTextureUploadEntry targeting layer 0 and level 0.
3291
3292 \note an empty QRhiTextureUploadEntry should not be submitted without
3293 setting a QRhiTextureSubresourceUploadDescription via setDescription()
3294 first.
3295 */
3296
3297/*!
3298 Constructs a QRhiTextureUploadEntry targeting the given \a layer and mip
3299 \a level, with the subresource contents described by \a desc.
3300 */
3301QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
3302 const QRhiTextureSubresourceUploadDescription &desc)
3303 : m_layer(layer),
3304 m_level(level),
3305 m_desc(desc)
3306{
3307}
3308
3309/*!
3310 \fn int QRhiTextureUploadEntry::layer() const
3311 \return the currently set layer index (cubemap face, array layer). Defaults to 0.
3312 */
3313
3314/*!
3315 \fn void QRhiTextureUploadEntry::setLayer(int layer)
3316 Sets the \a layer.
3317 */
3318
3319/*!
3320 \fn int QRhiTextureUploadEntry::level() const
3321 \return the currently set mip level. Defaults to 0.
3322 */
3323
3324/*!
3325 \fn void QRhiTextureUploadEntry::setLevel(int level)
3326 Sets the mip \a level.
3327 */
3328
3329/*!
3330 \fn QRhiTextureSubresourceUploadDescription QRhiTextureUploadEntry::description() const
3331 \return the currently set subresource description.
3332 */
3333
3334/*!
3335 \fn void QRhiTextureUploadEntry::setDescription(const QRhiTextureSubresourceUploadDescription &desc)
3336 Sets the subresource description \a desc.
3337 */
3338
3339/*!
3340 \class QRhiTextureUploadDescription
3341 \inmodule QtGuiPrivate
3342 \inheaderfile rhi/qrhi.h
3343 \since 6.6
3344 \brief Describes a texture upload operation.
3345
3346 Used with QRhiResourceUpdateBatch::uploadTexture(). That function has two
3347 variants: one taking a QImage and one taking a
3348 QRhiTextureUploadDescription. The former is a convenience version,
3349 internally creating a QRhiTextureUploadDescription with a single image
3350 targeting level 0 for layer 0.
3351
3352 An example of the common, simple case of wanting to upload the contents
3353 of a QImage to a QRhiTexture with a matching pixel size:
3354
3355 \code
3356 QImage image(256, 256, QImage::Format_RGBA8888);
3357 image.fill(Qt::green); // or could use a QPainter targeting image
3358 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256));
3359 texture->create();
3360 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
3361 u->uploadTexture(texture, image);
3362 \endcode
3363
3364 When cubemaps, pre-generated mip images, compressed textures, or partial
3365 uploads are involved, applications will have to use this class instead.
3366
3367 QRhiTextureUploadDescription also enables specifying batched uploads, which
3368 are useful for example when generating an atlas or glyph cache texture:
3369 multiple, partial uploads for the same subresource (meaning the same layer
3370 and level) are supported, and can be, depending on the backend and the
3371 underlying graphics API, more efficient when batched into the same
3372 QRhiTextureUploadDescription as opposed to issuing individual
3373 \l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} commands for
3374 each of them.
3375
3376 \note Cubemaps have one layer for each of the six faces in the order +X,
3377 -X, +Y, -Y, +Z, -Z.
3378
3379 For example, specifying the faces of a cubemap could look like the following:
3380
3381 \code
3382 QImage faces[6];
3383 // ...
3384 QVarLengthArray<QRhiTextureUploadEntry, 6> entries;
3385 for (int i = 0; i < 6; ++i)
3386 entries.append(QRhiTextureUploadEntry(i, 0, faces[i]));
3387 QRhiTextureUploadDescription desc;
3388 desc.setEntries(entries.cbegin(), entries.cend());
3389 resourceUpdates->uploadTexture(texture, desc);
3390 \endcode
3391
3392 Another example that specifies mip images for a compressed texture:
3393
3394 \code
3395 QList<QRhiTextureUploadEntry> entries;
3396 const int mipCount = rhi->mipLevelsForSize(compressedTexture->pixelSize());
3397 for (int level = 0; level < mipCount; ++level) {
3398 const QByteArray compressedDataForLevel = ..
3399 entries.append(QRhiTextureUploadEntry(0, level, compressedDataForLevel));
3400 }
3401 QRhiTextureUploadDescription desc;
3402 desc.setEntries(entries.cbegin(), entries.cend());
3403 resourceUpdates->uploadTexture(compressedTexture, desc);
3404 \endcode
3405
3406 With partial uploads targeting the same subresource, it is recommended to
3407 batch them into a single upload request, whenever possible:
3408
3409 \code
3410 QRhiTextureSubresourceUploadDescription subresDesc(image);
3411 subresDesc.setSourceSize(QSize(10, 10));
3412 subResDesc.setDestinationTopLeft(QPoint(50, 40));
3413 QRhiTextureUploadEntry entry(0, 0, subresDesc); // layer 0, level 0
3414
3415 QRhiTextureSubresourceUploadDescription subresDesc2(image);
3416 subresDesc2.setSourceSize(QSize(30, 40));
3417 subResDesc2.setDestinationTopLeft(QPoint(100, 200));
3418 QRhiTextureUploadEntry entry2(0, 0, subresDesc2); // layer 0, level 0, i.e. same subresource
3419
3420 QRhiTextureUploadDescription desc({ entry, entry2});
3421 resourceUpdates->uploadTexture(texture, desc);
3422 \endcode
3423
3424 Batching is a recommendation, not a requirement. The subresources of a
3425 texture, including the mip levels of a compressed texture, can also be
3426 uploaded via separate
3427 \l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} calls, in any
3428 order, and spread over multiple frames. This is what streaming a mip chain
3429 under a per-frame upload budget needs.
3430
3431 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3432 for details.
3433
3434 \sa QRhiResourceUpdateBatch
3435 */
3436
3437/*!
3438 \fn QRhiTextureUploadDescription::QRhiTextureUploadDescription()
3439
3440 Constructs an empty texture upload description.
3441 */
3442
3443/*!
3444 Constructs a texture upload description with a single subresource upload
3445 described by \a entry.
3446 */
3447QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry)
3448{
3449 m_entries.append(entry);
3450}
3451
3452/*!
3453 Constructs a texture upload description with the specified \a list of entries.
3454
3455 \note \a list can also contain multiple QRhiTextureUploadEntry elements
3456 with the same layer and level. This makes sense when those uploads are
3457 partial, meaning their subresource description has a source size or image
3458 smaller than the subresource dimensions, and can be more efficient than
3459 issuing separate uploadTexture()'s.
3460 */
3461QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list)
3462 : m_entries(list)
3463{
3464}
3465
3466/*!
3467 \fn void QRhiTextureUploadDescription::setEntries(std::initializer_list<QRhiTextureUploadEntry> list)
3468 Sets the \a list of entries.
3469 */
3470
3471/*!
3472 \fn template<typename InputIterator> void QRhiTextureUploadDescription::setEntries(InputIterator first, InputIterator last)
3473 Sets the list of entries using the iterators \a first and \a last.
3474 */
3475
3476/*!
3477 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cbeginEntries() const
3478 \return a const iterator pointing to the first item in the entry list.
3479 */
3480
3481/*!
3482 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cendEntries() const
3483 \return a const iterator pointing just after the last item in the entry list.
3484 */
3485
3486/*!
3487 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::entryAt(qsizetype index) const
3488 \return the entry at \a index.
3489 */
3490
3491/*!
3492 \fn qsizetype QRhiTextureUploadDescription::entryCount() const
3493 \return the number of entries.
3494 */
3495
3496/*!
3497 \class QRhiBufferCopyDescription
3498 \inmodule QtGuiPrivate
3499 \inheaderfile rhi/qrhi.h
3500 \since 6.13
3501 \brief Describes a buffer-to-buffer copy operation.
3502
3503 A size() of 0 indicates that the entire source buffer is to be copied. A
3504 default constructed copy description therefore leads to copying the whole
3505 of the source buffer to the beginning of the destination buffer.
3506
3507 \note The copied region must fit both the source and the destination
3508 buffer. When it does not, QRhiResourceUpdateBatch::copyBuffer() prints a
3509 warning and drops the operation.
3510
3511 \note size(), sourceOffset(), and destinationOffset() should all be
3512 multiples of 4. This is a requirement of the blit encoder in Metal, and it
3513 applies on macOS on Intel-based devices. Other platforms and 3D APIs,
3514 including Metal on Apple Silicon and on iOS, have no such restriction, but
3515 portable code has to assume the strictest of these. Note that a size() of 0
3516 implies the full size of the source buffer, which is not necessarily a
3517 multiple of 4 either.
3518
3519 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3520 for details.
3521
3522 \sa QRhiResourceUpdateBatch::copyBuffer()
3523 */
3524
3525/*!
3526 \fn QRhiBufferCopyDescription::QRhiBufferCopyDescription()
3527
3528 Constructs an empty buffer copy description.
3529 */
3530
3531/*!
3532 \fn quint32 QRhiBufferCopyDescription::size() const
3533 \return the number of bytes to copy.
3534
3535 \note A size() of 0 indicates that the entire source buffer is to be
3536 copied.
3537 */
3538
3539/*!
3540 \fn void QRhiBufferCopyDescription::setSize(quint32 sz)
3541 Sets the number of bytes to copy to \a sz.
3542 */
3543
3544/*!
3545 \fn quint32 QRhiBufferCopyDescription::sourceOffset() const
3546 \return the offset in bytes into the source buffer. Defaults to 0.
3547 */
3548
3549/*!
3550 \fn void QRhiBufferCopyDescription::setSourceOffset(quint32 offset)
3551 Sets the source \a offset in bytes.
3552 */
3553
3554/*!
3555 \fn quint32 QRhiBufferCopyDescription::destinationOffset() const
3556 \return the offset in bytes into the destination buffer. Defaults to 0.
3557 */
3558
3559/*!
3560 \fn void QRhiBufferCopyDescription::setDestinationOffset(quint32 offset)
3561 Sets the destination \a offset in bytes.
3562 */
3563
3564/*!
3565 \class QRhiTextureCopyDescription
3566 \inmodule QtGuiPrivate
3567 \inheaderfile rhi/qrhi.h
3568 \since 6.6
3569 \brief Describes a texture-to-texture copy operation.
3570
3571 An empty pixelSize() indicates that the entire subresource is to be copied.
3572 A default constructed copy description therefore leads to copying the
3573 entire subresource at level 0 of layer 0.
3574
3575 \note The source texture must be created with
3576 QRhiTexture::UsedAsTransferSource.
3577
3578 \note The source and destination rectangles defined by pixelSize(),
3579 sourceTopLeft(), and destinationTopLeft() must fit the source and
3580 destination textures, respectively. The behavior is undefined otherwise.
3581
3582 With cubemaps, 3D textures, and texture arrays one face or slice can be
3583 copied at a time. The face or slice is specified by the source and
3584 destination layer indices. With mipmapped textures one mip level can be
3585 copied at a time. The source and destination layer and mip level indices can
3586 differ, but the size and position must be carefully controlled to avoid out
3587 of bounds copies, in which case the behavior is undefined.
3588
3589 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3590 for details.
3591 */
3592
3593/*!
3594 \fn QRhiTextureCopyDescription::QRhiTextureCopyDescription()
3595
3596 Constructs an empty texture copy description.
3597 */
3598
3599/*!
3600 \fn QSize QRhiTextureCopyDescription::pixelSize() const
3601 \return the size of the region to copy.
3602
3603 \note An empty pixelSize() indicates that the entire subresource is to be
3604 copied. A default constructed copy description therefore leads to copying
3605 the entire subresource at level 0 of layer 0.
3606 */
3607
3608/*!
3609 \fn void QRhiTextureCopyDescription::setPixelSize(const QSize &sz)
3610 Sets the size of the region to copy to \a sz.
3611 */
3612
3613/*!
3614 \fn int QRhiTextureCopyDescription::sourceLayer() const
3615 \return the source array layer (cubemap face or array layer index). Defaults to 0.
3616 */
3617
3618/*!
3619 \fn void QRhiTextureCopyDescription::setSourceLayer(int layer)
3620 Sets the source array \a layer.
3621 */
3622
3623/*!
3624 \fn int QRhiTextureCopyDescription::sourceLevel() const
3625 \return the source mip level. Defaults to 0.
3626 */
3627
3628/*!
3629 \fn void QRhiTextureCopyDescription::setSourceLevel(int level)
3630 Sets the source mip \a level.
3631 */
3632
3633/*!
3634 \fn QPoint QRhiTextureCopyDescription::sourceTopLeft() const
3635 \return the source top-left position (in pixels). Defaults to (0, 0).
3636 */
3637
3638/*!
3639 \fn void QRhiTextureCopyDescription::setSourceTopLeft(const QPoint &p)
3640 Sets the source top-left position to \a p.
3641 */
3642
3643/*!
3644 \fn int QRhiTextureCopyDescription::destinationLayer() const
3645 \return the destination array layer (cubemap face or array layer index). Default to 0.
3646 */
3647
3648/*!
3649 \fn void QRhiTextureCopyDescription::setDestinationLayer(int layer)
3650 Sets the destination array \a layer.
3651 */
3652
3653/*!
3654 \fn int QRhiTextureCopyDescription::destinationLevel() const
3655 \return the destionation mip level. Defaults to 0.
3656 */
3657
3658/*!
3659 \fn void QRhiTextureCopyDescription::setDestinationLevel(int level)
3660 Sets the destination mip \a level.
3661 */
3662
3663/*!
3664 \fn QPoint QRhiTextureCopyDescription::destinationTopLeft() const
3665 \return the destionation top-left position in pixels. Defaults to (0, 0).
3666 */
3667
3668/*!
3669 \fn void QRhiTextureCopyDescription::setDestinationTopLeft(const QPoint &p)
3670 Sets the destination top-left position \a p.
3671 */
3672
3673/*!
3674 \class QRhiReadbackDescription
3675 \inmodule QtGuiPrivate
3676 \inheaderfile rhi/qrhi.h
3677 \since 6.6
3678 \brief Describes a readback (reading back texture contents from possibly GPU-only memory) operation.
3679
3680 The source of the readback operation is either a QRhiTexture or the
3681 current backbuffer of the currently targeted QRhiSwapChain. When
3682 texture() is not set, the swapchain is used. Otherwise the specified
3683 QRhiTexture is treated as the source.
3684
3685 \note Textures used in readbacks must be created with
3686 QRhiTexture::UsedAsTransferSource.
3687
3688 \note Swapchains used in readbacks must be created with
3689 QRhiSwapChain::UsedAsTransferSource.
3690
3691 layer() and level() are only applicable when the source is a QRhiTexture.
3692
3693 \note Multisample textures cannot be read back. Readbacks are supported for
3694 multisample swapchain buffers however.
3695
3696 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3697 for details.
3698 */
3699
3700/*!
3701 \fn QRhiReadbackDescription::QRhiReadbackDescription() = default
3702
3703 Constructs an empty texture readback description.
3704
3705 \note The source texture is set to null by default, which is still a valid
3706 readback: it specifies that the backbuffer of the current swapchain is to
3707 be read back. (current meaning the frame's target swapchain at the time of
3708 committing the QRhiResourceUpdateBatch with the
3709 \l{QRhiResourceUpdateBatch::readBackTexture()}{texture readback} on it)
3710 */
3711
3712/*!
3713 Constructs an texture readback description that specifies that level 0 of
3714 layer 0 of \a texture is to be read back.
3715
3716 \note \a texture can also be null in which case this constructor is
3717 identical to the argumentless variant.
3718 */
3719QRhiReadbackDescription::QRhiReadbackDescription(QRhiTexture *texture)
3720 : m_texture(texture)
3721{
3722}
3723
3724/*!
3725 \fn QRhiTexture *QRhiReadbackDescription::texture() const
3726
3727 \return the QRhiTexture that is read back. Can be left set to \nullptr
3728 which indicates that the backbuffer of the current swapchain is to be used
3729 instead.
3730 */
3731
3732/*!
3733 \fn void QRhiReadbackDescription::setTexture(QRhiTexture *tex)
3734
3735 Sets the texture \a tex as the source of the readback operation.
3736
3737 Setting \nullptr is valid too, in which case the current swapchain's
3738 current backbuffer is used. (but then the readback cannot be issued in a
3739 non-swapchain-based frame)
3740
3741 \note Multisample textures cannot be read back. Readbacks are supported for
3742 multisample swapchain buffers however.
3743
3744 \note Textures used in readbacks must be created with
3745 QRhiTexture::UsedAsTransferSource.
3746
3747 \note Swapchains used in readbacks must be created with
3748 QRhiSwapChain::UsedAsTransferSource.
3749 */
3750
3751/*!
3752 \fn int QRhiReadbackDescription::layer() const
3753
3754 \return the currently set array layer (cubemap face, array index). Defaults to 0.
3755
3756 Applicable only when the source of the readback is a QRhiTexture.
3757 */
3758
3759/*!
3760 \fn void QRhiReadbackDescription::setLayer(int layer)
3761 Sets the array \a layer to read back.
3762 */
3763
3764/*!
3765 \fn int QRhiReadbackDescription::level() const
3766
3767 \return the currently set mip level. Defaults to 0.
3768
3769 Applicable only when the source of the readback is a QRhiTexture.
3770 */
3771
3772/*!
3773 \fn void QRhiReadbackDescription::setLevel(int level)
3774 Sets the mip \a level to read back.
3775 */
3776
3777/*!
3778 \fn const QRect &QRhiReadbackDescription::rect() const
3779 \since 6.10
3780
3781 \return the rectangle to read back. Defaults to an invalid rectangle.
3782
3783 If invalid, the entire texture or swapchain backbuffer is read back.
3784 */
3785
3786/*!
3787 \fn void QRhiReadbackDescription::setRect(const QRect &rectangle)
3788 \since 6.10
3789
3790 Sets the \a rectangle to read back.
3791 */
3792
3793/*!
3794 \class QRhiReadbackResult
3795 \inmodule QtGuiPrivate
3796 \inheaderfile rhi/qrhi.h
3797 \since 6.6
3798 \brief Describes the results of a potentially asynchronous buffer or texture readback operation.
3799
3800 When \l completed is set, the function is invoked when the \l data is
3801 available. \l format and \l pixelSize are set upon completion together with
3802 \l data.
3803
3804 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3805 for details.
3806 */
3807
3808/*!
3809 \variable QRhiReadbackResult::completed
3810
3811 Callback that is invoked upon completion, on the thread the QRhi operates
3812 on. Can be left set to \nullptr, in which case no callback is invoked.
3813 */
3814
3815/*!
3816 \variable QRhiReadbackResult::format
3817
3818 Valid only for textures, the texture format.
3819 */
3820
3821/*!
3822 \variable QRhiReadbackResult::pixelSize
3823
3824 Valid only for textures, the size in pixels.
3825 */
3826
3827/*!
3828 \variable QRhiReadbackResult::data
3829
3830 The buffer or image data.
3831
3832 \sa QRhiResourceUpdateBatch::readBackTexture(), QRhiResourceUpdateBatch::readBackBuffer()
3833 */
3834
3835
3836/*!
3837 \class QRhiNativeHandles
3838 \inmodule QtGuiPrivate
3839 \inheaderfile rhi/qrhi.h
3840 \since 6.6
3841 \brief Base class for classes exposing backend-specific collections of native resource objects.
3842
3843 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3844 for details.
3845 */
3846
3847/*!
3848 \class QRhiResource
3849 \inmodule QtGuiPrivate
3850 \inheaderfile rhi/qrhi.h
3851 \since 6.6
3852 \brief Base class for classes encapsulating native resource objects.
3853
3854 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3855 for details.
3856 */
3857
3858/*!
3859 \enum QRhiResource::Type
3860 Specifies type of the resource.
3861
3862 \value Buffer
3863 \value Texture
3864 \value Sampler
3865 \value RenderBuffer
3866 \value RenderPassDescriptor
3867 \value SwapChainRenderTarget
3868 \value TextureRenderTarget
3869 \value ShaderResourceBindings
3870 \value GraphicsPipeline
3871 \value SwapChain
3872 \value ComputePipeline
3873 \value CommandBuffer
3874 \value ShadingRateMap
3875 \value [since 6.13] IndirectCommandBuffer
3876 */
3877
3878/*!
3879 \fn virtual QRhiResource::Type QRhiResource::resourceType() const = 0
3880
3881 \return the type of the resource.
3882 */
3883
3884/*!
3885 \internal
3886 */
3887QRhiResource::QRhiResource(QRhiImplementation *rhi)
3888 : m_rhi(rhi)
3889{
3890 m_id = QRhiGlobalObjectIdGenerator::newId();
3891}
3892
3893/*!
3894 Destructor.
3895
3896 Releases (or requests deferred releasing of) the underlying native graphics
3897 resources, if there are any.
3898
3899 \note Resources referenced by commands for the current frame should not be
3900 released until the frame is submitted by QRhi::endFrame().
3901
3902 \sa destroy()
3903 */
3904QRhiResource::~QRhiResource()
3905{
3906 // destroy() cannot be called here, due to virtuals; it is up to the
3907 // subclasses to do that.
3908}
3909
3910/*!
3911 \fn virtual void QRhiResource::destroy() = 0
3912
3913 Releases (or requests deferred releasing of) the underlying native graphics
3914 resources. Safe to call multiple times, subsequent invocations will be a
3915 no-op then.
3916
3917 Once destroy() is called, the QRhiResource instance can be reused, by
3918 calling \c create() again. That will then result in creating new native
3919 graphics resources underneath.
3920
3921 \note Resources referenced by commands for the current frame should not be
3922 released until the frame is submitted by QRhi::endFrame().
3923
3924 The QRhiResource destructor also performs the same task, so calling this
3925 function is not necessary before deleting a QRhiResource.
3926
3927 \sa deleteLater()
3928 */
3929
3930/*!
3931 When called without a frame being recorded, this function is equivalent to
3932 deleting the object. Between a QRhi::beginFrame() and QRhi::endFrame()
3933 however the behavior is different: the QRhiResource will not be destroyed
3934 until the frame is submitted via QRhi::endFrame(), thus satisfying the QRhi
3935 requirement of not altering QRhiResource objects that are referenced by the
3936 frame being recorded.
3937
3938 If the QRhi that created this object is already destroyed, the object is
3939 deleted immediately.
3940
3941 Using deleteLater() can be a useful convenience in many cases, and it
3942 complements the low-level guarantee (that the underlying native graphics
3943 objects are never destroyed until it is safe to do so and it is known for
3944 sure that they are not used by the GPU in an still in-flight frame), by
3945 offering a way to make sure the C++ object instances (of QRhiBuffer,
3946 QRhiTexture, etc.) themselves also stay valid until the end of the current
3947 frame.
3948
3949 The following example shows a convenient way of creating a throwaway buffer
3950 that is only used in one frame and gets automatically released in
3951 endFrame(). (when it comes to the underlying native buffer(s), the usual
3952 guarantee applies: the QRhi backend defers the releasing of those until it
3953 is guaranteed that the frame in which the buffer is accessed by the GPU has
3954 completed)
3955
3956 \code
3957 rhi->beginFrame(swapchain);
3958 QRhiBuffer *buf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, 256);
3959 buf->deleteLater(); // !
3960 u = rhi->nextResourceUpdateBatch();
3961 u->uploadStaticBuffer(buf, data);
3962 // ... draw with buf
3963 rhi->endFrame();
3964 \endcode
3965
3966 \sa destroy()
3967 */
3968void QRhiResource::deleteLater()
3969{
3970 if (m_rhi)
3971 m_rhi->addDeleteLater(this);
3972 else
3973 delete this;
3974}
3975
3976/*!
3977 \return the currently set object name. By default the name is empty.
3978 */
3979QByteArray QRhiResource::name() const
3980{
3981 return m_objectName;
3982}
3983
3984/*!
3985 Sets a \a name for the object.
3986
3987 This allows getting descriptive names for the native graphics
3988 resources visible in graphics debugging tools, such as
3989 \l{https://renderdoc.org/}{RenderDoc} and
3990 \l{https://developer.apple.com/xcode/}{XCode}.
3991
3992 When it comes to naming native objects by relaying the name via the
3993 appropriate graphics API, note that the name is ignored when
3994 QRhi::DebugMarkers are not supported, and may, depending on the backend,
3995 also be ignored when QRhi::EnableDebugMarkers is not set.
3996
3997 \note The name may be ignored for objects other than buffers,
3998 renderbuffers, and textures, depending on the backend.
3999
4000 \note The name may be modified. For slotted resources, such as a QRhiBuffer
4001 backed by multiple native buffers, QRhi will append a suffix to make the
4002 underlying native buffers easily distinguishable from each other.
4003 */
4004void QRhiResource::setName(const QByteArray &name)
4005{
4006 m_objectName = name;
4007}
4008
4009/*!
4010 \return the global, unique identifier of this QRhiResource.
4011
4012 User code rarely needs to deal with the value directly. It is used
4013 internally for tracking and bookkeeping purposes.
4014 */
4015quint64 QRhiResource::globalResourceId() const
4016{
4017 return m_id;
4018}
4019
4020/*!
4021 \return the QRhi that created this resource.
4022
4023 If the QRhi that created this object is already destroyed, the result is
4024 \nullptr.
4025 */
4026QRhi *QRhiResource::rhi() const
4027{
4028 return m_rhi ? m_rhi->q : nullptr;
4029}
4030
4031/*!
4032 \class QRhiBuffer
4033 \inmodule QtGuiPrivate
4034 \inheaderfile rhi/qrhi.h
4035 \since 6.6
4036 \brief Vertex, index, or uniform (constant) buffer resource.
4037
4038 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4039 for details.
4040
4041 A QRhiBuffer encapsulates zero, one, or more native buffer objects (such as
4042 a \c VkBuffer or \c MTLBuffer). With some graphics APIs and backends
4043 certain types of buffers may not use a native buffer object at all (e.g.
4044 OpenGL if uniform buffer objects are not used), but this is transparent to
4045 the user of the QRhiBuffer API. Similarly, the fact that some types of
4046 buffers may use two or three native buffers underneath, in order to allow
4047 efficient per-frame content update without stalling the GPU pipeline, is
4048 mostly invisible to the applications and libraries.
4049
4050 A QRhiBuffer instance is always created by calling
4051 \l{QRhi::newBuffer()}{the QRhi's newBuffer() function}. This creates no
4052 native graphics resources. To do that, call create() after setting the
4053 appropriate options, such as the type, usage flags, size, although in most cases these
4054 are already set based on the arguments passed to
4055 \l{QRhi::newBuffer()}{newBuffer()}.
4056
4057 \section1 Example usage
4058
4059 To create a uniform buffer for a shader where the GLSL uniform block
4060 contains a single \c mat4 member, and update the contents:
4061
4062 \code
4063 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64);
4064 if (!ubuf->create()) { error(); }
4065 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4066 QMatrix4x4 mvp;
4067 // ... set up the modelview-projection matrix
4068 batch->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
4069 // ...
4070 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4071 \endcode
4072
4073 An example of creating a buffer with vertex data:
4074
4075 \code
4076 const float vertices[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f };
4077 QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices));
4078 if (!vbuf->create()) { error(); }
4079 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4080 batch->uploadStaticBuffer(vbuf, vertices);
4081 // ...
4082 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4083 \endcode
4084
4085 An index buffer:
4086
4087 \code
4088 static const quint16 indices[] = { 0, 1, 2 };
4089 QRhiBuffer *ibuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices));
4090 if (!ibuf->create()) { error(); }
4091 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4092 batch->uploadStaticBuffer(ibuf, indices);
4093 // ...
4094 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4095 \endcode
4096
4097 \section1 Common patterns
4098
4099 A call to create() destroys any existing native resources if create() was
4100 successfully called before. If those native resources are still in use by
4101 an in-flight frame (i.e., there's a chance they are still read by the GPU),
4102 the destroying of those resources is deferred automatically. Thus a very
4103 common and convenient pattern to safely increase the size of an already
4104 initialized buffer is the following. In practice this drops and creates a
4105 whole new set of native resources underneath, so it is not necessarily a
4106 cheap operation, but is more convenient and still faster than the
4107 alternatives, because by not destroying the \c buf object itself, all
4108 references to it stay valid in other data structures (e.g., in any
4109 QRhiShaderResourceBinding the QRhiBuffer is referenced from).
4110
4111 \code
4112 if (buf->size() < newSize) {
4113 buf->setSize(newSize);
4114 if (!buf->create()) { error(); }
4115 }
4116 // continue using buf, fill it with new data
4117 \endcode
4118
4119 When working with uniform buffers, it will sometimes be necessary to
4120 combine data for multiple draw calls into a single buffer for efficiency
4121 reasons. Be aware of the aligment requirements: with some graphics APIs
4122 offsets for a uniform buffer must be aligned to 256 bytes. This applies
4123 both to QRhiShaderResourceBinding and to the dynamic offsets passed to
4124 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}. Use the
4125 \l{QRhi::ubufAlignment()}{ubufAlignment()} and
4126 \l{QRhi::ubufAligned()}{ubufAligned()} functions to create portable code.
4127 As an example, the following is an outline for issuing multiple (\c N) draw
4128 calls with the same pipeline and geometry, but with a different data in the
4129 uniform buffers exposed at binding point 0. This assumes the buffer is
4130 exposed via
4131 \l{QRhiShaderResourceBinding::uniformBufferWithDynamicOffset()}{uniformBufferWithDynamicOffset()}
4132 which allows passing a QRhiCommandBuffer::DynamicOffset list to
4133 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}.
4134
4135 \code
4136 const int N = 2;
4137 const int UB_SIZE = 64 + 4; // assuming a uniform block with { mat4 matrix; float opacity; }
4138 const int ONE_UBUF_SIZE = rhi->ubufAligned(UB_SIZE);
4139 const int TOTAL_UBUF_SIZE = N * ONE_UBUF_SIZE;
4140 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, TOTAL_UBUF_SIZE);
4141 if (!ubuf->create()) { error(); }
4142 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4143 for (int i = 0; i < N; ++i) {
4144 batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE, 64, matrix.constData());
4145 batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE + 64, 4, &opacity);
4146 }
4147 // ...
4148 // beginPass(), set pipeline, etc., and then:
4149 for (int i = 0; i < N; ++i) {
4150 QRhiCommandBuffer::DynamicOffset dynOfs[] = { { 0, i * ONE_UBUF_SIZE } };
4151 cb->setShaderResources(srb, 1, dynOfs);
4152 cb->draw(36);
4153 }
4154 \endcode
4155
4156 \sa QRhiResourceUpdateBatch, QRhi, QRhiCommandBuffer
4157 */
4158
4159/*!
4160 \enum QRhiBuffer::Type
4161 Specifies storage type of buffer resource.
4162
4163 \value Immutable Indicates that the data is not expected to change ever
4164 after the initial upload. Under the hood such buffer resources are
4165 typically placed in device local (GPU) memory (on systems where
4166 applicable). Uploading new data is possible, but may be expensive. The
4167 upload typically happens by copying to a separate, host visible staging
4168 buffer from which a GPU buffer-to-buffer copy is issued into the actual
4169 GPU-only buffer.
4170
4171 \value Static Indicates that the data is expected to change only
4172 infrequently. Typically placed in device local (GPU) memory, where
4173 applicable. On backends where host visible staging buffers are used for
4174 uploading, the staging buffers are kept around for this type, unlike with
4175 Immutable, so subsequent uploads do not suffer in performance. Frequent
4176 updates, especially updates in consecutive frames, should be avoided.
4177
4178 \value Dynamic Indicates that the data is expected to change frequently.
4179 Not recommended for large buffers. Typically backed by host visible memory
4180 in 2 copies in order to allow for changing without stalling the graphics
4181 pipeline. The double buffering is managed transparently to the applications
4182 and is not exposed in the API here in any form. This is the recommended,
4183 and, with some backends, the only possible, type for buffers with
4184 UniformBuffer usage.
4185 */
4186
4187/*!
4188 \enum QRhiBuffer::UsageFlag
4189 Flag values to specify how the buffer is going to be used.
4190
4191 \value VertexBuffer Vertex buffer. This allows the QRhiBuffer to be used in
4192 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
4193
4194 \value IndexBuffer Index buffer. This allows the QRhiBuffer to be used in
4195 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
4196
4197 \value UniformBuffer Uniform buffer (also called constant buffer). This
4198 allows the QRhiBuffer to be used in combination with
4199 \l{QRhiShaderResourceBinding::UniformBuffer}{UniformBuffer}. When
4200 \l{QRhi::NonDynamicUniformBuffers}{NonDynamicUniformBuffers} is reported as
4201 not supported, this usage can only be combined with the type Dynamic.
4202
4203 \value StorageBuffer Storage buffer. This allows the QRhiBuffer to be used
4204 in combination with \l{QRhiShaderResourceBinding::BufferLoad}{BufferLoad},
4205 \l{QRhiShaderResourceBinding::BufferStore}{BufferStore}, or
4206 \l{QRhiShaderResourceBinding::BufferLoadStore}{BufferLoadStore}. This usage
4207 can only be combined with the types Immutable or Static, and is only
4208 available when the \l{QRhi::Compute}{Compute feature} is reported as
4209 supported.
4210
4211 \value [since 6.12] IndirectBuffer Indirect draw or dispatch buffer. This
4212 allows the QRhiBuffer to be used in
4213 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()},
4214 \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}, and
4215 \l{QRhiCommandBuffer::dispatchIndirect()}{dispatchIndirect()}.
4216 This usage can be combined with types Immutable or Static. Combining it with
4217 Dynamic is unsupported with D3D11, where create() will fail. This usage may
4218 also be combined with StorageBuffer on backends that support
4219 \l{QRhi::Compute}{compute shaders}, allowing indirect draw or dispatch
4220 commands to be generated by compute shaders and consumed by indirect
4221 draw/dispatch calls.
4222 */
4223
4224/*!
4225 \class QRhiBuffer::NativeBuffer
4226 \inmodule QtGuiPrivate
4227 \inheaderfile rhi/qrhi.h
4228 \brief Contains information about the underlying native resources of a buffer.
4229 */
4230
4231/*!
4232 \variable QRhiBuffer::NativeBuffer::objects
4233 \brief an array with pointers to the native object handles.
4234
4235 With OpenGL, the native handle is a GLuint value, so the elements in the \c
4236 objects array are pointers to a GLuint. With Vulkan, the native handle is a
4237 VkBuffer, so the elements of the array are pointers to a VkBuffer. With
4238 Direct3D 11 and Metal the elements are pointers to a ID3D11Buffer or
4239 MTLBuffer pointer, respectively. With Direct3D 12, the elements are
4240 pointers to a ID3D12Resource.
4241
4242 \note Pay attention to the fact that the elements are always pointers to
4243 the native buffer handle type, even if the native type itself is a pointer.
4244 (so the elements are \c{VkBuffer *} on Vulkan, even though VkBuffer itself
4245 is a pointer on 64-bit architectures).
4246 */
4247
4248/*!
4249 \variable QRhiBuffer::NativeBuffer::slotCount
4250 \brief Specifies the number of valid elements in the objects array.
4251
4252 The value can be 0, 1, 2, or 3 in practice. 0 indicates that the QRhiBuffer
4253 is not backed by any native buffer objects. This can happen with
4254 QRhiBuffers with the usage UniformBuffer when the underlying API does not
4255 support (or the backend chooses not to use) native uniform buffers. 1 is
4256 commonly used for Immutable and Static types (but some backends may
4257 differ). 2 or 3 is typical when the type is Dynamic (but some backends may
4258 differ).
4259
4260 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4261 */
4262
4263/*!
4264 \internal
4265 */
4266QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, quint32 size_)
4267 : QRhiResource(rhi),
4268 m_type(type_), m_usage(usage_), m_size(size_)
4269{
4270}
4271
4272/*!
4273 \return the resource type.
4274 */
4275QRhiResource::Type QRhiBuffer::resourceType() const
4276{
4277 return Buffer;
4278}
4279
4280/*!
4281 \fn virtual bool QRhiBuffer::create() = 0
4282
4283 Creates the corresponding native graphics resources. If there are already
4284 resources present due to an earlier create() with no corresponding
4285 destroy(), then destroy() is called implicitly first.
4286
4287 \return \c true when successful, \c false when a graphics operation failed.
4288 Regardless of the return value, calling destroy() is always safe.
4289 */
4290
4291/*!
4292 \fn QRhiBuffer::Type QRhiBuffer::type() const
4293 \return the buffer type.
4294 */
4295
4296/*!
4297 \fn void QRhiBuffer::setType(Type t)
4298 Sets the buffer's type to \a t.
4299 */
4300
4301/*!
4302 \fn QRhiBuffer::UsageFlags QRhiBuffer::usage() const
4303 \return the buffer's usage flags.
4304 */
4305
4306/*!
4307 \fn void QRhiBuffer::setUsage(UsageFlags u)
4308 Sets the buffer's usage flags to \a u.
4309 */
4310
4311/*!
4312 \fn quint32 QRhiBuffer::size() const
4313
4314 \return the buffer's size in bytes.
4315
4316 This is always the value that was passed to setSize() or QRhi::newBuffer().
4317 Internally, the native buffers may be bigger if that is required by the
4318 underlying graphics API.
4319 */
4320
4321/*!
4322 \fn void QRhiBuffer::setSize(quint32 sz)
4323
4324 Sets the size of the buffer in bytes. The size is normally specified in
4325 QRhi::newBuffer() so this function is only used when the size has to be
4326 changed. As with other setters, the size only takes effect when calling
4327 create(), and for already created buffers this involves releasing the previous
4328 native resource and creating new ones under the hood.
4329
4330 Backends may choose to allocate buffers bigger than \a sz in order to
4331 fulfill alignment requirements. This is hidden from the applications and
4332 size() will always report the size requested in \a sz.
4333 */
4334
4335/*!
4336 \return the underlying native resources for this buffer. The returned value
4337 will be empty if exposing the underlying native resources is not supported by
4338 the backend.
4339
4340 A QRhiBuffer may be backed by multiple native buffer objects, depending on
4341 the type() and the QRhi backend in use. When this is the case, all of them
4342 are returned in the objects array in the returned struct, with slotCount
4343 specifying the number of native buffer objects. While
4344 \l{QRhi::beginFrame()}{recording a frame}, QRhi::currentFrameSlot() can be
4345 used to determine which of the native buffers QRhi is using for operations
4346 that read or write from this QRhiBuffer within the frame being recorded.
4347
4348 In some cases a QRhiBuffer will not be backed by a native buffer object at
4349 all. In this case slotCount will be set to 0 and no valid native objects
4350 are returned. This is not an error, and is perfectly valid when a given
4351 backend does not use native buffers for QRhiBuffers with certain types or
4352 usages.
4353
4354 \note Be aware that QRhi backends may employ various buffer update
4355 strategies. Unlike textures, where uploading image data always means
4356 recording a buffer-to-image (or similar) copy command on the command
4357 buffer, buffers, in particular Dynamic and UniformBuffer ones, can operate
4358 in many different ways. For example, a QRhiBuffer with usage type
4359 UniformBuffer may not even be backed by a native buffer object at all if
4360 uniform buffers are not used or supported by a given backend and graphics
4361 API. There are also differences to how data is written to the buffer and
4362 the type of backing memory used. For buffers backed by host visible memory,
4363 calling this function guarantees that pending host writes are executed for
4364 all the returned native buffers.
4365
4366 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4367 */
4368QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
4369{
4370 return { {}, 0 };
4371}
4372
4373/*!
4374 \return a pointer to a memory block with the host visible buffer data.
4375
4376 This is a shortcut for medium-to-large dynamic uniform buffers that have
4377 their \b entire contents (or at least all regions that are read by the
4378 shaders in the current frame) changed \b{in every frame} and the
4379 QRhiResourceUpdateBatch-based update mechanism is seen too heavy due to the
4380 amount of data copying involved.
4381
4382 The call to this function must be eventually followed by a call to
4383 endFullDynamicUniformBufferUpdateForCurrentFrame(), before recording any
4384 render or compute pass that relies on this buffer.
4385
4386 \warning Updating data via this method is not compatible with
4387 QRhiResourceUpdateBatch-based updates and readbacks. Unexpected behavior
4388 may occur when attempting to combine the two update models for the same
4389 buffer. Similarly, the data updated this direct way may not be visible to
4390 \l{QRhiResourceUpdateBatch::readBackBuffer()}{readBackBuffer operations},
4391 depending on the backend.
4392
4393 \warning When updating buffer data via this method, the update must be done
4394 in every frame, otherwise backends that perform double or triple buffering
4395 of resources may end up in unexpected behavior.
4396
4397 \warning Partial updates are not possible with this approach since some
4398 backends may choose a strategy where the previous contents of the buffer is
4399 lost upon calling this function. Data must be written to all regions that
4400 are read by shaders in the frame currently being prepared.
4401
4402 \warning This function can only be called when recording a frame, so
4403 between QRhi::beginFrame() and QRhi::endFrame().
4404
4405 \warning This function can only be called on Dynamic buffers.
4406 */
4407char *QRhiBuffer::beginFullDynamicBufferUpdateForCurrentFrame()
4408{
4409 return nullptr;
4410}
4411
4412/*!
4413 To be called when the entire contents of the buffer data has been updated
4414 in the memory block returned from
4415 beginFullDynamicBufferUpdateForCurrentFrame().
4416 */
4417void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
4418{
4419}
4420
4421/*!
4422 \internal
4423 */
4424void QRhiBuffer::fullDynamicBufferUpdateForCurrentFrame(const void *data, quint32 size)
4425{
4426 char *p = beginFullDynamicBufferUpdateForCurrentFrame();
4427 if (p) {
4428 memcpy(p, data, size > 0 ? size : m_size);
4429 endFullDynamicBufferUpdateForCurrentFrame();
4430 }
4431}
4432
4433/*!
4434 \class QRhiRenderBuffer
4435 \inmodule QtGuiPrivate
4436 \inheaderfile rhi/qrhi.h
4437 \since 6.6
4438 \brief Renderbuffer resource.
4439
4440 Renderbuffers cannot be sampled or read but have some benefits over
4441 textures in some cases:
4442
4443 A \l DepthStencil renderbuffer may be lazily allocated and be backed by
4444 transient memory with some APIs. On some platforms this may mean the
4445 depth/stencil buffer uses no physical backing at all.
4446
4447 That transient nature has a consequence: the contents of a \l DepthStencil
4448 renderbuffer are not guaranteed to survive if a backend has to interrupt and
4449 restart a render pass internally. With Metal this happens when a draw call
4450 is implemented via indirect command buffers, which is the case for
4451 \l{QRhiCommandBuffer::drawIndirectCount()}{drawIndirectCount()} and its
4452 indexed variant, for a high draw count
4453 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()} or
4454 \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}, and
4455 also when tessellation is used. Draws recorded after such a call then
4456 depth-test against a depth buffer that lost its contents. When this matters,
4457 set the \l NoTransientBacking flag, which makes the contents preservable at
4458 the cost of the memory and bandwidth that the transient backing was saving.
4459 Alternatively, where a QRhiTextureRenderTarget is used anyway, attach a depth
4460 or depth-stencil QRhiTexture with
4461 \l{QRhiTextureRenderTargetDescription::setDepthTexture()}{setDepthTexture()}
4462 instead of a renderbuffer: that is preserved across an interruption, unless
4463 QRhiTextureRenderTarget::DoNotStoreDepthStencilContents is set.
4464
4465 Note that the indirect drawing cases above are avoidable. A
4466 QRhiIndirectCommandBuffer executed with
4467 \l{QRhiCommandBuffer::executeIndirect()}{executeIndirect()} is prepared
4468 before the render pass begins, so it never interrupts the pass however many
4469 commands it holds, and none of this applies to it. Only tessellation then
4470 remains as a reason to consider \l NoTransientBacking.
4471
4472 \l Color renderbuffers are useful since QRhi::MultisampleRenderBuffer may be
4473 supported even when QRhi::MultisampleTexture is not.
4474
4475 How the renderbuffer is implemented by a backend is not exposed to the
4476 applications. In some cases it may be backed by ordinary textures, while in
4477 others there may be a different kind of native resource used.
4478
4479 Renderbuffers that are used as (and are only used as) depth-stencil buffers
4480 in combination with a QRhiSwapChain's color buffers should have the
4481 UsedWithSwapChainOnly flag set. This serves a double purpose: such buffers,
4482 depending on the backend and the underlying APIs, be more efficient, and
4483 QRhi provides automatic sizing behavior to match the color buffers, which
4484 means calling setPixelSize() and create() are not necessary for such
4485 renderbuffers.
4486
4487 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4488 for details.
4489 */
4490
4491/*!
4492 \enum QRhiRenderBuffer::Type
4493 Specifies the type of the renderbuffer
4494
4495 \value DepthStencil Combined depth/stencil
4496 \value Color Color
4497 */
4498
4499/*!
4500 \struct QRhiRenderBuffer::NativeRenderBuffer
4501 \inmodule QtGuiPrivate
4502 \inheaderfile rhi/qrhi.h
4503 \brief Wraps a native renderbuffer object.
4504 */
4505
4506/*!
4507 \variable QRhiRenderBuffer::NativeRenderBuffer::object
4508 \brief 64-bit integer containing the native object handle.
4509
4510 Used with QRhiRenderBuffer::createFrom().
4511
4512 With OpenGL the native handle is a GLuint value. \c object is expected to
4513 be a valid OpenGL renderbuffer object ID.
4514 */
4515
4516/*!
4517 \enum QRhiRenderBuffer::Flag
4518 Flag values for flags() and setFlags()
4519
4520 \value UsedWithSwapChainOnly For DepthStencil renderbuffers this indicates
4521 that the renderbuffer is only used in combination with a QRhiSwapChain, and
4522 never in any other way. This provides automatic sizing and resource
4523 rebuilding, so calling setPixelSize() or create() is not needed whenever
4524 this flag is set. This flag value may also trigger backend-specific
4525 behavior, for example with OpenGL, where a separate windowing system
4526 interface API is in use (EGL, GLX, etc.), the flag is especially important
4527 as it avoids creating any actual renderbuffer resource as there is already
4528 a windowing system provided depth/stencil buffer as requested by
4529 QSurfaceFormat.
4530
4531 \value [since 6.13] NoTransientBacking Requests that the renderbuffer is not
4532 backed by transient, lazily allocated memory. Only relevant for
4533 \l DepthStencil renderbuffers, and only with backends that would otherwise
4534 choose such storage, which in practice means Metal on Apple GPUs. Set this
4535 when the contents have to survive a render pass being interrupted and
4536 continued internally by a backend, as described in the
4537 \l{QRhiRenderBuffer}{class documentation}. It costs actual memory and
4538 bandwidth for the depth/stencil buffer, so do not set it when not needed.
4539 In particular it is not needed on account of
4540 \l{QRhiCommandBuffer::executeIndirect()}{executeIndirect()}, which never
4541 interrupts the pass.
4542 */
4543
4544/*!
4545 \internal
4546 */
4547QRhiRenderBuffer::QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
4548 int sampleCount_, Flags flags_,
4549 QRhiTexture::Format backingFormatHint_)
4550 : QRhiResource(rhi),
4551 m_type(type_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_),
4552 m_backingFormatHint(backingFormatHint_)
4553{
4554}
4555
4556/*!
4557 \return the resource type.
4558 */
4559QRhiResource::Type QRhiRenderBuffer::resourceType() const
4560{
4561 return RenderBuffer;
4562}
4563
4564/*!
4565 \fn virtual bool QRhiRenderBuffer::create() = 0
4566
4567 Creates the corresponding native graphics resources. If there are already
4568 resources present due to an earlier create() with no corresponding
4569 destroy(), then destroy() is called implicitly first.
4570
4571 \return \c true when successful, \c false when a graphics operation failed.
4572 Regardless of the return value, calling destroy() is always safe.
4573 */
4574
4575/*!
4576 Similar to create() except that no new native renderbuffer objects are
4577 created. Instead, the native renderbuffer object specified by \a src is
4578 used.
4579
4580 This allows importing an existing renderbuffer object (which must belong to
4581 the same device or sharing context, depending on the graphics API) from an
4582 external graphics engine.
4583
4584 \note This is currently applicable to OpenGL only. This function exists
4585 solely to allow importing a renderbuffer object that is bound to some
4586 special, external object, such as an EGLImageKHR. Once the application
4587 performed the glEGLImageTargetRenderbufferStorageOES call, the renderbuffer
4588 object can be passed to this function to create a wrapping
4589 QRhiRenderBuffer, which in turn can be passed in as a color attachment to
4590 a QRhiTextureRenderTarget to enable rendering to the EGLImage.
4591
4592 \note pixelSize(), sampleCount(), and flags() must still be set correctly.
4593 Passing incorrect sizes and other values to QRhi::newRenderBuffer() and
4594 then following it with a createFrom() expecting that the native
4595 renderbuffer object alone is sufficient to deduce such values is \b wrong
4596 and will lead to problems.
4597
4598 \note QRhiRenderBuffer does not take ownership of the native object, and
4599 destroy() will not release that object.
4600
4601 \note This function is only implemented when the QRhi::RenderBufferImport
4602 feature is reported as \l{QRhi::isFeatureSupported()}{supported}. Otherwise,
4603 the function does nothing and the return value is \c false.
4604
4605 \return \c true when successful, \c false when not supported.
4606 */
4607bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
4608{
4609 Q_UNUSED(src);
4610 return false;
4611}
4612
4613/*!
4614 \fn QRhiRenderBuffer::Type QRhiRenderBuffer::type() const
4615 \return the renderbuffer type.
4616 */
4617
4618/*!
4619 \fn void QRhiRenderBuffer::setType(Type t)
4620 Sets the type to \a t.
4621 */
4622
4623/*!
4624 \fn QSize QRhiRenderBuffer::pixelSize() const
4625 \return the pixel size.
4626 */
4627
4628/*!
4629 \fn void QRhiRenderBuffer::setPixelSize(const QSize &sz)
4630 Sets the size (in pixels) to \a sz.
4631 */
4632
4633/*!
4634 \fn int QRhiRenderBuffer::sampleCount() const
4635 \return the sample count. 1 means no multisample antialiasing.
4636 */
4637
4638/*!
4639 \fn void QRhiRenderBuffer::setSampleCount(int s)
4640 Sets the sample count to \a s.
4641 */
4642
4643/*!
4644 \fn QRhiRenderBuffer::Flags QRhiRenderBuffer::flags() const
4645 \return the flags.
4646 */
4647
4648/*!
4649 \fn void QRhiRenderBuffer::setFlags(Flags f)
4650 Sets the flags to \a f.
4651 */
4652
4653/*!
4654 \fn virtual QRhiTexture::Format QRhiRenderBuffer::backingFormat() const = 0
4655
4656 \internal
4657 */
4658
4659/*!
4660 \class QRhiTexture
4661 \inmodule QtGuiPrivate
4662 \inheaderfile rhi/qrhi.h
4663 \since 6.6
4664 \brief Texture resource.
4665
4666 A QRhiTexture encapsulates a native texture object, such as a \c VkImage or
4667 \c MTLTexture.
4668
4669 A QRhiTexture instance is always created by calling
4670 \l{QRhi::newTexture()}{the QRhi's newTexture() function}. This creates no
4671 native graphics resources. To do that, call create() after setting the
4672 appropriate options, such as the format and size, although in most cases
4673 these are already set based on the arguments passed to
4674 \l{QRhi::newTexture()}{newTexture()}.
4675
4676 Setting the \l{QRhiTexture::Flags}{flags} correctly is essential, otherwise
4677 various errors can occur depending on the underlying QRhi backend and
4678 graphics API. For example, when a texture will be rendered into from a
4679 render pass via QRhiTextureRenderTarget, the texture must be created with
4680 the \l RenderTarget flag set. Similarly, when the texture is going to be
4681 \l{QRhiResourceUpdateBatch::readBackTexture()}{read back}, the \l
4682 UsedAsTransferSource flag must be set upfront. Mipmapped textures must have
4683 the MipMapped flag set. And so on. It is not possible to change the flags
4684 once create() has succeeded. To release the existing and create a new
4685 native texture object with the changed settings, call the setters and call
4686 create() again. This then might be a potentially expensive operation.
4687
4688 \section1 Example usage
4689
4690 To create a 2D texture with a size of 512x512 pixels and set its contents to all green:
4691
4692 \code
4693 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512));
4694 if (!texture->create()) { error(); }
4695 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4696 QImage image(512, 512, QImage::Format_RGBA8888);
4697 image.fill(Qt::green);
4698 batch->uploadTexture(texture, image);
4699 // ...
4700 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4701 \endcode
4702
4703 \section1 Common patterns
4704
4705 A call to create() destroys any existing native resources if create() was
4706 successfully called before. If those native resources are still in use by
4707 an in-flight frame (i.e., there's a chance they are still read by the GPU),
4708 the destroying of those resources is deferred automatically. Thus a very
4709 common and convenient pattern to safely change the size of an already
4710 existing texture is the following. In practice this drops and creates a
4711 whole new native texture resource underneath, so it is not necessarily a
4712 cheap operation, but is more convenient and still faster than the
4713 alternatives, because by not destroying the \c texture object itself, all
4714 references to it stay valid in other data structures (e.g., in any
4715 QShaderResourceBinding the QRhiTexture is referenced from).
4716
4717 \code
4718 // determine newSize, e.g. based on the swapchain's output size or other factors
4719 if (texture->pixelSize() != newSize) {
4720 texture->setPixelSize(newSize);
4721 if (!texture->create()) { error(); }
4722 }
4723 // continue using texture, fill it with new data
4724 \endcode
4725
4726 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4727 for details.
4728
4729 \sa QRhiResourceUpdateBatch, QRhi, QRhiTextureRenderTarget
4730 */
4731
4732/*!
4733 \enum QRhiTexture::Flag
4734
4735 Flag values to specify how the texture is going to be used. Not honoring
4736 the flags set before create() and attempting to use the texture in ways that
4737 was not declared upfront can lead to unspecified behavior or decreased
4738 performance depending on the backend and the underlying graphics API.
4739
4740 \value RenderTarget The texture going to be used in combination with
4741 QRhiTextureRenderTarget.
4742
4743 \value CubeMap The texture is a cubemap. Such textures have 6 layers, one
4744 for each face in the order of +X, -X, +Y, -Y, +Z, -Z. Cubemap textures
4745 cannot be multisample.
4746
4747 \value MipMapped The texture has mipmaps. The appropriate mip count is
4748 calculated automatically and can also be retrieved via
4749 QRhi::mipLevelsForSize(). The images for the mip levels have to be
4750 provided in the texture uploaded or generated via
4751 QRhiResourceUpdateBatch::generateMips(). Multisample textures cannot have
4752 mipmaps.
4753
4754 \value sRGB Use an sRGB format.
4755
4756 \value UsedAsTransferSource The texture is used as the source of a texture
4757 copy or readback, meaning the texture is given as the source in
4758 QRhiResourceUpdateBatch::copyTexture() or
4759 QRhiResourceUpdateBatch::readBackTexture().
4760
4761 \value UsedWithGenerateMips The texture is going to be used with
4762 QRhiResourceUpdateBatch::generateMips().
4763
4764 \value UsedWithLoadStore The texture is going to be used with image
4765 load/store operations, for example, in a compute shader.
4766
4767 \value UsedAsCompressedAtlas This value has no effect since Qt 6.13.
4768 Textures that have a compressed format and the dimensions of subresource
4769 uploads do not match the texture size are handled automatically now.
4770
4771 \value ExternalOES The texture should use the GL_TEXTURE_EXTERNAL_OES
4772 target with OpenGL. This flag is ignored with other graphics APIs.
4773
4774 \value ThreeDimensional The texture is a 3D texture. Such textures should
4775 be created with the QRhi::newTexture() overload taking a depth in addition
4776 to width and height. A 3D texture can have mipmaps but cannot be
4777 multisample. When rendering into, or uploading data to a 3D texture, the \c
4778 layer specified in the render target's color attachment or the upload
4779 description refers to a single slice in range [0..depth-1]. The underlying
4780 graphics API may not support 3D textures at run time. Support is indicated
4781 by the QRhi::ThreeDimensionalTextures feature.
4782
4783 \value TextureRectangleGL The texture should use the GL_TEXTURE_RECTANGLE
4784 target with OpenGL. This flag is ignored with other graphics APIs. Just
4785 like ExternalOES, this flag is useful when working with platform APIs where
4786 native OpenGL texture objects received from the platform are wrapped in a
4787 QRhiTexture, and the platform can only provide textures for a non-2D
4788 texture target.
4789
4790 \value TextureArray The texture is a texture array, i.e. a single texture
4791 object that is a homogeneous array of 2D textures. Texture arrays are
4792 created with QRhi::newTextureArray(). The underlying graphics API may not
4793 support texture array objects at run time. Support is indicated by the
4794 QRhi::TextureArrays feature. When rendering into, or uploading data to a
4795 texture array, the \c layer specified in the render target's color
4796 attachment or the upload description selects a single element in the array.
4797
4798 \value OneDimensional The texture is a 1D texture. Such textures can be
4799 created by passing a 0 height and depth to QRhi::newTexture(). Note that
4800 there can be limitations on one dimensional textures depending on the
4801 underlying graphics API. For example, rendering to them or using them with
4802 mipmap-based filtering may be unsupported. This is indicated by the
4803 QRhi::OneDimensionalTextures and QRhi::OneDimensionalTextureMipmaps
4804 feature flags.
4805
4806 \value UsedAsShadingRateMap
4807 */
4808
4809/*!
4810 \enum QRhiTexture::Format
4811
4812 Specifies the texture format. See also QRhi::isTextureFormatSupported() and
4813 note that flags() can modify the format when QRhiTexture::sRGB is set.
4814
4815 \value UnknownFormat Not a valid format. This cannot be passed to setFormat().
4816
4817 \value RGBA8 Four components, unsigned normalized 8-bit per component. Always supported. (32 bits total)
4818
4819 \value BGRA8 Four components, unsigned normalized 8-bit per component. (32 bits total)
4820
4821 \value R8 One component, unsigned normalized 8-bit. (8 bits total)
4822
4823 \value RG8 Two components, unsigned normalized 8-bit. (16 bits total)
4824
4825 \value R16 One component, unsigned normalized 16-bit. (16 bits total)
4826
4827 \value RG16 Two components, unsigned normalized 16-bit. (32 bits total)
4828
4829 \value RED_OR_ALPHA8 Either same as R8, or is a similar format with the component swizzled to alpha,
4830 depending on \l{QRhi::RedOrAlpha8IsRed}{RedOrAlpha8IsRed}. (8 bits total)
4831
4832 \value RGBA16F Four components, 16-bit float. (64 bits total)
4833
4834 \value RGBA32F Four components, 32-bit float. (128 bits total)
4835
4836 \value R16F One component, 16-bit float. (16 bits total)
4837
4838 \value R32F One component, 32-bit float. (32 bits total)
4839
4840 \value RGB10A2 Four components, unsigned normalized 10 bit R, G, and B,
4841 2-bit alpha. This is a packed format so native endianness applies. Note
4842 that there is no BGR10A2. This is because RGB10A2 maps to
4843 DXGI_FORMAT_R10G10B10A2_UNORM with D3D, MTLPixelFormatRGB10A2Unorm with
4844 Metal, VK_FORMAT_A2B10G10R10_UNORM_PACK32 with Vulkan, and
4845 GL_RGB10_A2/GL_RGB/GL_UNSIGNED_INT_2_10_10_10_REV on OpenGL (ES). This is
4846 the only universally supported RGB30 option. The corresponding QImage
4847 formats are QImage::Format_BGR30 and QImage::Format_A2BGR30_Premultiplied.
4848 (32 bits total)
4849
4850 \value D16 16-bit depth (normalized unsigned integer)
4851
4852 \value D24 24-bit depth (normalized unsigned integer)
4853
4854 \value D24S8 24-bit depth (normalized unsigned integer), 8 bit stencil
4855
4856 \value D32F 32-bit depth (32-bit float)
4857
4858 \value [since 6.9] D32FS8 32-bit depth (32-bit float), 8 bits of stencil, 24 bits unused
4859 (64 bits total)
4860
4861 \value BC1
4862 \value BC2
4863 \value BC3
4864 \value BC4
4865 \value BC5
4866 \value BC6H
4867 \value BC7
4868
4869 \value ETC2_RGB8
4870 \value ETC2_RGB8A1
4871 \value ETC2_RGBA8
4872
4873 \value ASTC_4x4
4874 \value ASTC_5x4
4875 \value ASTC_5x5
4876 \value ASTC_6x5
4877 \value ASTC_6x6
4878 \value ASTC_8x5
4879 \value ASTC_8x6
4880 \value ASTC_8x8
4881 \value ASTC_10x5
4882 \value ASTC_10x6
4883 \value ASTC_10x8
4884 \value ASTC_10x10
4885 \value ASTC_12x10
4886 \value ASTC_12x12
4887
4888 \value [since 6.9] R8UI One component, unsigned 8-bit. (8 bits total)
4889 \value [since 6.9] R32UI One component, unsigned 32-bit. (32 bits total)
4890 \value [since 6.9] RG32UI Two components, unsigned 32-bit. (64 bits total)
4891 \value [since 6.9] RGBA32UI Four components, unsigned 32-bit. (128 bits total)
4892
4893 \value [since 6.10] R8SI One component, signed 8-bit. (8 bits total)
4894 \value [since 6.10] R32SI One component, signed 32-bit. (32 bits total)
4895 \value [since 6.10] RG32SI Two components, signed 32-bit. (64 bits total)
4896 \value [since 6.10] RGBA32SI Four components, signed 32-bit. (128 bits total)
4897 */
4898
4899// When adding new texture formats, update void tst_QRhi::textureFormats_data().
4900
4901/*!
4902 \struct QRhiTexture::NativeTexture
4903 \inmodule QtGuiPrivate
4904 \inheaderfile rhi/qrhi.h
4905 \brief Contains information about the underlying native resources of a texture.
4906 */
4907
4908/*!
4909 \variable QRhiTexture::NativeTexture::object
4910 \brief 64-bit integer containing the native object handle.
4911
4912 With OpenGL, the native handle is a GLuint value, so \c object can then be
4913 cast to a GLuint. With Vulkan, the native handle is a VkImage, so \c object
4914 can be cast to a VkImage. With Direct3D 11 and Metal \c object contains a
4915 ID3D11Texture2D or MTLTexture pointer, respectively. With Direct3D 12
4916 \c object contains a ID3D12Resource pointer.
4917 */
4918
4919/*!
4920 \variable QRhiTexture::NativeTexture::layout
4921 \brief Specifies the current image layout for APIs like Vulkan.
4922
4923 For Vulkan, \c layout contains a \c VkImageLayout value. For Direct3D 12, a
4924 \c D3D12_RESOURCE_STATES value. For other APIs, this is undefined and should be
4925 ignored.
4926 */
4927
4928/*!
4929 \internal
4930 */
4931QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
4932 int arraySize_, int sampleCount_, Flags flags_)
4933 : QRhiResource(rhi),
4934 m_format(format_), m_pixelSize(pixelSize_), m_depth(depth_),
4935 m_arraySize(arraySize_), m_sampleCount(sampleCount_), m_flags(flags_)
4936{
4937}
4938
4939/*!
4940 \return the resource type.
4941 */
4942QRhiResource::Type QRhiTexture::resourceType() const
4943{
4944 return Texture;
4945}
4946
4947/*!
4948 \fn virtual bool QRhiTexture::create() = 0
4949
4950 Creates the corresponding native graphics resources. If there are already
4951 resources present due to an earlier create() with no corresponding
4952 destroy(), then destroy() is called implicitly first.
4953
4954 \return \c true when successful, \c false when a graphics operation failed.
4955 Regardless of the return value, calling destroy() is always safe.
4956 */
4957
4958/*!
4959 \return the underlying native resources for this texture. The returned value
4960 will be empty if exposing the underlying native resources is not supported by
4961 the backend.
4962
4963 \sa createFrom()
4964 */
4965QRhiTexture::NativeTexture QRhiTexture::nativeTexture()
4966{
4967 return {};
4968}
4969
4970/*!
4971 Similar to create(), except that no new native textures are created.
4972 Instead, the native texture resources specified by \a src is used.
4973
4974 This allows importing an existing native texture object (which must belong
4975 to the same device or sharing context, depending on the graphics API) from
4976 an external graphics engine.
4977
4978 \return true if the specified existing native texture object has been
4979 successfully wrapped as a non-owning QRhiTexture.
4980
4981 \note format(), pixelSize(), sampleCount(), and flags() must still be set
4982 correctly. Passing incorrect sizes and other values to QRhi::newTexture()
4983 and then following it with a createFrom() expecting that the native texture
4984 object alone is sufficient to deduce such values is \b wrong and will lead
4985 to problems.
4986
4987 \note QRhiTexture does not take ownership of the texture object. destroy()
4988 does not free the object or any associated memory.
4989
4990 The opposite of this operation, exposing a QRhiTexture-created native
4991 texture object to a foreign engine, is possible via nativeTexture().
4992
4993 \note When importing a 3D texture, or a texture array object, or, with
4994 OpenGL ES, an external texture, it is then especially important to set the
4995 corresponding flags (ThreeDimensional, TextureArray, ExternalOES) via
4996 setFlags() before calling this function.
4997*/
4998bool QRhiTexture::createFrom(QRhiTexture::NativeTexture src)
4999{
5000 Q_UNUSED(src);
5001 return false;
5002}
5003
5004/*!
5005 With some graphics APIs, such as Vulkan, integrating custom rendering code
5006 that uses the graphics API directly needs special care when it comes to
5007 image layouts. This function allows communicating the expected \a layout the
5008 image backing the QRhiTexture is in after the native rendering commands.
5009
5010 For example, consider rendering into a QRhiTexture's VkImage directly with
5011 Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and
5012 QRhiCommandBuffer::endExternal(), followed by using the image for texture
5013 sampling in a QRhi-based render pass. To avoid potentially incorrect image
5014 layout transitions, this function can be used to indicate what the image
5015 layout will be once the commands recorded in said code block complete.
5016
5017 Calling this function makes sense only after
5018 QRhiCommandBuffer::endExternal() and before a subsequent
5019 QRhiCommandBuffer::beginPass().
5020
5021 This function has no effect with QRhi backends where the underlying
5022 graphics API does not expose a concept of image layouts.
5023
5024 \note With Vulkan \a layout is a \c VkImageLayout. With Direct 3D 12 \a
5025 layout is a value composed of the bits from \c D3D12_RESOURCE_STATES.
5026 */
5027void QRhiTexture::setNativeLayout(int layout)
5028{
5029 Q_UNUSED(layout);
5030}
5031
5032/*!
5033 \fn QRhiTexture::Format QRhiTexture::format() const
5034 \return the texture format.
5035 */
5036
5037/*!
5038 \fn void QRhiTexture::setFormat(QRhiTexture::Format fmt)
5039
5040 Sets the requested texture format to \a fmt.
5041
5042 \note The value set is only taken into account upon the next call to
5043 create(), i.e. when the underlying graphics resource are (re)created.
5044 Setting a new value is futile otherwise and must be avoided since it can
5045 lead to inconsistent state.
5046 */
5047
5048/*!
5049 \fn QSize QRhiTexture::pixelSize() const
5050 \return the size in pixels.
5051 */
5052
5053/*!
5054 \fn void QRhiTexture::setPixelSize(const QSize &sz)
5055
5056 Sets the texture size, specified in pixels, to \a sz.
5057
5058 \note The value set is only taken into account upon the next call to
5059 create(), i.e. when the underlying graphics resource are (re)created.
5060 Setting a new value is futile otherwise and must be avoided since it can
5061 lead to inconsistent state. The same applies to all other setters as well.
5062 */
5063
5064/*!
5065 \fn int QRhiTexture::depth() const
5066 \return the depth for 3D textures.
5067 */
5068
5069/*!
5070 \fn void QRhiTexture::setDepth(int depth)
5071 Sets the \a depth for a 3D texture.
5072 */
5073
5074/*!
5075 \fn int QRhiTexture::arraySize() const
5076 \return the texture array size.
5077 */
5078
5079/*!
5080 \fn void QRhiTexture::setArraySize(int arraySize)
5081 Sets the texture \a arraySize.
5082 */
5083
5084/*!
5085 \fn int QRhiTexture::arrayRangeStart() const
5086
5087 \return the first array layer when setArrayRange() was called.
5088
5089 \sa setArrayRange()
5090 */
5091
5092/*!
5093 \fn int QRhiTexture::arrayRangeLength() const
5094
5095 \return the exposed array range size when setArrayRange() was called.
5096
5097 \sa setArrayRange()
5098*/
5099
5100/*!
5101 \fn void QRhiTexture::setArrayRange(int startIndex, int count)
5102
5103 Normally all array layers are exposed and it is up to the shader to select
5104 the layer via the third coordinate passed to the \c{texture()} GLSL
5105 function when sampling the \c sampler2DArray. When QRhi::TextureArrayRange
5106 is reported as supported, calling setArrayRange() before create() or
5107 createFrom() requests selecting only the specified range, \a count elements
5108 starting from \a startIndex. The shader logic can then be written with this
5109 in mind.
5110
5111 \sa QRhi::TextureArrayRange
5112 */
5113
5114/*!
5115 \fn Flags QRhiTexture::flags() const
5116 \return the texture flags.
5117 */
5118
5119/*!
5120 \fn void QRhiTexture::setFlags(Flags f)
5121 Sets the texture flags to \a f.
5122 */
5123
5124/*!
5125 \fn int QRhiTexture::sampleCount() const
5126 \return the sample count. 1 means no multisample antialiasing.
5127 */
5128
5129/*!
5130 \fn void QRhiTexture::setSampleCount(int s)
5131 Sets the sample count to \a s.
5132 */
5133
5134/*!
5135 \struct QRhiTexture::ViewFormat
5136 \inmodule QtGuiPrivate
5137 \inheaderfile rhi/qrhi.h
5138 \since 6.8
5139 \brief Specifies the view format for reading or writing from or to the texture.
5140
5141 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5142 for details.
5143 */
5144
5145/*!
5146 \variable QRhiTexture::ViewFormat::format
5147 */
5148
5149/*!
5150 \variable QRhiTexture::ViewFormat::srgb
5151 */
5152
5153/*!
5154 \fn QRhiTexture::ViewFormat QRhiTexture::readViewFormat() const
5155 \since 6.8
5156 \return the view format used when sampling the texture. When not called, the view
5157 format is assumed to be the same as format().
5158 */
5159
5160/*!
5161 \fn void QRhiTexture::setReadViewFormat(const ViewFormat &fmt)
5162 \since 6.8
5163
5164 Sets the shader resource view format (or the format of the view used for
5165 sampling the texture) to \a fmt. By default the same format (and sRGB-ness)
5166 is used as the texture itself, and in most cases this function does not need
5167 to be called.
5168
5169 This setting is only taken into account when the \l QRhi::TextureViewFormat
5170 feature is reported as supported.
5171
5172 \note This functionality is provided to allow "casting" between
5173 non-sRGB and sRGB in order to get the shader reads perform, or not perform,
5174 the implicit sRGB conversions. Other types of casting may or may not be
5175 functional.
5176 */
5177
5178/*!
5179 \fn QRhiTexture::ViewFormat QRhiTexture::writeViewFormat() const
5180 \since 6.8
5181 \return the view format used when writing to the texture and when using it
5182 with image load/store. When not called, the view format is assumed to be the
5183 same as format().
5184 */
5185
5186/*!
5187 \fn void QRhiTexture::setWriteViewFormat(const ViewFormat &fmt)
5188 \since 6.8
5189
5190 Sets the render target view format to \a fmt. By default the same format
5191 (and sRGB-ness) is used as the texture itself, and in most cases this
5192 function does not need to be called.
5193
5194 One common use case for providing a write view format is working with
5195 externally provided textures that, outside of our control, use an sRGB
5196 format with 3D APIs such as Vulkan or Direct 3D, but the rendering engine is
5197 already prepared to handle linearization and conversion to sRGB at the end
5198 of its shading pipeline. In this case what is wanted when rendering into
5199 such a texture is a render target view (e.g. VkImageView) that has the same,
5200 but non-sRGB format. (if e.g. from an OpenXR implementation one gets a
5201 VK_FORMAT_R8G8B8A8_SRGB texture, it is likely that rendering into it should
5202 be done using a VK_FORMAT_R8G8B8A8_UNORM view, if that is what the rendering
5203 engine's pipeline requires; in this example one would call this function
5204 with a ViewFormat that has a format of QRhiTexture::RGBA8 and \c srgb set to
5205 \c false).
5206
5207 This setting is only taken into account when the \l QRhi::TextureViewFormat
5208 feature is reported as supported.
5209
5210 \note This functionality is provided to allow "casting" between
5211 non-sRGB and sRGB in order to get the shader write not perform, or perform,
5212 the implicit sRGB conversions. Other types of casting may or may not be
5213 functional.
5214 */
5215
5216/*!
5217 \class QRhiSampler
5218 \inmodule QtGuiPrivate
5219 \inheaderfile rhi/qrhi.h
5220 \since 6.6
5221 \brief Sampler resource.
5222
5223 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5224 for details.
5225 */
5226
5227/*!
5228 \enum QRhiSampler::Filter
5229 Specifies the minification, magnification, or mipmap filtering
5230
5231 \value None Applicable only for mipmapMode(), indicates no mipmaps to be used
5232 \value Nearest
5233 \value Linear
5234 */
5235
5236/*!
5237 \enum QRhiSampler::AddressMode
5238 Specifies the addressing mode
5239
5240 \value Repeat
5241 \value ClampToEdge
5242 \value Mirror
5243 */
5244
5245/*!
5246 \enum QRhiSampler::CompareOp
5247 Specifies the texture comparison function.
5248
5249 \value Never (default)
5250 \value Less
5251 \value Equal
5252 \value LessOrEqual
5253 \value Greater
5254 \value NotEqual
5255 \value GreaterOrEqual
5256 \value Always
5257 */
5258
5259/*!
5260 \internal
5261 */
5262QRhiSampler::QRhiSampler(QRhiImplementation *rhi,
5263 Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
5264 AddressMode u_, AddressMode v_, AddressMode w_)
5265 : QRhiResource(rhi),
5266 m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_),
5267 m_addressU(u_), m_addressV(v_), m_addressW(w_),
5268 m_compareOp(QRhiSampler::Never)
5269{
5270}
5271
5272/*!
5273 \return the resource type.
5274 */
5275QRhiResource::Type QRhiSampler::resourceType() const
5276{
5277 return Sampler;
5278}
5279
5280/*!
5281 \fn QRhiSampler::Filter QRhiSampler::magFilter() const
5282 \return the magnification filter mode.
5283 */
5284
5285/*!
5286 \fn void QRhiSampler::setMagFilter(Filter f)
5287 Sets the magnification filter mode to \a f.
5288 */
5289
5290/*!
5291 \fn QRhiSampler::Filter QRhiSampler::minFilter() const
5292 \return the minification filter mode.
5293 */
5294
5295/*!
5296 \fn void QRhiSampler::setMinFilter(Filter f)
5297 Sets the minification filter mode to \a f.
5298 */
5299
5300/*!
5301 \fn QRhiSampler::Filter QRhiSampler::mipmapMode() const
5302 \return the mipmap filter mode.
5303 */
5304
5305/*!
5306 \fn void QRhiSampler::setMipmapMode(Filter f)
5307
5308 Sets the mipmap filter mode to \a f.
5309
5310 Leave this set to None when the texture has no mip levels, or when the mip
5311 levels are not to be taken into account.
5312 */
5313
5314/*!
5315 \fn QRhiSampler::AddressMode QRhiSampler::addressU() const
5316 \return the horizontal wrap mode.
5317 */
5318
5319/*!
5320 \fn void QRhiSampler::setAddressU(AddressMode mode)
5321 Sets the horizontal wrap \a mode.
5322 */
5323
5324/*!
5325 \fn QRhiSampler::AddressMode QRhiSampler::addressV() const
5326 \return the vertical wrap mode.
5327 */
5328
5329/*!
5330 \fn void QRhiSampler::setAddressV(AddressMode mode)
5331 Sets the vertical wrap \a mode.
5332 */
5333
5334/*!
5335 \fn QRhiSampler::AddressMode QRhiSampler::addressW() const
5336 \return the depth wrap mode.
5337 */
5338
5339/*!
5340 \fn void QRhiSampler::setAddressW(AddressMode mode)
5341 Sets the depth wrap \a mode.
5342 */
5343
5344/*!
5345 \fn QRhiSampler::CompareOp QRhiSampler::textureCompareOp() const
5346 \return the texture comparison function.
5347 */
5348
5349/*!
5350 \fn void QRhiSampler::setTextureCompareOp(CompareOp op)
5351 Sets the texture comparison function \a op.
5352 */
5353
5354/*!
5355 \class QRhiShadingRateMap
5356 \inmodule QtGuiPrivate
5357 \inheaderfile rhi/qrhi.h
5358 \since 6.9
5359 \brief An object that wraps a texture or another kind of native 3D API object.
5360
5361 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5362 for details.
5363
5364 For an introduction to Variable Rate Shading (VRS), see
5365 \l{https://learn.microsoft.com/en-us/windows/win32/direct3d12/vrs}. Qt
5366 supports a subset of the VRS features offered by Direct 3D 12 and Vulkan. In
5367 addition, Metal's somewhat different mechanism is supported by making it
5368 possible to set up a QRhiShadingRateMap with an existing
5369 MTLRasterizationRateMap object.
5370 */
5371
5372/*!
5373 \struct QRhiShadingRateMap::NativeShadingRateMap
5374 \inmodule QtGuiPrivate
5375 \inheaderfile rhi/qrhi.h
5376 \since 6.9
5377 \brief Wraps a native shading rate map.
5378
5379 An example is MTLRasterizationRateMap with Metal. Other 3D APIs that use
5380 textures for image-based VRS do not use this struct since those can function
5381 via the QRhiTexture-based overload of QRhiShadingRateMap::createFrom().
5382 */
5383
5384/*!
5385 \variable QRhiShadingRateMap::NativeShadingRateMap::object
5386 \brief 64-bit integer containing the native object handle.
5387
5388 Used with QRhiShadingRateMap::createFrom(). For example, with Metal,
5389 \c object is expected to be an id<MTLRasterizationRateMap>.
5390 */
5391
5392/*!
5393 \internal
5394 */
5395QRhiShadingRateMap::QRhiShadingRateMap(QRhiImplementation *rhi)
5396 : QRhiResource(rhi)
5397{
5398}
5399
5400/*!
5401 \return the resource type.
5402 */
5403QRhiResource::Type QRhiShadingRateMap::resourceType() const
5404{
5405 return ShadingRateMap;
5406}
5407
5408/*!
5409 Sets up the shading rate map to use a native 3D API shading rate object
5410 \a src.
5411
5412 \return \c true when successful, \c false when not supported.
5413
5414 \note This is functional only when the QRhi::VariableRateShadingMap feature
5415 is reported as supported, while QRhi::VariableRateShadingMapWithTexture
5416 feature is not. Currently this is true for Metal, assuming variable rate
5417 shading is supported by the GPU.
5418
5419 \note With Metal, the \c object field of \a src is expected to contain an
5420 id<MTLRasterizationRateMap>. Qt passes the MTLRasterizationRateMap on to the
5421 MTLRenderPassDescriptor, and, because Metal then interprets viewports and
5422 scissor rectangles in the map's screen space coordinate system, sizes the
5423 default scissor and converts viewports and scissors specified via
5424 QRhiCommandBuffer accordingly. The size of that coordinate system is
5425 reported by logicalSize(). Anything else, such as scaling when sampling
5426 the rendered result, is up to the application (or the XR compositor).
5427 */
5428bool QRhiShadingRateMap::createFrom(NativeShadingRateMap src)
5429{
5430 Q_UNUSED(src);
5431 return false;
5432}
5433
5434/*!
5435 Sets up the shading rate map to use the texture \a src as the
5436 image containing the per-tile shading rates.
5437
5438 \return \c true when successful, \c false when not supported.
5439
5440 The QRhiShadingRateMap does not take ownership of \a src.
5441
5442 \note This is functional only when the
5443 QRhi::VariableRateShadingMapWithTexture feature is reported as supported. In
5444 practice may be supported on Vulkan and Direct 3D 12 when using modern
5445 graphics cards. It will never be supported on OpenGL or Metal, for example.
5446
5447 \note \a src must have a format of QRhiTexture::R8UI.
5448
5449 \note \a src must have a width of \c{ceil(render_target_pixel_width /
5450 (float)tile_width)} and a height of \c{ceil(render_target_pixel_height /
5451 (float)tile_height)}. It is up to the application to ensure the size of the
5452 texture is as expected, using the above formula, at all times. The tile size
5453 can be queried via \l QRhi::resourceLimit() and
5454 QRhi::ShadingRateImageTileSize.
5455
5456 Each byte (texel) in the texture corresponds to the shading rate value for
5457 one tile. 0 indicates 1x1, while a value of 10 indicates 4x4. See
5458 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shading_rate}{D3D12_SHADING_RATE}
5459 for other possible values.
5460 */
5461bool QRhiShadingRateMap::createFrom(QRhiTexture *src)
5462{
5463 Q_UNUSED(src);
5464 return false;
5465}
5466
5467/*!
5468 \since 6.13
5469
5470 \return the size of the logical coordinate space the shading rate map
5471 defines, or an invalid QSize when the map does not define one.
5472
5473 Some implementations, Metal in particular, describe a shading rate map in
5474 terms of a logical (screen space) size that is mapped onto the physical
5475 pixels of the render target. When such a map is attached to a render
5476 target, viewports and scissor rectangles are interpreted in the logical
5477 coordinate system, and the logical size is typically larger than
5478 QRhiRenderTarget::pixelSize(). Applications that derive viewports,
5479 scissors, or projection setup from the render target size should use this
5480 size instead whenever it is valid.
5481
5482 For implementations where the shading rate map is a tile image covering
5483 the render target, such as Vulkan and Direct 3D 12, there is no separate
5484 logical coordinate space, and an invalid QSize is returned. The render
5485 target's pixel size applies as usual in that case.
5486
5487 \sa QRhiRenderTarget::pixelSize()
5488 */
5489QSize QRhiShadingRateMap::logicalSize() const
5490{
5491 return QSize();
5492}
5493
5494/*!
5495 \class QRhiRenderPassDescriptor
5496 \inmodule QtGuiPrivate
5497 \inheaderfile rhi/qrhi.h
5498 \since 6.6
5499 \brief Render pass resource.
5500
5501 A render pass, if such a concept exists in the underlying graphics API, is
5502 a collection of attachments (color, depth, stencil) and describes how those
5503 attachments are used.
5504
5505 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5506 for details.
5507 */
5508
5509/*!
5510 \internal
5511 */
5512QRhiRenderPassDescriptor::QRhiRenderPassDescriptor(QRhiImplementation *rhi)
5513 : QRhiResource(rhi)
5514{
5515}
5516
5517/*!
5518 \return the resource type.
5519 */
5520QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
5521{
5522 return RenderPassDescriptor;
5523}
5524
5525/*!
5526 \fn virtual bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const = 0
5527
5528 \return true if the \a other QRhiRenderPassDescriptor is compatible with
5529 this one, meaning \c this and \a other can be used interchangeably in
5530 QRhiGraphicsPipeline::setRenderPassDescriptor().
5531
5532 The concept of the compatibility of renderpass descriptors is similar to
5533 the \l{QRhiShaderResourceBindings::isLayoutCompatible}{layout
5534 compatibility} of QRhiShaderResourceBindings instances. They allow better
5535 reuse of QRhiGraphicsPipeline instances: for example, a
5536 QRhiGraphicsPipeline instance cache is expected to use these functions to
5537 look for a matching pipeline, instead of just comparing pointers, thus
5538 allowing a different QRhiRenderPassDescriptor and
5539 QRhiShaderResourceBindings to be used in combination with the pipeline, as
5540 long as they are compatible.
5541
5542 The exact details of compatibility depend on the underlying graphics API.
5543 Two renderpass descriptors
5544 \l{QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()}{created}
5545 from the same QRhiTextureRenderTarget are always compatible.
5546
5547 Similarly to QRhiShaderResourceBindings, compatibility can also be tested
5548 without having two existing objects available. Extracting the opaque blob by
5549 calling serializedFormat() allows testing for compatibility by comparing the
5550 returned vector to another QRhiRenderPassDescriptor's
5551 serializedFormat(). This has benefits in certain situations, because it
5552 allows testing the compatibility of a QRhiRenderPassDescriptor with a
5553 QRhiGraphicsPipeline even when the QRhiRenderPassDescriptor the pipeline was
5554 originally built with is no longer available (but the data returned from its
5555 serializedFormat() still is).
5556
5557 \sa newCompatibleRenderPassDescriptor(), serializedFormat()
5558 */
5559
5560/*!
5561 \fn virtual QRhiRenderPassDescriptor *QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor() const = 0
5562
5563 \return a new QRhiRenderPassDescriptor that is
5564 \l{isCompatible()}{compatible} with this one.
5565
5566 This function allows cloning a QRhiRenderPassDescriptor. The returned
5567 object is ready to be used, and the ownership is transferred to the caller.
5568 Cloning a QRhiRenderPassDescriptor object can become useful in situations
5569 where the object is stored in data structures related to graphics pipelines
5570 (in order to allow creating new pipelines which in turn requires a
5571 renderpass descriptor object), and the lifetime of the renderpass
5572 descriptor created from a render target may be shorter than the pipelines.
5573 (for example, because the engine manages and destroys renderpasses together
5574 with the textures and render targets it was created from) In such a
5575 situation, it can be beneficial to store a cloned version in the data
5576 structures, and thus transferring ownership as well.
5577
5578 \sa isCompatible()
5579 */
5580
5581/*!
5582 \fn virtual QVector<quint32> QRhiRenderPassDescriptor::serializedFormat() const = 0
5583
5584 \return a vector of integers containing an opaque blob describing the data
5585 relevant for \l{isCompatible()}{compatibility}.
5586
5587 Given two QRhiRenderPassDescriptor objects \c rp1 and \c rp2, if the data
5588 returned from this function is identical, then \c{rp1->isCompatible(rp2)},
5589 and vice versa hold true as well.
5590
5591 \note The returned data is meant to be used for storing in memory and
5592 comparisons during the lifetime of the QRhi the object belongs to. It is not
5593 meant for storing on disk, reusing between processes, or using with multiple
5594 QRhi instances with potentially different backends.
5595
5596 \note Calling this function is expected to be a cheap operation since the
5597 backends are not supposed to calculate the data in this function, but rather
5598 return an already calculated series of data.
5599
5600 When creating reusable components as part of a library, where graphics
5601 pipelines are created and maintained while targeting a QRhiRenderTarget (be
5602 it a swapchain or a texture) managed by the client of the library, the
5603 components must be able to deal with a changing QRhiRenderPassDescriptor.
5604 For example, because the render target changes and so invalidates the
5605 previously QRhiRenderPassDescriptor (with regards to the new render target
5606 at least) due to having a potentially different color format and attachments
5607 now. Or because \l{QRhiShadingRateMap}{variable rate shading} is taken into
5608 use dynamically. A simple pattern that helps dealing with this is performing
5609 the following check on every frame, to recognize the case when the pipeline
5610 needs to be associated with a new QRhiRenderPassDescriptor, because
5611 something is different about the render target now, compared to earlier
5612 frames:
5613
5614 \code
5615 QRhiRenderPassDescriptor *rp = m_renderTarget->renderPassDescriptor();
5616 if (m_pipeline && rp->serializedFormat() != m_renderPassFormat) {
5617 m_pipeline->setRenderPassDescriptor(rp);
5618 m_renderPassFormat = rp->serializedFormat();
5619 m_pipeline->create();
5620 }
5621 // remember to store m_renderPassFormat also when creating m_pipeline the first time
5622 \endcode
5623
5624 \sa isCompatible()
5625 */
5626
5627/*!
5628 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
5629 QRhiVulkanRenderPassNativeHandles. The returned value is \nullptr when exposing
5630 the underlying native resources is not supported by the backend.
5631
5632 \sa QRhiVulkanRenderPassNativeHandles
5633 */
5634const QRhiNativeHandles *QRhiRenderPassDescriptor::nativeHandles()
5635{
5636 return nullptr;
5637}
5638
5639/*!
5640 \class QRhiRenderTarget
5641 \inmodule QtGuiPrivate
5642 \inheaderfile rhi/qrhi.h
5643 \since 6.6
5644 \brief Represents an onscreen (swapchain) or offscreen (texture) render target.
5645
5646 Applications do not create an instance of this class directly. Rather, it
5647 is the subclass QRhiTextureRenderTarget that is instantiable by clients of
5648 the API via \l{QRhi::newTextureRenderTarget()}{newTextureRenderTarget()}.
5649 The other subclass is QRhiSwapChainRenderTarget, which is the type
5650 QRhiSwapChain returns when calling
5651 \l{QRhiSwapChain::currentFrameRenderTarget()}{currentFrameRenderTarget()}.
5652
5653 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5654 for details.
5655
5656 \sa QRhiSwapChainRenderTarget, QRhiTextureRenderTarget
5657 */
5658
5659/*!
5660 \internal
5661 */
5662QRhiRenderTarget::QRhiRenderTarget(QRhiImplementation *rhi)
5663 : QRhiResource(rhi)
5664{
5665}
5666
5667/*!
5668 \fn virtual QSize QRhiRenderTarget::pixelSize() const = 0
5669
5670 \return the size in pixels.
5671
5672 Valid only after create() has been called successfully. Until then the
5673 result is a default-constructed QSize.
5674
5675 With QRhiTextureRenderTarget the returned size is the size of the
5676 associated attachments at the time of create(), in practice the size of the
5677 first color attachment, or the depth/stencil buffer if there are no color
5678 attachments. If the associated textures or renderbuffers are resized and
5679 rebuilt afterwards, then pixelSize() performs an implicit call to create()
5680 in order to rebuild the underlying data structures. This implicit check is
5681 similar to what QRhiCommandBuffer::beginPass() does, and ensures that the
5682 returned size is always up-to-date.
5683 */
5684
5685/*!
5686 \fn virtual float QRhiRenderTarget::devicePixelRatio() const = 0
5687
5688 \return the device pixel ratio. For QRhiTextureRenderTarget this is always
5689 1. For targets retrieved from a QRhiSwapChain the value reflects the
5690 \l{QWindow::devicePixelRatio()}{device pixel ratio} of the targeted
5691 QWindow.
5692 */
5693
5694/*!
5695 \fn virtual int QRhiRenderTarget::sampleCount() const = 0
5696
5697 \return the sample count or 1 if multisample antialiasing is not relevant for
5698 this render target.
5699 */
5700
5701/*!
5702 \fn QRhiRenderPassDescriptor *QRhiRenderTarget::renderPassDescriptor() const
5703
5704 \return the associated QRhiRenderPassDescriptor.
5705 */
5706
5707/*!
5708 \fn void QRhiRenderTarget::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
5709
5710 Sets the QRhiRenderPassDescriptor \a desc for use with this render target.
5711 */
5712
5713/*!
5714 \internal
5715 */
5716QRhiSwapChainRenderTarget::QRhiSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain_)
5717 : QRhiRenderTarget(rhi),
5718 m_swapchain(swapchain_)
5719{
5720}
5721
5722/*!
5723 \class QRhiSwapChainRenderTarget
5724 \inmodule QtGuiPrivate
5725 \inheaderfile rhi/qrhi.h
5726 \since 6.6
5727 \brief Swapchain render target resource.
5728
5729 When targeting the color buffers of a swapchain, active render target is a
5730 QRhiSwapChainRenderTarget. This is what
5731 QRhiSwapChain::currentFrameRenderTarget() returns.
5732
5733 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5734 for details.
5735
5736 \sa QRhiSwapChain
5737 */
5738
5739/*!
5740 \return the resource type.
5741 */
5742QRhiResource::Type QRhiSwapChainRenderTarget::resourceType() const
5743{
5744 return SwapChainRenderTarget;
5745}
5746
5747/*!
5748 \fn QRhiSwapChain *QRhiSwapChainRenderTarget::swapChain() const
5749
5750 \return the swapchain object.
5751 */
5752
5753/*!
5754 \class QRhiTextureRenderTarget
5755 \inmodule QtGuiPrivate
5756 \inheaderfile rhi/qrhi.h
5757 \since 6.6
5758 \brief Texture render target resource.
5759
5760 A texture render target allows rendering into one or more textures,
5761 optionally with a depth texture or depth/stencil renderbuffer.
5762
5763 For multisample rendering the common approach is to use a renderbuffer as
5764 the color attachment and set the non-multisample destination texture as the
5765 \c{resolve texture}. For more information, read the detailed description of
5766 the \l QRhiColorAttachment class.
5767
5768 \note Textures used in combination with QRhiTextureRenderTarget must be
5769 created with the QRhiTexture::RenderTarget flag.
5770
5771 The simplest example of creating a render target with a texture as its
5772 single color attachment:
5773
5774 \code
5775 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
5776 texture->create();
5777 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture });
5778 rp = rt->newCompatibleRenderPassDescriptor();
5779 rt->setRenderPassDescriptor(rp);
5780 rt->create();
5781 // rt can now be used with beginPass()
5782 \endcode
5783
5784 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5785 for details.
5786 */
5787
5788/*!
5789 \enum QRhiTextureRenderTarget::Flag
5790
5791 Flag values describing the load/store behavior for the render target. The
5792 load/store behavior may be baked into native resources under the hood,
5793 depending on the backend, and therefore it needs to be known upfront and
5794 cannot be changed without rebuilding (and so releasing and creating new
5795 native resources).
5796
5797 \value PreserveColorContents Indicates that the contents of the color
5798 attachments is to be loaded when starting a render pass, instead of
5799 clearing. This is potentially more expensive, especially on mobile (tiled)
5800 GPUs, but allows preserving the existing contents between passes. When doing
5801 multisample rendering with a resolve texture set, setting this flag also
5802 requests the multisample color data to be stored (written out) to the
5803 multisample texture or render buffer. (for non-multisample rendering the
5804 color data is always stored, but for MSAA storing the multisample data
5805 decreases efficiency for certain GPU architectures, hence defaulting to not
5806 writing it out) Note however that this is non-portable: in some cases there
5807 is no intermediate multisample texture on the graphics API level, e.g. when
5808 using OpenGL ES's \c{GL_EXT_multisampled_render_to_texture} as it is all
5809 implicit, handled by the OpenGL ES implementation. In that case,
5810 PreserveColorContents will likely have no effect. Therefore, avoid relying
5811 on this flag when using multisample rendering and the color attachment is
5812 using a multisample QRhiTexture (not QRhiRenderBuffer).
5813
5814 \value PreserveDepthStencilContents Indicates that the contents of the
5815 depth texture is to be loaded when starting a render pass, instead
5816 clearing. Only applicable when a texture is used as the depth buffer
5817 (QRhiTextureRenderTargetDescription::depthTexture() is set) because
5818 depth/stencil renderbuffers may not have any physical backing and data may
5819 not be written out in the first place.
5820
5821 \value DoNotStoreDepthStencilContents Indicates that the contents of the
5822 depth texture does not need to be written out. Relevant only when a
5823 QRhiTexture, not QRhiRenderBuffer, is used as the depth-stencil buffer,
5824 because for QRhiRenderBuffer this is implicit. When a depthResolveTexture is
5825 set, the flag is not relevant, because the behavior is then as if the flag
5826 was set. This enum value is introduced in Qt 6.8.
5827 */
5828
5829/*!
5830 \internal
5831 */
5832QRhiTextureRenderTarget::QRhiTextureRenderTarget(QRhiImplementation *rhi,
5833 const QRhiTextureRenderTargetDescription &desc_,
5834 Flags flags_)
5835 : QRhiRenderTarget(rhi),
5836 m_desc(desc_),
5837 m_flags(flags_)
5838{
5839}
5840
5841/*!
5842 \return the resource type.
5843 */
5844QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
5845{
5846 return TextureRenderTarget;
5847}
5848
5849/*!
5850 \fn virtual QRhiRenderPassDescriptor *QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() = 0
5851
5852 \return a new QRhiRenderPassDescriptor that is compatible with this render
5853 target.
5854
5855 The returned value is used in two ways: it can be passed to
5856 setRenderPassDescriptor() and
5857 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
5858 describes the attachments (color, depth/stencil) and the load/store
5859 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
5860 be used in combination with a render target that has a
5861 \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
5862 QRhiRenderPassDescriptor set.
5863
5864 Two QRhiTextureRenderTarget instances can share the same render pass
5865 descriptor as long as they have the same number and type of attachments.
5866 The associated QRhiTexture or QRhiRenderBuffer instances are not part of
5867 the render pass descriptor so those can differ in the two
5868 QRhiTextureRenderTarget instances.
5869
5870 \note resources, such as QRhiTexture instances, referenced in description()
5871 must already have create() called on them.
5872
5873 \sa create()
5874 */
5875
5876/*!
5877 \fn virtual bool QRhiTextureRenderTarget::create() = 0
5878
5879 Creates the corresponding native graphics resources. If there are already
5880 resources present due to an earlier create() with no corresponding
5881 destroy(), then destroy() is called implicitly first.
5882
5883 \note renderPassDescriptor() must be set before calling create(). To obtain
5884 a QRhiRenderPassDescriptor compatible with the render target, call
5885 newCompatibleRenderPassDescriptor() before create() but after setting all
5886 other parameters, such as description() and flags(). To save resources,
5887 reuse the same QRhiRenderPassDescriptor with multiple
5888 QRhiTextureRenderTarget instances, whenever possible. Sharing the same
5889 render pass descriptor is only possible when the render targets have the
5890 same number and type of attachments (the actual textures can differ) and
5891 the same flags.
5892
5893 \note resources, such as QRhiTexture instances, referenced in description()
5894 must already have create() called on them.
5895
5896 \return \c true when successful, \c false when a graphics operation failed.
5897 Regardless of the return value, calling destroy() is always safe.
5898 */
5899
5900/*!
5901 \fn QRhiTextureRenderTargetDescription QRhiTextureRenderTarget::description() const
5902 \return the render target description.
5903 */
5904
5905/*!
5906 \fn void QRhiTextureRenderTarget::setDescription(const QRhiTextureRenderTargetDescription &desc)
5907 Sets the render target description \a desc.
5908 */
5909
5910/*!
5911 \fn QRhiTextureRenderTarget::Flags QRhiTextureRenderTarget::flags() const
5912 \return the currently set flags.
5913 */
5914
5915/*!
5916 \fn void QRhiTextureRenderTarget::setFlags(Flags f)
5917 Sets the flags to \a f.
5918 */
5919
5920/*!
5921 \class QRhiShaderResourceBindings
5922 \inmodule QtGuiPrivate
5923 \inheaderfile rhi/qrhi.h
5924 \since 6.6
5925 \brief Encapsulates resources for making buffer, texture, sampler resources visible to shaders.
5926
5927 A QRhiShaderResourceBindings is a collection of QRhiShaderResourceBinding
5928 objects, each of which describe a single binding.
5929
5930 Take a fragment shader with the following interface:
5931
5932 \badcode
5933 layout(std140, binding = 0) uniform buf {
5934 mat4 mvp;
5935 int flip;
5936 } ubuf;
5937
5938 layout(binding = 1) uniform sampler2D tex;
5939 \endcode
5940
5941 To make resources visible to the shader, the following
5942 QRhiShaderResourceBindings could be created and then passed to
5943 QRhiGraphicsPipeline::setShaderResourceBindings():
5944
5945 \code
5946 QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings();
5947 srb->setBindings({
5948 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf),
5949 QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler)
5950 });
5951 srb->create();
5952 // ...
5953 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
5954 // ...
5955 ps->setShaderResourceBindings(srb);
5956 ps->create();
5957 // ...
5958 cb->setGraphicsPipeline(ps);
5959 cb->setShaderResources(); // binds srb
5960 \endcode
5961
5962 This assumes that \c ubuf is a QRhiBuffer, \c texture is a QRhiTexture,
5963 while \a sampler is a QRhiSampler. The example also assumes that the
5964 uniform block is present in the vertex shader as well so the same buffer is
5965 made visible to the vertex stage too.
5966
5967 \section1 Advanced usage
5968
5969 Building on the above example, let's assume that a pass now needs to use
5970 the exact same pipeline and shaders with a different texture. Creating a
5971 whole separate QRhiGraphicsPipeline just for this would be an overkill.
5972 This is why QRhiCommandBuffer::setShaderResources() allows specifying a \a
5973 srb argument. As long as the layouts (so the number of bindings and the
5974 binding points) match between two QRhiShaderResourceBindings, they can both
5975 be used with the same pipeline, assuming the pipeline was created with one of
5976 them in the first place. See isLayoutCompatible() for more details.
5977
5978 \code
5979 QRhiShaderResourceBindings *srb2 = rhi->newShaderResourceBindings();
5980 // ...
5981 cb->setGraphicsPipeline(ps);
5982 cb->setShaderResources(srb2); // binds srb2
5983 \endcode
5984
5985 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5986 for details.
5987 */
5988
5989/*!
5990 \typedef QRhiShaderResourceBindingSet
5991 \relates QRhi
5992 \since 6.7
5993
5994 Synonym for QRhiShaderResourceBindings.
5995*/
5996
5997/*!
5998 \internal
5999 */
6000QRhiShaderResourceBindings::QRhiShaderResourceBindings(QRhiImplementation *rhi)
6001 : QRhiResource(rhi)
6002{
6003 m_layoutDesc.reserve(BINDING_PREALLOC * QRhiShaderResourceBinding::LAYOUT_DESC_ENTRIES_PER_BINDING);
6004}
6005
6006/*!
6007 \return the resource type.
6008 */
6009QRhiResource::Type QRhiShaderResourceBindings::resourceType() const
6010{
6011 return ShaderResourceBindings;
6012}
6013
6014/*!
6015 \return \c true if the layout is compatible with \a other. The layout does
6016 not include the actual resource (such as, buffer or texture) and related
6017 parameters (such as, offset or size). It does include the binding point,
6018 pipeline stage, and resource type, however. The number and order of the
6019 bindings must also match in order to be compatible.
6020
6021 When there is a QRhiGraphicsPipeline created with this
6022 QRhiShaderResourceBindings, and the function returns \c true, \a other can
6023 then safely be passed to QRhiCommandBuffer::setShaderResources(), and so
6024 be used with the pipeline in place of this QRhiShaderResourceBindings.
6025
6026 \note This function must only be called after a successful create(), because
6027 it relies on data generated during the baking of the underlying data
6028 structures. This way the function can implement a comparison approach that
6029 is more efficient than iterating through two binding lists and calling
6030 QRhiShaderResourceBinding::isLayoutCompatible() on each pair. This becomes
6031 relevant especially when this function is called at a high frequency.
6032
6033 \sa serializedLayoutDescription()
6034 */
6035bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBindings *other) const
6036{
6037 if (other == this)
6038 return true;
6039
6040 if (!other)
6041 return false;
6042
6043 // This can become a hot code path. Therefore we do not iterate and call
6044 // isLayoutCompatible() on m_bindings, but rather check a pre-calculated
6045 // hash code and then, if the hash matched, do a uint array comparison
6046 // (that's still more cache friendly).
6047
6048 return m_layoutDescHash == other->m_layoutDescHash
6049 && m_layoutDesc == other->m_layoutDesc;
6050}
6051
6052/*!
6053 \fn QVector<quint32> QRhiShaderResourceBindings::serializedLayoutDescription() const
6054
6055 \return a vector of integers containing an opaque blob describing the layout
6056 of the binding list, i.e. the data relevant for
6057 \l{isLayoutCompatible()}{layout compatibility tests}.
6058
6059 Given two objects \c srb1 and \c srb2, if the data returned from this
6060 function is identical, then \c{srb1->isLayoutCompatible(srb2)}, and vice
6061 versa hold true as well.
6062
6063 \note The returned data is meant to be used for storing in memory and
6064 comparisons during the lifetime of the QRhi the object belongs to. It is not
6065 meant for storing on disk, reusing between processes, or using with multiple
6066 QRhi instances with potentially different backends.
6067
6068 \sa isLayoutCompatible()
6069 */
6070
6071void QRhiImplementation::updateLayoutDesc(QRhiShaderResourceBindings *srb)
6072{
6073 srb->m_layoutDescHash = 0;
6074 srb->m_layoutDesc.clear();
6075 auto layoutDescAppender = std::back_inserter(srb->m_layoutDesc);
6076 for (const QRhiShaderResourceBinding &b : std::as_const(srb->m_bindings)) {
6077 const QRhiShaderResourceBinding::Data *d = &b.d;
6078 srb->m_layoutDescHash ^= uint(d->binding) ^ uint(d->stage) ^ uint(d->type())
6079 ^ uint(d->arraySize());
6080 layoutDescAppender = d->serialize(layoutDescAppender);
6081 }
6082}
6083
6084/*!
6085 \fn virtual bool QRhiShaderResourceBindings::create() = 0
6086
6087 Creates the corresponding resource binding set. Depending on the underlying
6088 graphics API, this may involve creating native graphics resources, and
6089 therefore it should not be assumed that this is a cheap operation.
6090
6091 If create() has been called before with no corresponding destroy(), then
6092 destroy() is called implicitly first.
6093
6094 \return \c true when successful, \c false when failed.
6095 Regardless of the return value, calling destroy() is always safe.
6096 */
6097
6098/*!
6099 \fn void QRhiShaderResourceBindings::setBindings(std::initializer_list<QRhiShaderResourceBinding> list)
6100 Sets the \a list of bindings.
6101 */
6102
6103/*!
6104 \fn template<typename InputIterator> void QRhiShaderResourceBindings::setBindings(InputIterator first, InputIterator last)
6105 Sets the list of bindings from the iterators \a first and \a last.
6106 */
6107
6108/*!
6109 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cbeginBindings() const
6110 \return a const iterator pointing to the first item in the binding list.
6111 */
6112
6113/*!
6114 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cendBindings() const
6115 \return a const iterator pointing just after the last item in the binding list.
6116 */
6117
6118/*!
6119 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::bindingAt(qsizetype index) const
6120 \return the binding at the specified \a index.
6121 */
6122
6123/*!
6124 \fn qsizetype QRhiShaderResourceBindings::bindingCount() const
6125 \return the number of bindings.
6126 */
6127
6128/*!
6129 \class QRhiShaderResourceBinding
6130 \inmodule QtGuiPrivate
6131 \inheaderfile rhi/qrhi.h
6132 \since 6.6
6133 \brief Describes the shader resource for a single binding point.
6134
6135 A QRhiShaderResourceBinding cannot be constructed directly. Instead, use the
6136 static functions such as uniformBuffer() or sampledTexture() to get an
6137 instance.
6138
6139 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
6140 for details.
6141 */
6142
6143/*!
6144 \enum QRhiShaderResourceBinding::Type
6145 Specifies type of the shader resource bound to a binding point
6146
6147 \value UniformBuffer Uniform buffer
6148
6149 \value SampledTexture Combined image sampler (a texture and sampler pair).
6150 Even when the shading language associated with the underlying 3D API has no
6151 support for this concept (e.g. D3D and HLSL), this is still supported
6152 because the shader translation layer takes care of the appropriate
6153 translation and remapping of binding points or shader registers.
6154
6155 \value Texture Texture (separate)
6156
6157 \value Sampler Sampler (separate)
6158
6159 \value ImageLoad Image load (with GLSL this maps to doing imageLoad() on a
6160 single level - and either one or all layers - of a texture exposed to the
6161 shader as an image object)
6162
6163 \value ImageStore Image store (with GLSL this maps to doing imageStore() or
6164 imageAtomic*() on a single level - and either one or all layers - of a
6165 texture exposed to the shader as an image object)
6166
6167 \value ImageLoadStore Image load and store
6168
6169 \value BufferLoad Storage buffer load (with GLSL this maps to reading from
6170 a shader storage buffer)
6171
6172 \value BufferStore Storage buffer store (with GLSL this maps to writing to
6173 a shader storage buffer)
6174
6175 \value BufferLoadStore Storage buffer load and store
6176 */
6177
6178/*!
6179 \enum QRhiShaderResourceBinding::StageFlag
6180 Flag values to indicate which stages the shader resource is visible in
6181
6182 \value VertexStage Vertex stage
6183 \value TessellationControlStage Tessellation control (hull shader) stage
6184 \value TessellationEvaluationStage Tessellation evaluation (domain shader) stage
6185 \value FragmentStage Fragment (pixel shader) stage
6186 \value ComputeStage Compute stage
6187 \value GeometryStage Geometry stage
6188 */
6189
6190/*!
6191 \return \c true if the layout is compatible with \a other. The layout does not
6192 include the actual resource (such as, buffer or texture) and related
6193 parameters (such as, offset or size).
6194
6195 For example, \c a and \c b below are not equal, but are compatible layout-wise:
6196
6197 \code
6198 auto a = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buffer);
6199 auto b = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, someOtherBuffer, 256);
6200 \endcode
6201 */
6202bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBinding &other) const
6203{
6204 // everything that goes into a VkDescriptorSetLayoutBinding must match
6205 return d.binding == other.d.binding
6206 && d.stage == other.d.stage
6207 && d.type() == other.d.type()
6208 && d.arraySize() == other.d.arraySize();
6209}
6210
6211template<QRhiShaderResourceBinding::Type T>
6212static auto &emplaceData(QRhiShaderResourceBinding::Data &d)
6213{
6214 // Not using the return value of emplace() because the standard library on
6215 // VxWorks lacks the LWG 2857 resolution, so emplace() returns void there.
6216 d.u.emplace<T>();
6217 return *std::get_if<T>(&d.u);
6218}
6219
6220/*!
6221 \return a shader resource binding for the given binding number, pipeline
6222 stages, and buffer specified by \a binding, \a stage, and \a buf.
6223
6224 \note When \a buf is not null, it must have been created with
6225 QRhiBuffer::UniformBuffer.
6226
6227 \note \a buf can be null. It is valid to create a
6228 QRhiShaderResourceBindings with unspecified resources, but such an object
6229 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6230 suitable for creating pipelines. Such a pipeline must then always be used
6231 together with another, layout compatible QRhiShaderResourceBindings with
6232 resources present passed to QRhiCommandBuffer::setShaderResources().
6233
6234 \note If the size of \a buf exceeds the limit reported for
6235 QRhi::MaxUniformBufferRange, unexpected errors may occur.
6236 */
6237QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
6238 int binding, StageFlags stage, QRhiBuffer *buf)
6239{
6240 QRhiShaderResourceBinding b;
6241 b.d.binding = binding;
6242 b.d.stage = stage;
6243 b.d.u.emplace<UniformBuffer>(Data::UniformBufferData{ buf, 0, 0, false });
6244 return b;
6245}
6246
6247/*!
6248 \return a shader resource binding for the given binding number, pipeline
6249 stages, and buffer specified by \a binding, \a stage, and \a buf. This
6250 overload binds a region only, as specified by \a offset and \a size.
6251
6252 \note It is up to the user to ensure the offset is aligned to
6253 QRhi::ubufAlignment().
6254
6255 \note \a size must be greater than 0.
6256
6257 \note When \a buf is not null, it must have been created with
6258 QRhiBuffer::UniformBuffer.
6259
6260 \note \a buf can be null. It is valid to create a
6261 QRhiShaderResourceBindings with unspecified resources, but such an object
6262 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6263 suitable for creating pipelines. Such a pipeline must then always be used
6264 together with another, layout compatible QRhiShaderResourceBindings with
6265 resources present passed to QRhiCommandBuffer::setShaderResources().
6266
6267 \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
6268 unexpected errors may occur.
6269 */
6270QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
6271 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6272{
6273 Q_ASSERT(size > 0);
6274 QRhiShaderResourceBinding b;
6275 b.d.binding = binding;
6276 b.d.stage = stage;
6277 b.d.u.emplace<UniformBuffer>(Data::UniformBufferData{ buf, offset, size, false });
6278 return b;
6279}
6280
6281/*!
6282 \return a shader resource binding for the given binding number, pipeline
6283 stages, and buffer specified by \a binding, \a stage, and \a buf. The
6284 uniform buffer is assumed to have dynamic offset. The dynamic offset can be
6285 specified in QRhiCommandBuffer::setShaderResources(), thus allowing using
6286 varying offset values without creating new bindings for the buffer. The
6287 size of the bound region is specified by \a size. Like with non-dynamic
6288 offsets, \c{offset + size} cannot exceed the size of \a buf.
6289
6290 \note When \a buf is not null, it must have been created with
6291 QRhiBuffer::UniformBuffer.
6292
6293 \note \a buf can be null. It is valid to create a
6294 QRhiShaderResourceBindings with unspecified resources, but such an object
6295 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6296 suitable for creating pipelines. Such a pipeline must then always be used
6297 together with another, layout compatible QRhiShaderResourceBindings with
6298 resources present passed to QRhiCommandBuffer::setShaderResources().
6299
6300 \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
6301 unexpected errors may occur.
6302 */
6303QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(
6304 int binding, StageFlags stage, QRhiBuffer *buf, quint32 size)
6305{
6306 Q_ASSERT(size > 0);
6307 QRhiShaderResourceBinding b;
6308 b.d.binding = binding;
6309 b.d.stage = stage;
6310 b.d.u.emplace<UniformBuffer>(Data::UniformBufferData{ buf, 0, size, true });
6311 return b;
6312}
6313
6314/*!
6315 \return a shader resource binding for the given binding number, pipeline
6316 stages, texture, and sampler specified by \a binding, \a stage, \a tex,
6317 \a sampler.
6318
6319 \note This function is equivalent to calling sampledTextures() with a
6320 \c count of 1.
6321
6322 \note \a tex and \a sampler can be null. It is valid to create a
6323 QRhiShaderResourceBindings with unspecified resources, but such an object
6324 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6325 suitable for creating pipelines. Such a pipeline must then always be used
6326 together with another, layout compatible QRhiShaderResourceBindings with
6327 resources present passed to QRhiCommandBuffer::setShaderResources().
6328
6329 \note A shader may not be able to consume more than 16 textures/samplers,
6330 depending on the underlying graphics API. This hard limit must be kept in
6331 mind in renderer design. This does not apply to texture arrays which
6332 consume a single binding point (shader register) and can contain 256-2048
6333 textures, depending on the underlying graphics API. Arrays of textures (see
6334 sampledTextures()) are however no different in this regard than using the
6335 same number of individual textures.
6336
6337 \sa sampledTextures()
6338 */
6339QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
6340 int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
6341{
6342 QRhiShaderResourceBinding b;
6343 b.d.binding = binding;
6344 b.d.stage = stage;
6345 emplaceData<SampledTexture>(b.d).texSamplers = { { tex, sampler } };
6346 return b;
6347}
6348
6349/*!
6350 \return a shader resource binding for the given binding number, pipeline
6351 stages, and the array of texture-sampler pairs specified by \a binding, \a
6352 stage, \a count, and \a texSamplers.
6353
6354 \note \a count must be at least 1. There is no fixed upper limit, but each
6355 element counts towards the per-stage texture and sampler limits of the
6356 underlying graphics API, summed over all bindings visible to a given
6357 stage. Portable applications should not use more than 16 samplers per
6358 stage in total.
6359
6360 \note When \a count is 1, this function is equivalent to sampledTexture().
6361
6362 This function is relevant when arrays of combined image samplers are
6363 involved. For example, in GLSL \c{layout(binding = 5) uniform sampler2D
6364 shadowMaps[8];} declares an array of combined image samplers. The
6365 application is then expected provide a QRhiShaderResourceBinding for
6366 binding point 5, set up by calling this function with \a count set to 8 and
6367 a valid texture and sampler for each element of the array.
6368
6369 \warning All elements of the array must be specified. With the above
6370 example, the only valid, portable approach is calling this function with a
6371 \a count of 8. Additionally, all QRhiTexture and QRhiSampler instances must
6372 be valid, meaning nullptr is not an accepted value. This is due to some of
6373 the underlying APIs, such as, Vulkan, that require a valid image and
6374 sampler object for each element in descriptor arrays. Applications are
6375 advised to provide "dummy" samplers and textures if some array elements are
6376 not relevant (due to not being accessed in the shader).
6377
6378 \note \a texSamplers can be null. It is valid to create a
6379 QRhiShaderResourceBindings with unspecified resources, but such an object
6380 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6381 suitable for creating pipelines. Such a pipeline must then always be used
6382 together with another, layout compatible QRhiShaderResourceBindings with
6383 resources present passed to QRhiCommandBuffer::setShaderResources().
6384
6385 \sa sampledTexture()
6386 */
6387QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTextures(
6388 int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers)
6389{
6390 Q_ASSERT(count >= 1);
6391 QRhiShaderResourceBinding b;
6392 b.d.binding = binding;
6393 b.d.stage = stage;
6394 auto &stex = emplaceData<SampledTexture>(b.d);
6395 stex.texSamplers.resize(count);
6396 for (int i = 0; i < count; ++i) {
6397 if (texSamplers)
6398 stex.texSamplers[i] = texSamplers[i];
6399 else
6400 stex.texSamplers[i] = { nullptr, nullptr };
6401 }
6402 return b;
6403}
6404
6405/*!
6406 \return a shader resource binding for the given binding number, pipeline
6407 stages, and texture specified by \a binding, \a stage, \a tex.
6408
6409 \note This function is equivalent to calling textures() with a
6410 \c count of 1.
6411
6412 \note \a tex can be null. It is valid to create a
6413 QRhiShaderResourceBindings with unspecified resources, but such an object
6414 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6415 suitable for creating pipelines. Such a pipeline must then always be used
6416 together with another, layout compatible QRhiShaderResourceBindings with
6417 resources present passed to QRhiCommandBuffer::setShaderResources().
6418
6419 This creates a binding for a separate texture (image) object, whereas
6420 sampledTexture() is suitable for combined image samplers. In
6421 Vulkan-compatible GLSL code separate textures are declared as \c texture2D
6422 as opposed to \c sampler2D: \c{layout(binding = 1) uniform texture2D tex;}
6423
6424 \note A shader may not be able to consume more than 16 textures, depending
6425 on the underlying graphics API. This hard limit must be kept in mind in
6426 renderer design. This does not apply to texture arrays which consume a
6427 single binding point (shader register) and can contain 256-2048 textures,
6428 depending on the underlying graphics API. Arrays of textures (see
6429 sampledTextures()) are however no different in this regard than using the
6430 same number of individual textures.
6431
6432 \sa textures(), sampler()
6433 */
6434QRhiShaderResourceBinding QRhiShaderResourceBinding::texture(int binding, StageFlags stage, QRhiTexture *tex)
6435{
6436 QRhiShaderResourceBinding b;
6437 b.d.binding = binding;
6438 b.d.stage = stage;
6439 emplaceData<Texture>(b.d).texSamplers = { { tex, nullptr } };
6440 return b;
6441}
6442
6443/*!
6444 \return a shader resource binding for the given binding number, pipeline
6445 stages, and the array of (separate) textures specified by \a binding, \a
6446 stage, \a count, and \a tex.
6447
6448 \note \a count must be at least 1. There is no fixed upper limit, but each
6449 element counts towards the per-stage texture limit of the underlying
6450 graphics API, summed over all bindings visible to a given stage. Portable
6451 applications should not use more than 16 textures per stage in total.
6452
6453 \note When \a count is 1, this function is equivalent to texture().
6454
6455 \warning All elements of the array must be specified.
6456
6457 \note \a tex can be null. It is valid to create a
6458 QRhiShaderResourceBindings with unspecified resources, but such an object
6459 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6460 suitable for creating pipelines. Such a pipeline must then always be used
6461 together with another, layout compatible QRhiShaderResourceBindings with
6462 resources present passed to QRhiCommandBuffer::setShaderResources().
6463
6464 \sa texture(), sampler()
6465 */
6466QRhiShaderResourceBinding QRhiShaderResourceBinding::textures(int binding, StageFlags stage, int count, QRhiTexture **tex)
6467{
6468 Q_ASSERT(count >= 1);
6469 QRhiShaderResourceBinding b;
6470 b.d.binding = binding;
6471 b.d.stage = stage;
6472 auto &stex = emplaceData<Texture>(b.d);
6473 stex.texSamplers.resize(count);
6474 for (int i = 0; i < count; ++i) {
6475 if (tex)
6476 stex.texSamplers[i] = { tex[i], nullptr };
6477 else
6478 stex.texSamplers[i] = { nullptr, nullptr };
6479 }
6480 return b;
6481}
6482
6483/*!
6484 \return a shader resource binding for the given binding number, pipeline
6485 stages, and sampler specified by \a binding, \a stage, \a sampler.
6486
6487 \note \a sampler can be null. It is valid to create a
6488 QRhiShaderResourceBindings with unspecified resources, but such an object
6489 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6490 suitable for creating pipelines. Such a pipeline must then always be used
6491 together with another, layout compatible QRhiShaderResourceBindings with
6492 resources present passed to QRhiCommandBuffer::setShaderResources().
6493
6494 Arrays of separate samplers are not supported.
6495
6496 This creates a binding for a separate sampler object, whereas
6497 sampledTexture() is suitable for combined image samplers. In
6498 Vulkan-compatible GLSL code separate samplers are declared as \c sampler
6499 as opposed to \c sampler2D: \c{layout(binding = 2) uniform sampler samp;}
6500
6501 With both a \c texture2D and \c sampler present, they can be used together
6502 to sample the texture: \c{fragColor = texture(sampler2D(tex, samp),
6503 texcoord);}.
6504
6505 \note A shader may not be able to consume more than 16 samplers, depending
6506 on the underlying graphics API. This hard limit must be kept in mind in
6507 renderer design.
6508
6509 \sa texture()
6510 */
6511QRhiShaderResourceBinding QRhiShaderResourceBinding::sampler(int binding, StageFlags stage, QRhiSampler *sampler)
6512{
6513 QRhiShaderResourceBinding b;
6514 b.d.binding = binding;
6515 b.d.stage = stage;
6516 emplaceData<Sampler>(b.d).texSamplers = { { nullptr, sampler } };
6517 return b;
6518}
6519
6520/*!
6521 \return a shader resource binding for a read-only storage image with the
6522 given \a binding number and pipeline \a stage. The image load operations
6523 will have access to all layers of the specified \a level. (so if the texture
6524 is a cubemap, the shader must use imageCube instead of image2D)
6525
6526 \note When \a tex is not null, it must have been created with
6527 QRhiTexture::UsedWithLoadStore.
6528
6529 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6530 with unspecified resources, but such an object cannot be used with
6531 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6532 pipelines. Such a pipeline must then always be used together with another,
6533 layout compatible QRhiShaderResourceBindings with resources present passed
6534 to QRhiCommandBuffer::setShaderResources().
6535
6536 \note Image load/store is only available within the compute and fragment stages.
6537 */
6538QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoad(
6539 int binding, StageFlags stage, QRhiTexture *tex, int level)
6540{
6541 QRhiShaderResourceBinding b;
6542 b.d.binding = binding;
6543 b.d.stage = stage;
6544 b.d.u.emplace<ImageLoad>(Data::StorageImageData{ tex, level });
6545 return b;
6546}
6547
6548/*!
6549 \return a shader resource binding for a write-only storage image with the
6550 given \a binding number and pipeline \a stage. The image store operations
6551 will have access to all layers of the specified \a level. (so if the texture
6552 is a cubemap, the shader must use imageCube instead of image2D)
6553
6554 \note When \a tex is not null, it must have been created with
6555 QRhiTexture::UsedWithLoadStore.
6556
6557 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6558 with unspecified resources, but such an object cannot be used with
6559 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6560 pipelines. Such a pipeline must then always be used together with another,
6561 layout compatible QRhiShaderResourceBindings with resources present passed
6562 to QRhiCommandBuffer::setShaderResources().
6563
6564 \note Image load/store is only available within the compute and fragment stages.
6565 */
6566QRhiShaderResourceBinding QRhiShaderResourceBinding::imageStore(
6567 int binding, StageFlags stage, QRhiTexture *tex, int level)
6568{
6569 QRhiShaderResourceBinding b;
6570 b.d.binding = binding;
6571 b.d.stage = stage;
6572 b.d.u.emplace<ImageStore>(Data::StorageImageData{ tex, level });
6573 return b;
6574}
6575
6576/*!
6577 \return a shader resource binding for a read/write storage image with the
6578 given \a binding number and pipeline \a stage. The image load/store operations
6579 will have access to all layers of the specified \a level. (so if the texture
6580 is a cubemap, the shader must use imageCube instead of image2D)
6581
6582 \note When \a tex is not null, it must have been created with
6583 QRhiTexture::UsedWithLoadStore.
6584
6585 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6586 with unspecified resources, but such an object cannot be used with
6587 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6588 pipelines. Such a pipeline must then always be used together with another,
6589 layout compatible QRhiShaderResourceBindings with resources present passed
6590 to QRhiCommandBuffer::setShaderResources().
6591
6592 \note Image load/store is only available within the compute and fragment stages.
6593 */
6594QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoadStore(
6595 int binding, StageFlags stage, QRhiTexture *tex, int level)
6596{
6597 QRhiShaderResourceBinding b;
6598 b.d.binding = binding;
6599 b.d.stage = stage;
6600 b.d.u.emplace<ImageLoadStore>(Data::StorageImageData{ tex, level });
6601 return b;
6602}
6603
6604/*!
6605 \return a shader resource binding for a read-only storage buffer with the
6606 given \a binding number and pipeline \a stage.
6607
6608 \note When \a buf is not null, must have been created with
6609 QRhiBuffer::StorageBuffer.
6610
6611 \note \a buf can be null. It is valid to create a
6612 QRhiShaderResourceBindings with unspecified resources, but such an object
6613 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6614 suitable for creating pipelines. Such a pipeline must then always be used
6615 together with another, layout compatible QRhiShaderResourceBindings with
6616 resources present passed to QRhiCommandBuffer::setShaderResources().
6617
6618 \note Buffer load/store is only guaranteed to be available within a compute
6619 pipeline. While some backends may support using these resources in a
6620 graphics pipeline as well, this is not universally supported, and even when
6621 it is, unexpected problems may arise when it comes to barriers and
6622 synchronization. Therefore, avoid using such resources with shaders other
6623 than compute.
6624 */
6625QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6626 int binding, StageFlags stage, QRhiBuffer *buf)
6627{
6628 QRhiShaderResourceBinding b;
6629 b.d.binding = binding;
6630 b.d.stage = stage;
6631 b.d.u.emplace<BufferLoad>(Data::StorageBufferData{ buf, 0, 0 });
6632 return b;
6633}
6634
6635/*!
6636 \return a shader resource binding for a read-only storage buffer with the
6637 given \a binding number and pipeline \a stage. This overload binds a region
6638 only, as specified by \a offset and \a size.
6639
6640 \note When \a buf is not null, must have been created with
6641 QRhiBuffer::StorageBuffer.
6642
6643 \note \a buf can be null. It is valid to create a
6644 QRhiShaderResourceBindings with unspecified resources, but such an object
6645 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6646 suitable for creating pipelines. Such a pipeline must then always be used
6647 together with another, layout compatible QRhiShaderResourceBindings with
6648 resources present passed to QRhiCommandBuffer::setShaderResources().
6649
6650 \note Buffer load/store is only guaranteed to be available within a compute
6651 pipeline. While some backends may support using these resources in a
6652 graphics pipeline as well, this is not universally supported, and even when
6653 it is, unexpected problems may arise when it comes to barriers and
6654 synchronization. Therefore, avoid using such resources with shaders other
6655 than compute.
6656 */
6657QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6658 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6659{
6660 Q_ASSERT(size > 0);
6661 QRhiShaderResourceBinding b;
6662 b.d.binding = binding;
6663 b.d.stage = stage;
6664 b.d.u.emplace<BufferLoad>(Data::StorageBufferData{ buf, offset, size });
6665 return b;
6666}
6667
6668/*!
6669 \return a shader resource binding for a write-only storage buffer with the
6670 given \a binding number and pipeline \a stage.
6671
6672 \note When \a buf is not null, must have been created with
6673 QRhiBuffer::StorageBuffer.
6674
6675 \note \a buf can be null. It is valid to create a
6676 QRhiShaderResourceBindings with unspecified resources, but such an object
6677 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6678 suitable for creating pipelines. Such a pipeline must then always be used
6679 together with another, layout compatible QRhiShaderResourceBindings with
6680 resources present passed to QRhiCommandBuffer::setShaderResources().
6681
6682 \note Buffer load/store is only guaranteed to be available within a compute
6683 pipeline. While some backends may support using these resources in a
6684 graphics pipeline as well, this is not universally supported, and even when
6685 it is, unexpected problems may arise when it comes to barriers and
6686 synchronization. Therefore, avoid using such resources with shaders other
6687 than compute.
6688 */
6689QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6690 int binding, StageFlags stage, QRhiBuffer *buf)
6691{
6692 QRhiShaderResourceBinding b;
6693 b.d.binding = binding;
6694 b.d.stage = stage;
6695 b.d.u.emplace<BufferStore>(Data::StorageBufferData{ buf, 0, 0 });
6696 return b;
6697}
6698
6699/*!
6700 \return a shader resource binding for a write-only storage buffer with the
6701 given \a binding number and pipeline \a stage. This overload binds a region
6702 only, as specified by \a offset and \a size.
6703
6704 \note When \a buf is not null, must have been created with
6705 QRhiBuffer::StorageBuffer.
6706
6707 \note \a buf can be null. It is valid to create a
6708 QRhiShaderResourceBindings with unspecified resources, but such an object
6709 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6710 suitable for creating pipelines. Such a pipeline must then always be used
6711 together with another, layout compatible QRhiShaderResourceBindings with
6712 resources present passed to QRhiCommandBuffer::setShaderResources().
6713
6714 \note Buffer load/store is only guaranteed to be available within a compute
6715 pipeline. While some backends may support using these resources in a
6716 graphics pipeline as well, this is not universally supported, and even when
6717 it is, unexpected problems may arise when it comes to barriers and
6718 synchronization. Therefore, avoid using such resources with shaders other
6719 than compute.
6720 */
6721QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6722 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6723{
6724 Q_ASSERT(size > 0);
6725 QRhiShaderResourceBinding b;
6726 b.d.binding = binding;
6727 b.d.stage = stage;
6728 b.d.u.emplace<BufferStore>(Data::StorageBufferData{ buf, offset, size });
6729 return b;
6730}
6731
6732/*!
6733 \return a shader resource binding for a read-write storage buffer with the
6734 given \a binding number and pipeline \a stage.
6735
6736 \note When \a buf is not null, must have been created with
6737 QRhiBuffer::StorageBuffer.
6738
6739 \note \a buf can be null. It is valid to create a
6740 QRhiShaderResourceBindings with unspecified resources, but such an object
6741 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6742 suitable for creating pipelines. Such a pipeline must then always be used
6743 together with another, layout compatible QRhiShaderResourceBindings with
6744 resources present passed to QRhiCommandBuffer::setShaderResources().
6745
6746 \note Buffer load/store is only guaranteed to be available within a compute
6747 pipeline. While some backends may support using these resources in a
6748 graphics pipeline as well, this is not universally supported, and even when
6749 it is, unexpected problems may arise when it comes to barriers and
6750 synchronization. Therefore, avoid using such resources with shaders other
6751 than compute.
6752 */
6753QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6754 int binding, StageFlags stage, QRhiBuffer *buf)
6755{
6756 QRhiShaderResourceBinding b;
6757 b.d.binding = binding;
6758 b.d.stage = stage;
6759 b.d.u.emplace<BufferLoadStore>(Data::StorageBufferData{ buf, 0, 0 });
6760 return b;
6761}
6762
6763/*!
6764 \return a shader resource binding for a read-write storage buffer with the
6765 given \a binding number and pipeline \a stage. This overload binds a region
6766 only, as specified by \a offset and \a size.
6767
6768 \note When \a buf is not null, must have been created with
6769 QRhiBuffer::StorageBuffer.
6770
6771 \note \a buf can be null. It is valid to create a
6772 QRhiShaderResourceBindings with unspecified resources, but such an object
6773 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6774 suitable for creating pipelines. Such a pipeline must then always be used
6775 together with another, layout compatible QRhiShaderResourceBindings with
6776 resources present passed to QRhiCommandBuffer::setShaderResources().
6777
6778 \note Buffer load/store is only guaranteed to be available within a compute
6779 pipeline. While some backends may support using these resources in a
6780 graphics pipeline as well, this is not universally supported, and even when
6781 it is, unexpected problems may arise when it comes to barriers and
6782 synchronization. Therefore, avoid using such resources with shaders other
6783 than compute.
6784 */
6785QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6786 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6787{
6788 Q_ASSERT(size > 0);
6789 QRhiShaderResourceBinding b;
6790 b.d.binding = binding;
6791 b.d.stage = stage;
6792 b.d.u.emplace<BufferLoadStore>(Data::StorageBufferData{ buf, offset, size });
6793 return b;
6794}
6795
6796/*!
6797 \return \c true if the contents of the two QRhiShaderResourceBinding
6798 objects \a a and \a b are equal. This includes the resources (buffer,
6799 texture) and related parameters (offset, size) as well. To only compare
6800 layouts (binding point, pipeline stage, resource type), use
6801 \l{QRhiShaderResourceBinding::isLayoutCompatible()}{isLayoutCompatible()}
6802 instead.
6803
6804 \relates QRhiShaderResourceBinding
6805 */
6806bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6807{
6808 const QRhiShaderResourceBinding::Data *da = QRhiImplementation::shaderResourceBindingData(a);
6809 const QRhiShaderResourceBinding::Data *db = QRhiImplementation::shaderResourceBindingData(b);
6810
6811 if (da == db)
6812 return true;
6813
6814
6815 if (da->binding != db->binding
6816 || da->stage != db->stage
6817 || da->type() != db->type())
6818 {
6819 return false;
6820 }
6821
6822 switch (da->type()) {
6823 case QRhiShaderResourceBinding::UniformBuffer:
6824 if (da->ubuf().buf != db->ubuf().buf
6825 || da->ubuf().offset != db->ubuf().offset
6826 || da->ubuf().maybeSize != db->ubuf().maybeSize)
6827 {
6828 return false;
6829 }
6830 break;
6831 case QRhiShaderResourceBinding::SampledTexture:
6832 if (da->stex().count() != db->stex().count())
6833 return false;
6834 for (int i = 0; i < da->stex().count(); ++i) {
6835 if (da->stex().texSamplers[i].tex != db->stex().texSamplers[i].tex
6836 || da->stex().texSamplers[i].sampler != db->stex().texSamplers[i].sampler)
6837 {
6838 return false;
6839 }
6840 }
6841 break;
6842 case QRhiShaderResourceBinding::Texture:
6843 if (da->stex().count() != db->stex().count())
6844 return false;
6845 for (int i = 0; i < da->stex().count(); ++i) {
6846 if (da->stex().texSamplers[i].tex != db->stex().texSamplers[i].tex)
6847 return false;
6848 }
6849 break;
6850 case QRhiShaderResourceBinding::Sampler:
6851 if (da->stex().texSamplers[0].sampler != db->stex().texSamplers[0].sampler)
6852 return false;
6853 break;
6854 case QRhiShaderResourceBinding::ImageLoad:
6855 case QRhiShaderResourceBinding::ImageStore:
6856 case QRhiShaderResourceBinding::ImageLoadStore:
6857 if (da->simage().tex != db->simage().tex
6858 || da->simage().level != db->simage().level)
6859 {
6860 return false;
6861 }
6862 break;
6863 case QRhiShaderResourceBinding::BufferLoad:
6864 case QRhiShaderResourceBinding::BufferStore:
6865 case QRhiShaderResourceBinding::BufferLoadStore:
6866 if (da->sbuf().buf != db->sbuf().buf
6867 || da->sbuf().offset != db->sbuf().offset
6868 || da->sbuf().maybeSize != db->sbuf().maybeSize)
6869 {
6870 return false;
6871 }
6872 break;
6873 default:
6874 Q_UNREACHABLE_RETURN(false);
6875 }
6876
6877 return true;
6878}
6879
6880/*!
6881 \return \c false if all the bindings in the two QRhiShaderResourceBinding
6882 objects \a a and \a b are equal; otherwise returns \c true.
6883
6884 \relates QRhiShaderResourceBinding
6885 */
6886bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6887{
6888 return !(a == b);
6889}
6890
6891/*!
6892 \fn size_t qHash(const QRhiShaderResourceBinding &key, size_t seed)
6893 \qhashold{QRhiShaderResourceBinding}
6894 */
6895size_t qHash(const QRhiShaderResourceBinding &b, size_t seed) noexcept
6896{
6897 const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6898 QtPrivate::QHashCombineWithSeed hash(seed);
6899 seed = hash(seed, d->binding);
6900 seed = hash(seed, d->stage);
6901 seed = hash(seed, d->type());
6902 switch (d->type()) {
6903 case QRhiShaderResourceBinding::UniformBuffer:
6904 seed = hash(seed, reinterpret_cast<quintptr>(d->ubuf().buf));
6905 break;
6906 case QRhiShaderResourceBinding::SampledTexture:
6907 seed = hash(seed, reinterpret_cast<quintptr>(d->stex().texSamplers[0].tex));
6908 seed = hash(seed, reinterpret_cast<quintptr>(d->stex().texSamplers[0].sampler));
6909 break;
6910 case QRhiShaderResourceBinding::Texture:
6911 seed = hash(seed, reinterpret_cast<quintptr>(d->stex().texSamplers[0].tex));
6912 break;
6913 case QRhiShaderResourceBinding::Sampler:
6914 seed = hash(seed, reinterpret_cast<quintptr>(d->stex().texSamplers[0].sampler));
6915 break;
6916 case QRhiShaderResourceBinding::ImageLoad:
6917 case QRhiShaderResourceBinding::ImageStore:
6918 case QRhiShaderResourceBinding::ImageLoadStore:
6919 seed = hash(seed, reinterpret_cast<quintptr>(d->simage().tex));
6920 break;
6921 case QRhiShaderResourceBinding::BufferLoad:
6922 case QRhiShaderResourceBinding::BufferStore:
6923 case QRhiShaderResourceBinding::BufferLoadStore:
6924 seed = hash(seed, reinterpret_cast<quintptr>(d->sbuf().buf));
6925 break;
6926 }
6927 return seed;
6928}
6929
6930#ifndef QT_NO_DEBUG_STREAM
6931QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
6932{
6933 QDebugStateSaver saver(dbg);
6934 const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6935 dbg.nospace() << "QRhiShaderResourceBinding("
6936 << "binding=" << d->binding
6937 << " stage=" << d->stage
6938 << " type=" << d->type();
6939 switch (d->type()) {
6940 case QRhiShaderResourceBinding::UniformBuffer:
6941 dbg.nospace() << " UniformBuffer("
6942 << "buffer=" << d->ubuf().buf
6943 << " offset=" << d->ubuf().offset
6944 << " maybeSize=" << d->ubuf().maybeSize
6945 << ')';
6946 break;
6947 case QRhiShaderResourceBinding::SampledTexture:
6948 dbg.nospace() << " SampledTextures("
6949 << "count=" << d->stex().count();
6950 for (int i = 0; i < d->stex().count(); ++i) {
6951 dbg.nospace() << " texture=" << d->stex().texSamplers[i].tex
6952 << " sampler=" << d->stex().texSamplers[i].sampler;
6953 }
6954 dbg.nospace() << ')';
6955 break;
6956 case QRhiShaderResourceBinding::Texture:
6957 dbg.nospace() << " Textures("
6958 << "count=" << d->stex().count();
6959 for (int i = 0; i < d->stex().count(); ++i)
6960 dbg.nospace() << " texture=" << d->stex().texSamplers[i].tex;
6961 dbg.nospace() << ')';
6962 break;
6963 case QRhiShaderResourceBinding::Sampler:
6964 dbg.nospace() << " Sampler("
6965 << " sampler=" << d->stex().texSamplers[0].sampler
6966 << ')';
6967 break;
6968 case QRhiShaderResourceBinding::ImageLoad:
6969 dbg.nospace() << " ImageLoad("
6970 << "texture=" << d->simage().tex
6971 << " level=" << d->simage().level
6972 << ')';
6973 break;
6974 case QRhiShaderResourceBinding::ImageStore:
6975 dbg.nospace() << " ImageStore("
6976 << "texture=" << d->simage().tex
6977 << " level=" << d->simage().level
6978 << ')';
6979 break;
6980 case QRhiShaderResourceBinding::ImageLoadStore:
6981 dbg.nospace() << " ImageLoadStore("
6982 << "texture=" << d->simage().tex
6983 << " level=" << d->simage().level
6984 << ')';
6985 break;
6986 case QRhiShaderResourceBinding::BufferLoad:
6987 dbg.nospace() << " BufferLoad("
6988 << "buffer=" << d->sbuf().buf
6989 << " offset=" << d->sbuf().offset
6990 << " maybeSize=" << d->sbuf().maybeSize
6991 << ')';
6992 break;
6993 case QRhiShaderResourceBinding::BufferStore:
6994 dbg.nospace() << " BufferStore("
6995 << "buffer=" << d->sbuf().buf
6996 << " offset=" << d->sbuf().offset
6997 << " maybeSize=" << d->sbuf().maybeSize
6998 << ')';
6999 break;
7000 case QRhiShaderResourceBinding::BufferLoadStore:
7001 dbg.nospace() << " BufferLoadStore("
7002 << "buffer=" << d->sbuf().buf
7003 << " offset=" << d->sbuf().offset
7004 << " maybeSize=" << d->sbuf().maybeSize
7005 << ')';
7006 break;
7007 default:
7008 dbg.nospace() << " UNKNOWN()";
7009 break;
7010 }
7011 dbg.nospace() << ')';
7012 return dbg;
7013}
7014#endif
7015
7016#ifndef QT_NO_DEBUG_STREAM
7017QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
7018{
7019 QDebugStateSaver saver(dbg);
7020 dbg.nospace() << "QRhiShaderResourceBindings("
7021 << srb.m_bindings
7022 << ')';
7023 return dbg;
7024}
7025#endif
7026
7027/*!
7028 \class QRhiGraphicsPipeline
7029 \inmodule QtGuiPrivate
7030 \inheaderfile rhi/qrhi.h
7031 \since 6.6
7032 \brief Graphics pipeline state resource.
7033
7034 Represents a graphics pipeline. What exactly this map to in the underlying
7035 native graphics API, varies. Where there is a concept of pipeline objects,
7036 for example with Vulkan, the QRhi backend will create such an object upon
7037 calling create(). Elsewhere, for example with OpenGL, the
7038 QRhiGraphicsPipeline may merely collect the various state, and create()'s
7039 main task is to set up the corresponding shader program, but deferring
7040 looking at any of the requested state to a later point.
7041
7042 As with all QRhiResource subclasses, the two-phased initialization pattern
7043 applies: setting any values via the setters, for example setDepthTest(), is
7044 only effective after calling create(). Avoid changing any values once the
7045 QRhiGraphicsPipeline has been initialized via create(). To change some
7046 state, set the new value and call create() again. However, that will
7047 effectively release all underlying native resources and create new ones. As
7048 a result, it may be a heavy, expensive operation. Rather, prefer creating
7049 multiple pipelines with the different states, and
7050 \l{QRhiCommandBuffer::setGraphicsPipeline()}{switch between them} when
7051 recording the render pass.
7052
7053 \note Setting the shader stages is mandatory. There must be at least one
7054 stage, and there must be a vertex stage.
7055
7056 \note Setting the shader resource bindings is mandatory. The referenced
7057 QRhiShaderResourceBindings must already have create() called on it by the
7058 time create() is called. Associating with a QRhiShaderResourceBindings that
7059 has no bindings is also valid, as long as no shader in any stage expects any
7060 resources. Using a QRhiShaderResourceBindings object that does not specify
7061 any actual resources (i.e., the buffers, textures, etc. for the binding
7062 points are set to \nullptr) is valid as well, as long as a
7063 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
7064 QRhiShaderResourceBindings, that specifies resources for all the bindings,
7065 is going to be set via
7066 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} when
7067 recording the render pass.
7068
7069 \note Setting the render pass descriptor is mandatory. To obtain a
7070 QRhiRenderPassDescriptor that can be passed to setRenderPassDescriptor(),
7071 use either QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() or
7072 QRhiSwapChain::newCompatibleRenderPassDescriptor().
7073
7074 \note Setting the vertex input layout is mandatory.
7075
7076 \note sampleCount() defaults to 1 and must match the sample count of the
7077 render target's color and depth stencil attachments.
7078
7079 \note The depth test, depth write, and stencil test are disabled by
7080 default. The face culling mode defaults to no culling.
7081
7082 \note stencilReadMask() and stencilWriteMask() apply to both faces. They
7083 both default to 0xFF.
7084
7085 \section1 Example usage
7086
7087 All settings of a graphics pipeline have defaults which might be suitable
7088 to many applications. Therefore a minimal example of creating a graphics
7089 pipeline could be the following. This assumes that the vertex shader takes
7090 a single \c{vec3 position} input at the input location 0. With the
7091 QRhiShaderResourceBindings and QRhiRenderPassDescriptor objects, plus the
7092 QShader collections for the vertex and fragment stages, a pipeline could be
7093 created like this:
7094
7095 \code
7096 QRhiShaderResourceBindings *srb;
7097 QRhiRenderPassDescriptor *rpDesc;
7098 QShader vs, fs;
7099 // ...
7100
7101 QRhiVertexInputLayout inputLayout;
7102 inputLayout.setBindings({ { 3 * sizeof(float) } });
7103 inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float3, 0 } });
7104
7105 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
7106 ps->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
7107 ps->setVertexInputLayout(inputLayout);
7108 ps->setShaderResourceBindings(srb);
7109 ps->setRenderPassDescriptor(rpDesc);
7110 if (!ps->create()) { error(); }
7111 \endcode
7112
7113 The above code creates a pipeline object that uses the defaults for many
7114 settings and states. For example, it will use a \l Triangles topology, no
7115 backface culling, blending is disabled but color write is enabled for all
7116 four channels, depth test/write are disabled, stencil operations are
7117 disabled.
7118
7119 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7120 for details.
7121
7122 \sa QRhiCommandBuffer, QRhi
7123 */
7124
7125/*!
7126 \enum QRhiGraphicsPipeline::Flag
7127
7128 Flag values for describing the dynamic state of the pipeline, and other
7129 options. The viewport is always dynamic.
7130
7131 \value UsesBlendConstants Indicates that a blend color constant will be set
7132 via QRhiCommandBuffer::setBlendConstants()
7133
7134 \value UsesStencilRef Indicates that a stencil reference value will be set
7135 via QRhiCommandBuffer::setStencilRef(). Pipelines without this flag use a
7136 stencil reference value of 0.
7137
7138 \value UsesScissor Indicates that a scissor rectangle will be set via
7139 QRhiCommandBuffer::setScissor()
7140
7141 \value CompileShadersWithDebugInfo Requests compiling shaders with debug
7142 information enabled. This is relevant only when runtime shader compilation
7143 from source code is involved, and only when the underlying infrastructure
7144 supports this. With concrete examples, this is not relevant with Vulkan and
7145 SPIR-V, because the GLSL-to-SPIR-V compilation does not happen at run
7146 time. On the other hand, consider Direct3D and HLSL, where there are
7147 multiple options: when the QShader packages ship with pre-compiled bytecode
7148 (\c DXBC), debug information is to be requested through the tool that
7149 generates the \c{.qsb} file, similarly to the case of Vulkan and
7150 SPIR-V. However, when having HLSL source code in the pre- or
7151 runtime-generated QShader packages, the first phase of compilation (HLSL
7152 source to intermediate format) happens at run time too, with this flag taken
7153 into account. Debug information is relevant in particular with tools like
7154 RenderDoc since it allows seeing the original source code when investigating
7155 the pipeline and when performing vertex or fragment shader debugging.
7156
7157 \value UsesShadingRate Indicates that a per-draw (per-pipeline) shading rate
7158 value will be set via QRhiCommandBuffer::setShadingRate(). Not specifying
7159 this flag and still calling setShadingRate() may lead to varying, unexpected
7160 results depending on the underlying graphics API.
7161
7162 \value [since 6.12] UsesIndirectDraws Indicates that this pipeline will be used with
7163 indirect draw calls (QRhiCommandBuffer::drawIndirect() or
7164 QRhiCommandBuffer::drawIndexedIndirect()). Setting this flag allows the
7165 Metal backend to use Indirect Command Buffers (ICB) for GPU-driven
7166 rendering, which significantly reduces CPU overhead for large draw counts.
7167 Not setting this flag when using indirect draws is still functional but may
7168 result in less optimal performance on Metal: QRhi::DrawIndirectMulti reports
7169 what the device can do, without knowing about individual pipelines, so a
7170 pipeline without this flag falls back to CPU-side looping even when that
7171 feature is reported as supported. The exception is
7172 QRhiCommandBuffer::drawIndirectCount() and
7173 QRhiCommandBuffer::drawIndexedIndirectCount(), for which the flag is
7174 mandatory on Metal because there is no non-ICB implementation of those. This
7175 flag has no effect on other backends.
7176 */
7177
7178/*!
7179 \enum QRhiGraphicsPipeline::Topology
7180 Specifies the primitive topology
7181
7182 \value Triangles (default)
7183 \value TriangleStrip
7184 \value TriangleFan (only available if QRhi::TriangleFanTopology is supported)
7185 \value Lines
7186 \value LineStrip
7187 \value Points
7188
7189 \value Patches (only available if QRhi::Tessellation is supported, and
7190 requires the tessellation stages to be present in the pipeline)
7191 */
7192
7193/*!
7194 \enum QRhiGraphicsPipeline::CullMode
7195 Specifies the culling mode
7196
7197 \value None No culling (default)
7198 \value Front Cull front faces
7199 \value Back Cull back faces
7200 */
7201
7202/*!
7203 \enum QRhiGraphicsPipeline::FrontFace
7204 Specifies the front face winding order
7205
7206 \value CCW Counter clockwise (default)
7207 \value CW Clockwise
7208 */
7209
7210/*!
7211 \enum QRhiGraphicsPipeline::ColorMaskComponent
7212 Flag values for specifying the color write mask
7213
7214 \value R
7215 \value G
7216 \value B
7217 \value A
7218 */
7219
7220/*!
7221 \enum QRhiGraphicsPipeline::BlendFactor
7222 Specifies the blend factor
7223
7224 \value Zero
7225 \value One
7226 \value SrcColor
7227 \value OneMinusSrcColor
7228 \value DstColor
7229 \value OneMinusDstColor
7230 \value SrcAlpha
7231 \value OneMinusSrcAlpha
7232 \value DstAlpha
7233 \value OneMinusDstAlpha
7234 \value ConstantColor
7235 \value OneMinusConstantColor
7236 \value ConstantAlpha
7237 \value OneMinusConstantAlpha
7238 \value SrcAlphaSaturate
7239 \value Src1Color
7240 \value OneMinusSrc1Color
7241 \value Src1Alpha
7242 \value OneMinusSrc1Alpha
7243 */
7244
7245/*!
7246 \enum QRhiGraphicsPipeline::BlendOp
7247 Specifies the blend operation
7248
7249 \value Add
7250 \value Subtract
7251 \value ReverseSubtract
7252 \value Min
7253 \value Max
7254 */
7255
7256/*!
7257 \enum QRhiGraphicsPipeline::CompareOp
7258 Specifies the depth or stencil comparison function
7259
7260 \value Never
7261 \value Less (default for depth)
7262 \value Equal
7263 \value LessOrEqual
7264 \value Greater
7265 \value NotEqual
7266 \value GreaterOrEqual
7267 \value Always (default for stencil)
7268 */
7269
7270/*!
7271 \enum QRhiGraphicsPipeline::StencilOp
7272 Specifies the stencil operation
7273
7274 \value StencilZero
7275 \value Keep (default)
7276 \value Replace
7277 \value IncrementAndClamp
7278 \value DecrementAndClamp
7279 \value Invert
7280 \value IncrementAndWrap
7281 \value DecrementAndWrap
7282 */
7283
7284/*!
7285 \enum QRhiGraphicsPipeline::PolygonMode
7286 \brief Specifies the polygon rasterization mode
7287
7288 Polygon Mode (Triangle Fill Mode in Metal, Fill Mode in D3D) specifies
7289 the fill mode used when rasterizing polygons. Polygons may be drawn as
7290 solids (Fill), or as a wire mesh (Line).
7291
7292 Support for non-fill polygon modes is optional and is indicated by the
7293 QRhi::NonFillPolygonMode feature. With OpenGL ES and some Vulkan
7294 implementations the feature will likely be reported as unsupported, which
7295 then means values other than Fill cannot be used.
7296
7297 \value Fill The interior of the polygon is filled (default)
7298 \value Line Boundary edges of the polygon are drawn as line segments.
7299 */
7300
7301/*!
7302 \struct QRhiGraphicsPipeline::TargetBlend
7303 \inmodule QtGuiPrivate
7304 \inheaderfile rhi/qrhi.h
7305 \since 6.6
7306 \brief Describes the blend state for one color attachment.
7307
7308 Defaults to color write enabled, blending disabled. The blend values are
7309 set up for pre-multiplied alpha (One, OneMinusSrcAlpha, One,
7310 OneMinusSrcAlpha) by default. This means that to get the alpha blending
7311 mode Qt Quick uses, it is enough to set the \c enable flag to true while
7312 leaving other values at their defaults.
7313
7314 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7315 for details.
7316 */
7317
7318/*!
7319 \variable QRhiGraphicsPipeline::TargetBlend::colorWrite
7320 */
7321
7322/*!
7323 \variable QRhiGraphicsPipeline::TargetBlend::enable
7324 */
7325
7326/*!
7327 \variable QRhiGraphicsPipeline::TargetBlend::srcColor
7328 */
7329
7330/*!
7331 \variable QRhiGraphicsPipeline::TargetBlend::dstColor
7332 */
7333
7334/*!
7335 \variable QRhiGraphicsPipeline::TargetBlend::opColor
7336 */
7337
7338/*!
7339 \variable QRhiGraphicsPipeline::TargetBlend::srcAlpha
7340 */
7341
7342/*!
7343 \variable QRhiGraphicsPipeline::TargetBlend::dstAlpha
7344 */
7345
7346/*!
7347 \variable QRhiGraphicsPipeline::TargetBlend::opAlpha
7348 */
7349
7350/*!
7351 \struct QRhiGraphicsPipeline::StencilOpState
7352 \inmodule QtGuiPrivate
7353 \inheaderfile rhi/qrhi.h
7354 \since 6.6
7355 \brief Describes the stencil operation state.
7356
7357 The default-constructed StencilOpState has the following set:
7358 \list
7359 \li failOp - \l Keep
7360 \li depthFailOp - \l Keep
7361 \li passOp - \l Keep
7362 \li compareOp \l Always
7363 \endlist
7364
7365 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7366 for details.
7367 */
7368
7369/*!
7370 \variable QRhiGraphicsPipeline::StencilOpState::failOp
7371 */
7372
7373/*!
7374 \variable QRhiGraphicsPipeline::StencilOpState::depthFailOp
7375 */
7376
7377/*!
7378 \variable QRhiGraphicsPipeline::StencilOpState::passOp
7379 */
7380
7381/*!
7382 \variable QRhiGraphicsPipeline::StencilOpState::compareOp
7383 */
7384
7385/*!
7386 \internal
7387 */
7388QRhiGraphicsPipeline::QRhiGraphicsPipeline(QRhiImplementation *rhi)
7389 : QRhiResource(rhi)
7390{
7391}
7392
7393/*!
7394 \return the resource type.
7395 */
7396QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
7397{
7398 return GraphicsPipeline;
7399}
7400
7401/*!
7402 \fn virtual bool QRhiGraphicsPipeline::create() = 0
7403
7404 Creates the corresponding native graphics resources. If there are already
7405 resources present due to an earlier create() with no corresponding
7406 destroy(), then destroy() is called implicitly first.
7407
7408 \return \c true when successful, \c false when a graphics operation failed.
7409 Regardless of the return value, calling destroy() is always safe.
7410
7411 \note This may be, depending on the underlying graphics API, an expensive
7412 operation, especially when shaders get compiled/optimized from source or
7413 from an intermediate bytecode format to the GPU's own instruction set.
7414 Where applicable, the QRhi backend automatically sets up the relevant
7415 non-persistent facilities to accelerate this, for example the Vulkan
7416 backend automatically creates a \c VkPipelineCache to improve data reuse
7417 during the lifetime of the application.
7418
7419 \note Drivers may also employ various persistent (disk-based) caching
7420 strategies for shader and pipeline data, which is hidden to and is outside
7421 of Qt's control. In some cases, depending on the graphics API and the QRhi
7422 backend, there are facilities within QRhi for manually managing such a
7423 cache, allowing the retrieval of a serializable blob that can then be
7424 reloaded in the future runs of the application to ensure faster pipeline
7425 creation times. See QRhi::pipelineCacheData() and
7426 QRhi::setPipelineCacheData() for details. Note also that when working with
7427 a QRhi instance managed by a higher level Qt framework, such as Qt Quick,
7428 it is possible that such disk-based caching is taken care of automatically,
7429 for example QQuickWindow uses a disk-based pipeline cache by default (which
7430 comes in addition to any driver-level caching).
7431 */
7432
7433/*!
7434 \fn QRhiGraphicsPipeline::Flags QRhiGraphicsPipeline::flags() const
7435 \return the currently set flags.
7436 */
7437
7438/*!
7439 \fn void QRhiGraphicsPipeline::setFlags(Flags f)
7440 Sets the flags \a f.
7441 */
7442
7443/*!
7444 \fn QRhiGraphicsPipeline::Topology QRhiGraphicsPipeline::topology() const
7445 \return the currently set primitive topology.
7446 */
7447
7448/*!
7449 \fn void QRhiGraphicsPipeline::setTopology(Topology t)
7450 Sets the primitive topology \a t.
7451 */
7452
7453/*!
7454 \fn QRhiGraphicsPipeline::CullMode QRhiGraphicsPipeline::cullMode() const
7455 \return the currently set face culling mode.
7456 */
7457
7458/*!
7459 \fn void QRhiGraphicsPipeline::setCullMode(CullMode mode)
7460 Sets the specified face culling \a mode.
7461 */
7462
7463/*!
7464 \fn QRhiGraphicsPipeline::FrontFace QRhiGraphicsPipeline::frontFace() const
7465 \return the currently set front face mode.
7466 */
7467
7468/*!
7469 \fn void QRhiGraphicsPipeline::setFrontFace(FrontFace f)
7470 Sets the front face mode \a f.
7471 */
7472
7473/*!
7474 \fn void QRhiGraphicsPipeline::setTargetBlends(std::initializer_list<TargetBlend> list)
7475
7476 Sets the \a list of render target blend settings. This is a list because
7477 when multiple render targets are used (i.e., a QRhiTextureRenderTarget with
7478 more than one QRhiColorAttachment), there needs to be a TargetBlend
7479 structure per render target (color attachment).
7480
7481 By default there is one default-constructed TargetBlend set.
7482
7483 \sa QRhi::MaxColorAttachments
7484 */
7485
7486/*!
7487 \fn template<typename InputIterator> void QRhiGraphicsPipeline::setTargetBlends(InputIterator first, InputIterator last)
7488 Sets the list of render target blend settings from the iterators \a first and \a last.
7489 */
7490
7491/*!
7492 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cbeginTargetBlends() const
7493 \return a const iterator pointing to the first item in the render target blend setting list.
7494 */
7495
7496/*!
7497 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cendTargetBlends() const
7498 \return a const iterator pointing just after the last item in the render target blend setting list.
7499 */
7500
7501/*!
7502 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::targetBlendAt(qsizetype index) const
7503 \return the render target blend setting at the specified \a index.
7504 */
7505
7506/*!
7507 \fn qsizetype QRhiGraphicsPipeline::targetBlendCount() const
7508 \return the number of render target blend settings.
7509 */
7510
7511/*!
7512 \fn bool QRhiGraphicsPipeline::hasDepthTest() const
7513 \return true if depth testing is enabled.
7514 */
7515
7516/*!
7517 \fn void QRhiGraphicsPipeline::setDepthTest(bool enable)
7518
7519 Enables or disables depth testing based on \a enable. Both depth test and
7520 the writing out of depth data are disabled by default.
7521
7522 \sa setDepthWrite()
7523 */
7524
7525/*!
7526 \fn bool QRhiGraphicsPipeline::hasDepthWrite() const
7527 \return true if depth write is enabled.
7528 */
7529
7530/*!
7531 \fn void QRhiGraphicsPipeline::setDepthWrite(bool enable)
7532
7533 Controls the writing out of depth data into the depth buffer based on
7534 \a enable. By default this is disabled. Depth write is typically enabled
7535 together with the depth test.
7536
7537 \note Enabling depth write without having depth testing enabled may not
7538 lead to the desired result, and should be avoided.
7539
7540 \sa setDepthTest()
7541 */
7542
7543/*!
7544 \fn bool QRhiGraphicsPipeline::hasDepthClamp() const
7545 \return true if depth clamp is enabled.
7546
7547 \since 6.11
7548 */
7549
7550/*!
7551 \fn void QRhiGraphicsPipeline::setDepthClamp(bool enable)
7552
7553 Enables depth clamping when \a enable is true. When depth clamping is
7554 enabled, primitives that would otherwise be clipped by the near or far
7555 clip plane are rasterized and their depth values are clamped to the
7556 depth range. When disabled (the default), such primitives are clipped.
7557
7558 \note This setting is ignored when the QRhi::DepthClamp feature is
7559 reported as unsupported.
7560
7561 \since 6.11
7562 */
7563
7564/*!
7565 \fn QRhiGraphicsPipeline::CompareOp QRhiGraphicsPipeline::depthOp() const
7566 \return the depth comparison function.
7567 */
7568
7569/*!
7570 \fn void QRhiGraphicsPipeline::setDepthOp(CompareOp op)
7571 Sets the depth comparison function \a op.
7572 */
7573
7574/*!
7575 \fn bool QRhiGraphicsPipeline::hasStencilTest() const
7576 \return true if stencil testing is enabled.
7577 */
7578
7579/*!
7580 \fn void QRhiGraphicsPipeline::setStencilTest(bool enable)
7581 Enables or disables stencil tests based on \a enable.
7582 By default this is disabled.
7583 */
7584
7585/*!
7586 \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilFront() const
7587 \return the current stencil test state for front faces.
7588 */
7589
7590/*!
7591 \fn void QRhiGraphicsPipeline::setStencilFront(const StencilOpState &state)
7592 Sets the stencil test \a state for front faces.
7593 */
7594
7595/*!
7596 \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilBack() const
7597 \return the current stencil test state for back faces.
7598 */
7599
7600/*!
7601 \fn void QRhiGraphicsPipeline::setStencilBack(const StencilOpState &state)
7602 Sets the stencil test \a state for back faces.
7603 */
7604
7605/*!
7606 \fn quint32 QRhiGraphicsPipeline::stencilReadMask() const
7607 \return the currrent stencil read mask.
7608 */
7609
7610/*!
7611 \fn void QRhiGraphicsPipeline::setStencilReadMask(quint32 mask)
7612 Sets the stencil read \a mask. The default value is 0xFF.
7613 */
7614
7615/*!
7616 \fn quint32 QRhiGraphicsPipeline::stencilWriteMask() const
7617 \return the current stencil write mask.
7618 */
7619
7620/*!
7621 \fn void QRhiGraphicsPipeline::setStencilWriteMask(quint32 mask)
7622 Sets the stencil write \a mask. The default value is 0xFF.
7623 */
7624
7625/*!
7626 \fn int QRhiGraphicsPipeline::sampleCount() const
7627 \return the currently set sample count. 1 means no multisample antialiasing.
7628 */
7629
7630/*!
7631 \fn void QRhiGraphicsPipeline::setSampleCount(int s)
7632
7633 Sets the sample count. Typical values for \a s are 1, 4, or 8. The pipeline
7634 must always be compatible with the render target, i.e. the sample counts
7635 must match.
7636
7637 \sa QRhi::supportedSampleCounts()
7638 */
7639
7640/*!
7641 \fn float QRhiGraphicsPipeline::lineWidth() const
7642 \return the currently set line width. The default is 1.0f.
7643 */
7644
7645/*!
7646 \fn void QRhiGraphicsPipeline::setLineWidth(float width)
7647
7648 Sets the line \a width. If the QRhi::WideLines feature is reported as
7649 unsupported at runtime, values other than 1.0f are ignored.
7650 */
7651
7652/*!
7653 \fn int QRhiGraphicsPipeline::depthBias() const
7654 \return the currently set depth bias.
7655 */
7656
7657/*!
7658 \fn void QRhiGraphicsPipeline::setDepthBias(int bias)
7659 Sets the depth \a bias. The default value is 0.
7660 */
7661
7662/*!
7663 \fn float QRhiGraphicsPipeline::slopeScaledDepthBias() const
7664 \return the currently set slope scaled depth bias.
7665 */
7666
7667/*!
7668 \fn void QRhiGraphicsPipeline::setSlopeScaledDepthBias(float bias)
7669 Sets the slope scaled depth \a bias. The default value is 0.
7670 */
7671
7672/*!
7673 \fn void QRhiGraphicsPipeline::setShaderStages(std::initializer_list<QRhiShaderStage> list)
7674 Sets the \a list of shader stages.
7675 */
7676
7677/*!
7678 \fn template<typename InputIterator> void QRhiGraphicsPipeline::setShaderStages(InputIterator first, InputIterator last)
7679 Sets the list of shader stages from the iterators \a first and \a last.
7680 */
7681
7682/*!
7683 \fn const QRhiShaderStage *QRhiGraphicsPipeline::cbeginShaderStages() const
7684 \return a const iterator pointing to the first item in the shader stage list.
7685 */
7686
7687/*!
7688 \fn const QRhiShaderStage *QRhiGraphicsPipeline::cendShaderStages() const
7689 \return a const iterator pointing just after the last item in the shader stage list.
7690 */
7691
7692/*!
7693 \fn const QRhiShaderStage *QRhiGraphicsPipeline::shaderStageAt(qsizetype index) const
7694 \return the shader stage at the specified \a index.
7695 */
7696
7697/*!
7698 \fn qsizetype QRhiGraphicsPipeline::shaderStageCount() const
7699 \return the number of shader stages in this pipeline.
7700 */
7701
7702/*!
7703 \fn QRhiVertexInputLayout QRhiGraphicsPipeline::vertexInputLayout() const
7704 \return the currently set vertex input layout specification.
7705 */
7706
7707/*!
7708 \fn void QRhiGraphicsPipeline::setVertexInputLayout(const QRhiVertexInputLayout &layout)
7709 Specifies the vertex input \a layout.
7710 */
7711
7712/*!
7713 \fn QRhiShaderResourceBindings *QRhiGraphicsPipeline::shaderResourceBindings() const
7714 \return the currently associated QRhiShaderResourceBindings object.
7715 */
7716
7717/*!
7718 \fn void QRhiGraphicsPipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
7719
7720 Associates with \a srb describing the resource binding layout and the
7721 resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional,
7722 because only the layout matters during pipeline creation. Therefore, the \a
7723 srb passed in here can leave the actual buffer or texture objects
7724 unspecified (\nullptr) as long as there is another,
7725 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
7726 QRhiShaderResourceBindings bound via
7727 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
7728 recording the draw calls.
7729 */
7730
7731/*!
7732 \fn QRhiRenderPassDescriptor *QRhiGraphicsPipeline::renderPassDescriptor() const
7733 \return the currently set QRhiRenderPassDescriptor.
7734 */
7735
7736/*!
7737 \fn void QRhiGraphicsPipeline::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
7738 Associates with the specified QRhiRenderPassDescriptor \a desc.
7739 */
7740
7741/*!
7742 \fn int QRhiGraphicsPipeline::patchControlPointCount() const
7743 \return the currently set patch control point count.
7744 */
7745
7746/*!
7747 \fn void QRhiGraphicsPipeline::setPatchControlPointCount(int count)
7748
7749 Sets the number of patch control points to \a count. The default value is
7750 3. This is used only when the topology is set to \l Patches.
7751 */
7752
7753/*!
7754 \fn QRhiGraphicsPipeline::PolygonMode QRhiGraphicsPipeline::polygonMode() const
7755 \return the polygon mode.
7756 */
7757
7758/*!
7759 \fn void QRhiGraphicsPipeline::setPolygonMode(PolygonMode mode)
7760 Sets the polygon \a mode. The default is Fill.
7761
7762 \sa QRhi::NonFillPolygonMode
7763 */
7764
7765/*!
7766 \fn int QRhiGraphicsPipeline::multiViewCount() const
7767 \return the view count. The default is 0, indicating no multiview rendering.
7768 \since 6.7
7769 */
7770
7771/*!
7772 \fn void QRhiGraphicsPipeline::setMultiViewCount(int count)
7773 Sets the view \a count for multiview rendering. The default is 0,
7774 indicating no multiview rendering.
7775 \a count must be 2 or larger to trigger multiview rendering.
7776
7777 Multiview is only available when the \l{QRhi::MultiView}{MultiView feature}
7778 is reported as supported. The render target must be a 2D texture array, and
7779 the color attachment for the render target must have the same \a count set.
7780
7781 See QRhiColorAttachment::setMultiViewCount() for further details on
7782 multiview rendering.
7783
7784 \since 6.7
7785 \sa QRhi::MultiView, QRhiColorAttachment::setMultiViewCount()
7786 */
7787
7788/*!
7789 \class QRhiSwapChain
7790 \inmodule QtGuiPrivate
7791 \inheaderfile rhi/qrhi.h
7792 \since 6.6
7793 \brief Swapchain resource.
7794
7795 A swapchain enables presenting rendering results to a surface. A swapchain
7796 is typically backed by a set of color buffers. Of these, one is displayed
7797 at a time.
7798
7799 Below is a typical pattern for creating and managing a swapchain and some
7800 associated resources in order to render onto a QWindow:
7801
7802 \code
7803 void init()
7804 {
7805 sc = rhi->newSwapChain();
7806 ds = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
7807 QSize(), // no need to set the size here due to UsedWithSwapChainOnly
7808 1,
7809 QRhiRenderBuffer::UsedWithSwapChainOnly);
7810 sc->setWindow(window);
7811 sc->setDepthStencil(ds);
7812 rp = sc->newCompatibleRenderPassDescriptor();
7813 sc->setRenderPassDescriptor(rp);
7814 resizeSwapChain();
7815 }
7816
7817 void resizeSwapChain()
7818 {
7819 hasSwapChain = sc->createOrResize();
7820 }
7821
7822 void render()
7823 {
7824 if (!hasSwapChain || notExposed)
7825 return;
7826
7827 if (sc->currentPixelSize() != sc->surfacePixelSize() || newlyExposed) {
7828 resizeSwapChain();
7829 if (!hasSwapChain)
7830 return;
7831 newlyExposed = false;
7832 }
7833
7834 rhi->beginFrame(sc);
7835 // ...
7836 rhi->endFrame(sc);
7837 }
7838 \endcode
7839
7840 Avoid relying on QWindow resize events to resize swapchains, especially
7841 considering that surface sizes may not always fully match the QWindow
7842 reported dimensions. The safe, cross-platform approach is to do the check
7843 via surfacePixelSize() whenever starting a new frame.
7844
7845 Releasing the swapchain must happen while the QWindow and the underlying
7846 native window is fully up and running. Building on the previous example:
7847
7848 \code
7849 void releaseSwapChain()
7850 {
7851 if (hasSwapChain) {
7852 sc->destroy();
7853 hasSwapChain = false;
7854 }
7855 }
7856
7857 // assuming Window is our QWindow subclass
7858 bool Window::event(QEvent *e)
7859 {
7860 switch (e->type()) {
7861 case QEvent::UpdateRequest: // for QWindow::requestUpdate()
7862 render();
7863 break;
7864 case QEvent::PlatformSurface:
7865 if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
7866 releaseSwapChain();
7867 break;
7868 default:
7869 break;
7870 }
7871 return QWindow::event(e);
7872 }
7873 \endcode
7874
7875 Initializing the swapchain and starting to render the first frame cannot
7876 start at any time. The safe, cross-platform approach is to rely on expose
7877 events. QExposeEvent is a loosely specified event that is sent whenever a
7878 window gets mapped, obscured, and resized, depending on the platform.
7879
7880 \code
7881 void Window::exposeEvent(QExposeEvent *)
7882 {
7883 // initialize and start rendering when the window becomes usable for graphics purposes
7884 if (isExposed() && !running) {
7885 running = true;
7886 init();
7887 }
7888
7889 // stop pushing frames when not exposed or size becomes 0
7890 if ((!isExposed() || (hasSwapChain && sc->surfacePixelSize().isEmpty())) && running)
7891 notExposed = true;
7892
7893 // continue when exposed again and the surface has a valid size
7894 if (isExposed() && running && notExposed && !sc->surfacePixelSize().isEmpty()) {
7895 notExposed = false;
7896 newlyExposed = true;
7897 }
7898
7899 if (isExposed() && !sc->surfacePixelSize().isEmpty())
7900 render();
7901 }
7902 \endcode
7903
7904 Once the rendering has started, a simple way to request a new frame is
7905 QWindow::requestUpdate(). While on some platforms this is merely a small
7906 timer, on others it has a specific implementation: for instance on macOS or
7907 iOS it may be backed by
7908 \l{https://developer.apple.com/documentation/corevideo/cvdisplaylink?language=objc}{CVDisplayLink}.
7909 The example above is already prepared for update requests by handling
7910 QEvent::UpdateRequest.
7911
7912 While acting as a QRhiRenderTarget, QRhiSwapChain also manages a
7913 QRhiCommandBuffer. Calling QRhi::endFrame() submits the recorded commands
7914 and also enqueues a \c present request. The default behavior is to do this
7915 with a swap interval of 1, meaning synchronizing to the display's vertical
7916 refresh is enabled. Thus the rendering thread calling beginFrame() and
7917 endFrame() will get throttled to vsync. On some backends this can be
7918 disabled by passing QRhiSwapChain:NoVSync in flags().
7919
7920 Multisampling (MSAA) is handled transparently to the applications when
7921 requested via setSampleCount(). Where applicable, QRhiSwapChain will take
7922 care of creating additional color buffers and issuing a multisample resolve
7923 command at the end of a frame. For OpenGL, it is necessary to request the
7924 appropriate sample count also via QSurfaceFormat, by calling
7925 QSurfaceFormat::setDefaultFormat() before initializing the QRhi.
7926
7927 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7928 for details.
7929 */
7930
7931/*!
7932 \enum QRhiSwapChain::Flag
7933 Flag values to describe swapchain properties
7934
7935 \value SurfaceHasPreMulAlpha Indicates that the target surface has
7936 transparency with premultiplied alpha. For example, this is what Qt Quick
7937 uses when the alpha channel is enabled on the target QWindow, because the
7938 scenegraph rendrerer always outputs fragments with alpha multiplied into
7939 the red, green, and blue values. To ensure identical behavior across
7940 platforms, always set QSurfaceFormat::alphaBufferSize() to a non-zero value
7941 on the target QWindow whenever this flag is set on the swapchain.
7942
7943 \value SurfaceHasNonPreMulAlpha Indicates the target surface has
7944 transparency with non-premultiplied alpha. Be aware that this may not be
7945 supported on some systems, if the system compositor always expects content
7946 with premultiplied alpha. In that case the behavior with this flag set is
7947 expected to be equivalent to SurfaceHasPreMulAlpha.
7948
7949 \value sRGB Requests to pick an sRGB format for the swapchain's color
7950 buffers and/or render target views, where applicable. Note that this
7951 implies that sRGB framebuffer update and blending will get enabled for all
7952 content targeting this swapchain, and opting out is not possible. For
7953 OpenGL, set \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the
7954 QSurfaceFormat of the QWindow in addition. Applicable only when the
7955 swapchain format is set to QRhiSwapChain::SDR.
7956
7957 \value UsedAsTransferSource Indicates the swapchain will be used as the
7958 source of a readback in QRhiResourceUpdateBatch::readBackTexture().
7959
7960 \value NoVSync Requests disabling waiting for vertical sync, also avoiding
7961 throttling the rendering thread. The behavior is backend specific and
7962 applicable only where it is possible to control this. Some may ignore the
7963 request altogether. For OpenGL, try instead setting the swap interval to 0
7964 on the QWindow via QSurfaceFormat::setSwapInterval().
7965
7966 \value MinimalBufferCount Requests creating the swapchain with the minimum
7967 number of buffers, which is in practice 2, unless the graphics
7968 implementation has a higher minimum number than that. Only applicable with
7969 backends where such control is available via the graphics API, for example,
7970 Vulkan. By default it is up to the backend to decide what number of buffers
7971 it requests (in practice this is almost always either 2 or 3), and it is
7972 not the applications' concern. However, on Vulkan for instance the backend
7973 will likely prefer the higher number (3), for example to avoid odd
7974 performance issues with some Vulkan implementations on mobile devices. It
7975 could be that on some platforms it can prove to be beneficial to force the
7976 lower buffer count (2), so this flag allows forcing that. Note that all
7977 this has no effect on the number of frames kept in flight, so the CPU
7978 (QRhi) will still prepare frames at most \c{N - 1} frames ahead of the GPU,
7979 even when the swapchain image buffer count larger than \c N. (\c{N} =
7980 QRhi::FramesInFlight and typically 2).
7981 */
7982
7983/*!
7984 \enum QRhiSwapChain::Format
7985 Describes the swapchain format. The default format is SDR.
7986
7987 This enum is used with
7988 \l{QRhiSwapChain::isFormatSupported()}{isFormatSupported()} to check
7989 upfront if creating the swapchain with the given format is supported by the
7990 platform and the window's associated screen, and with
7991 \l{QRhiSwapChain::setFormat()}{setFormat()}
7992 to set the requested format in the swapchain before calling
7993 \l{QRhiSwapChain::createOrResize()}{createOrResize()} for the first time.
7994
7995 \value SDR 8-bit RGBA or BGRA, depending on the backend and platform. With
7996 OpenGL ES in particular, it could happen that the platform provides less
7997 than 8 bits (e.g. due to EGL and the QSurfaceFormat choosing a 565 or 444
7998 format - this is outside the control of QRhi). Standard dynamic range. May
7999 be combined with setting the QRhiSwapChain::sRGB flag.
8000
8001 \value HDRExtendedSrgbLinear 16-bit float RGBA, high dynamic range,
8002 extended linear sRGB (scRGB) color space. This involves Rec. 709 primaries
8003 (same as SDR/sRGB) and linear colors. Conversion to the display's native
8004 color space (such as, HDR10) is performed by the windowing system. On
8005 Windows this is the canonical color space of the system compositor, and is
8006 the recommended format for HDR swapchains in general on desktop platforms.
8007
8008 \value HDR10 10-bit unsigned int RGB or BGR with 2 bit alpha, high dynamic
8009 range, HDR10 (Rec. 2020) color space with an ST2084 PQ transfer function.
8010
8011 \value HDRExtendedDisplayP3Linear 16-bit float RGBA, high dynamic range,
8012 extended linear Display P3 color space. The primary choice for HDR on
8013 platforms such as iOS and VisionOS.
8014 */
8015
8016/*!
8017 \internal
8018 */
8019QRhiSwapChain::QRhiSwapChain(QRhiImplementation *rhi)
8020 : QRhiResource(rhi)
8021{
8022}
8023
8024/*!
8025 \return the resource type.
8026 */
8027QRhiResource::Type QRhiSwapChain::resourceType() const
8028{
8029 return SwapChain;
8030}
8031
8032/*!
8033 \fn QSize QRhiSwapChain::currentPixelSize() const
8034
8035 \return the size with which the swapchain was last successfully built. Use
8036 this to decide if createOrResize() needs to be called again: if
8037 \c{currentPixelSize() != surfacePixelSize()} then the swapchain needs to be
8038 resized.
8039
8040 \note Typical rendering logic will call this function to get the output
8041 size when starting to prepare a new frame, and base dependent calculations
8042 (such as, the viewport) on the size returned from this function.
8043
8044 While in many cases the value is the same as \c{QWindow::size() *
8045 QWindow::devicePixelRatio()}, relying on the QWindow-reported size is not
8046 guaranteed to be correct on all platforms and graphics API implementations.
8047 Using this function is therefore strongly recommended whenever there is a
8048 need to identify the dimensions, in pixels, of the output layer or surface.
8049
8050 This also has the added benefit of avoiding potential data races when QRhi
8051 is used on a dedicated rendering thread, because the need to call QWindow
8052 functions, that may then access data updated on the main thread, is
8053 avoided.
8054
8055 \sa surfacePixelSize()
8056 */
8057
8058/*!
8059 \fn virtual QSize QRhiSwapChain::surfacePixelSize() = 0
8060
8061 \return The size of the window's associated surface or layer.
8062
8063 \warning Do not assume this is the same as \c{QWindow::size() *
8064 QWindow::devicePixelRatio()}. With some graphics APIs and windowing system
8065 interfaces (for example, Vulkan) there is a theoretical possibility for a
8066 surface to assume a size different from the associated window. To support
8067 these cases, \b{rendering logic must always base size-derived calculations
8068 (such as, viewports) on the size reported from QRhiSwapChain, and never on
8069 the size queried from QWindow}.
8070
8071 \note \b{Can also be called before createOrResize(), if at least window() is
8072 already set. This in combination with currentPixelSize() allows to detect
8073 when a swapchain needs to be resized.} However, watch out for the fact that
8074 the size of the underlying native object (surface, layer, or similar) is
8075 "live", so whenever this function is called, it returns the latest value
8076 reported by the underlying implementation, without any atomicity guarantee.
8077 Therefore, using this function to determine pixel sizes for graphics
8078 resources that are used in a frame is strongly discouraged. Rely on
8079 currentPixelSize() instead which returns a size that is atomic and will not
8080 change between createOrResize() invocations.
8081
8082 \note For depth-stencil buffers used in combination with the swapchain's
8083 color buffers, it is strongly recommended to rely on the automatic sizing
8084 and rebuilding behavior provided by the
8085 QRhiRenderBuffer:UsedWithSwapChainOnly flag. Avoid querying the surface
8086 size via this function just to get a size that can be passed to
8087 QRhiRenderBuffer::setPixelSize() as that would suffer from the lack of
8088 atomicity as described above.
8089
8090 \sa currentPixelSize()
8091 */
8092
8093/*!
8094 \fn virtual bool QRhiSwapChain::isFormatSupported(Format f) = 0
8095
8096 \return true if the given swapchain format \a f is supported. SDR is always
8097 supported.
8098
8099 \note Can be called independently of createOrResize(), but window() must
8100 already be set. Calling without the window set may lead to unexpected
8101 results depending on the backend and platform (most likely false for any
8102 HDR format), because HDR format support is usually tied to the output
8103 (screen) to which the swapchain's associated window belongs at any given
8104 time. If the result is true for a HDR format, then creating the swapchain
8105 with that format is expected to succeed as long as the window is not moved
8106 to another screen in the meantime.
8107
8108 The main use of this function is to call it before the first
8109 createOrResize() after the window is already set. This allow the QRhi
8110 backends to perform platform or windowing system specific queries to
8111 determine if the window (and the screen it is on) is capable of true HDR
8112 output with the specified format.
8113
8114 When the format is reported as supported, call setFormat() to set the
8115 requested format and call createOrResize(). Be aware of the consequences
8116 however: successfully requesting a HDR format will involve having to deal
8117 with a different color space, possibly doing white level correction for
8118 non-HDR-aware content, adjusting tonemapping methods, adjusting offscreen
8119 render target settings, etc.
8120
8121 \sa setFormat()
8122 */
8123
8124/*!
8125 \fn virtual QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer() = 0
8126
8127 \return a command buffer on which rendering commands and resource updates
8128 can be recorded within a \l{QRhi::beginFrame()}{beginFrame} -
8129 \l{QRhi::endFrame()}{endFrame} block, assuming beginFrame() was called with
8130 this swapchain.
8131
8132 \note The returned object is valid also after endFrame(), up until the next
8133 beginFrame(), but the returned command buffer should not be used to record
8134 any commands then. Rather, it can be used to query data collected during
8135 the frame (or previous frames), for example by calling
8136 \l{QRhiCommandBuffer::lastCompletedGpuTime()}{lastCompletedGpuTime()}.
8137
8138 \note The value must not be cached and reused between frames. The caller
8139 should not hold on to the returned object once
8140 \l{QRhi::beginFrame()}{beginFrame()} is called again. Instead, the command
8141 buffer object should be queried again by calling this function.
8142*/
8143
8144/*!
8145 \fn virtual QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget() = 0
8146
8147 \return a render target that can used with beginPass() in order to render
8148 the swapchain's current backbuffer. Only valid within a
8149 QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called
8150 with this swapchain.
8151
8152 \note the value must not be cached and reused between frames
8153 */
8154
8155/*!
8156 \enum QRhiSwapChain::StereoTargetBuffer
8157 Selects the backbuffer to use with a stereoscopic swapchain.
8158
8159 \value LeftBuffer
8160 \value RightBuffer
8161 */
8162
8163/*!
8164 \return a render target that can be used with beginPass() in order to
8165 render to the swapchain's left or right backbuffer. This overload should be
8166 used only with stereoscopic rendering, that is, when the associated QWindow
8167 is backed by two color buffers, one for each eye, instead of just one.
8168
8169 When stereoscopic rendering is not supported, the return value will be
8170 the default target. It is supported by all hardware backends except for Metal, in
8171 combination with \l QSurfaceFormat::StereoBuffers, assuming it is supported
8172 by the graphics and display driver stack at run time. Metal and Null backends
8173 are going to return the default render target from this overload.
8174
8175 \note the value must not be cached and reused between frames
8176 */
8177QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
8178{
8179 Q_UNUSED(targetBuffer);
8180 return currentFrameRenderTarget();
8181}
8182
8183/*!
8184 \fn virtual bool QRhiSwapChain::createOrResize() = 0
8185
8186 Creates the swapchain if not already done and resizes the swapchain buffers
8187 to match the current size of the targeted surface. Call this whenever the
8188 size of the target surface is different than before.
8189
8190 \note call destroy() only when the swapchain needs to be released
8191 completely, typically upon
8192 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed. To perform resizing, just
8193 call createOrResize().
8194
8195 \return \c true when successful, \c false when a graphics operation failed.
8196 Regardless of the return value, calling destroy() is always safe.
8197 */
8198
8199/*!
8200 \fn QWindow *QRhiSwapChain::window() const
8201 \return the currently set window.
8202 */
8203
8204/*!
8205 \fn void QRhiSwapChain::setWindow(QWindow *window)
8206 Sets the \a window.
8207 */
8208
8209/*!
8210 \fn QRhiSwapChainProxyData QRhiSwapChain::proxyData() const
8211 \return the currently set proxy data.
8212 */
8213
8214/*!
8215 \fn void QRhiSwapChain::setProxyData(const QRhiSwapChainProxyData &d)
8216 Sets the proxy data \a d.
8217
8218 \sa QRhi::updateSwapChainProxyData()
8219 */
8220
8221/*!
8222 \fn QRhiSwapChain::Flags QRhiSwapChain::flags() const
8223 \return the currently set flags.
8224 */
8225
8226/*!
8227 \fn void QRhiSwapChain::setFlags(Flags f)
8228 Sets the flags \a f.
8229 */
8230
8231/*!
8232 \fn QRhiSwapChain::Format QRhiSwapChain::format() const
8233 \return the currently set format.
8234 */
8235
8236/*!
8237 \fn void QRhiSwapChain::setFormat(Format f)
8238 Sets the format \a f.
8239
8240 Avoid setting formats that are reported as unsupported from
8241 isFormatSupported(). Note that support for a given format may depend on the
8242 screen the swapchain's associated window is opened on. On some platforms,
8243 such as Windows and macOS, for HDR output to work it is necessary to have
8244 HDR output enabled in the display settings.
8245
8246 See isFormatSupported(), \l QRhiSwapChainHdrInfo, and \l Format for more
8247 information on high dynamic range output.
8248 */
8249
8250/*!
8251 \fn QRhiRenderBuffer *QRhiSwapChain::depthStencil() const
8252 \return the currently associated renderbuffer for depth-stencil.
8253 */
8254
8255/*!
8256 \fn void QRhiSwapChain::setDepthStencil(QRhiRenderBuffer *ds)
8257 Sets the renderbuffer \a ds for use as a depth-stencil buffer.
8258 */
8259
8260/*!
8261 \fn int QRhiSwapChain::sampleCount() const
8262 \return the currently set sample count. 1 means no multisample antialiasing.
8263 */
8264
8265/*!
8266 \fn void QRhiSwapChain::setSampleCount(int samples)
8267
8268 Sets the sample count. Common values for \a samples are 1 (no MSAA), 4 (4x
8269 MSAA), or 8 (8x MSAA).
8270
8271 \sa QRhi::supportedSampleCounts()
8272 */
8273
8274/*!
8275 \fn QRhiRenderPassDescriptor *QRhiSwapChain::renderPassDescriptor() const
8276 \return the currently associated QRhiRenderPassDescriptor object.
8277 */
8278
8279/*!
8280 \fn void QRhiSwapChain::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
8281 Associates with the QRhiRenderPassDescriptor \a desc.
8282 */
8283
8284/*!
8285 \fn virtual QRhiRenderPassDescriptor *QRhiSwapChain::newCompatibleRenderPassDescriptor() = 0;
8286
8287 \return a new QRhiRenderPassDescriptor that is compatible with this swapchain.
8288
8289 The returned value is used in two ways: it can be passed to
8290 setRenderPassDescriptor() and
8291 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
8292 describes the attachments (color, depth/stencil) and the load/store
8293 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
8294 be used in combination with a swapchain that has a
8295 \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
8296 QRhiRenderPassDescriptor set.
8297
8298 \sa createOrResize()
8299 */
8300
8301/*!
8302 \fn QRhiShadingRateMap *QRhiSwapChain::shadingRateMap() const
8303 \return the currently set QRhiShadingRateMap. By default this is \nullptr.
8304 \since 6.9
8305 */
8306
8307/*!
8308 \fn void QRhiSwapChain::setShadingRateMap(QRhiShadingRateMap *map)
8309
8310 Associates with the specified QRhiShadingRateMap \a map. This is functional
8311 only when the \l QRhi::VariableRateShadingMap feature is reported as
8312 supported.
8313
8314 When QRhiCommandBuffer::setShadingRate() is also called, the higher of the
8315 two shading rates is used for each tile. There is currently no control
8316 offered over the combiner behavior.
8317
8318 \note Setting a shading rate map implies that a different, new
8319 QRhiRenderPassDescriptor is needed and some of the native swapchain objects
8320 must be rebuilt. Therefore, if the swapchain is already set up, call
8321 newCompatibleRenderPassDescriptor() and setRenderPassDescriptor() right
8322 after setShadingRateMap(). Then, createOrResize() must also be called again.
8323 This has rolling consequences, for example for graphics pipelines: those
8324 also need to be associated with the new QRhiRenderPassDescriptor and then
8325 rebuilt. See \l QRhiRenderPassDescriptor::serializedFormat() for some
8326 suggestions on how to deal with this. Remember to set the
8327 QRhiGraphicsPipeline::UsesShadingRate flag for them as well.
8328
8329 \since 6.9
8330 */
8331
8332/*!
8333 \struct QRhiSwapChainHdrInfo
8334 \inmodule QtGuiPrivate
8335 \inheaderfile rhi/qrhi.h
8336 \since 6.6
8337
8338 \brief Describes the high dynamic range related information of the
8339 swapchain's associated output.
8340
8341 To perform HDR-compatible tonemapping, where the target range is not [0,1],
8342 one often needs to know the maximum luminance of the display the
8343 swapchain's window is associated with. While this is often made
8344 user-configurable (think brightness, gamma and similar settings in games),
8345 it can be highly useful to set defaults based on the values reported by the
8346 display itself, thus providing a decent starting point.
8347
8348 There are some problems however: the information is exposed in different
8349 forms on different platforms, whereas with cross-platform graphics APIs
8350 there is often no associated solution at all, because managing such
8351 information is not in the scope of the API (and may rather be retrievable
8352 via other platform-specific means, if any).
8353
8354 With Metal on macOS/iOS, there is no luminance values exposed in the
8355 platform APIs. Instead, the maximum color component value, that would be
8356 1.0 in a non-HDR setup, is provided. The \c limitsType field indicates what
8357 kind of information is available. It is then up to the clients of QRhi to
8358 access the correct data from the \c limits union and use it as they see
8359 fit.
8360
8361 With an API like Vulkan, where there is no way to get such information, the
8362 values are always the built-in defaults.
8363
8364 Therefore, the struct returned from QRhiSwapChain::hdrInfo() contains
8365 either some hard-coded defaults or real values received from an API such as
8366 DXGI (IDXGIOutput6) or Cocoa (NSScreen). When no platform queries are
8367 available (or needs using platform facilities out of scope for QRhi), the
8368 hard-coded defaults are a maximum luminance of 1000 nits and an SDR white
8369 level of 200.
8370
8371 The struct also exposes the presumed luminance behavior of the platform and
8372 its compositor, to indicate what a color component value of 1.0 is treated
8373 as in a HDR color buffer. In some cases it will be necessary to perform
8374 color correction of non-HDR content composited with HDR content. To enable
8375 this, the SDR white level is queried from the system on some platforms
8376 (Windows) and exposed here.
8377
8378 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8379 for details.
8380
8381 \sa QRhiSwapChain::hdrInfo()
8382 */
8383
8384/*!
8385 \enum QRhiSwapChainHdrInfo::LimitsType
8386
8387 \value LuminanceInNits Indicates that the \l limits union has its
8388 \c luminanceInNits struct set
8389
8390 \value ColorComponentValue Indicates that the \l limits union has its
8391 \c colorComponentValue struct set
8392*/
8393
8394/*!
8395 \enum QRhiSwapChainHdrInfo::LuminanceBehavior
8396
8397 \value SceneReferred Indicates that the color value of 1.0 is interpreted
8398 as 80 nits. This is the behavior of HDR-enabled windows with the Windows
8399 compositor. See
8400 \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range}{this
8401 page} for more information on HDR on Windows.
8402
8403 \value DisplayReferred Indicates that the color value of 1.0 is interpreted
8404 as the value of the SDR white. (which can be e.g. 200 nits, but will vary
8405 depending on screen brightness) This is the behavior of HDR-enabled windows
8406 on Apple platforms. See
8407 \l{https://developer.apple.com/documentation/metal/hdr_content/displaying_hdr_content_in_a_metal_layer}{this
8408 page} for more information on Apple's EDR system.
8409*/
8410
8411/*!
8412 \variable QRhiSwapChainHdrInfo::limitsType
8413
8414 With Metal on macOS/iOS, there is no luminance values exposed in the
8415 platform APIs. Instead, the maximum color component value, that would be
8416 1.0 in a non-HDR setup, is provided. This value indicates what kind of
8417 information is available in \l limits.
8418
8419 \sa QRhiSwapChain::hdrInfo()
8420*/
8421
8422/*!
8423 \variable QRhiSwapChainHdrInfo::limits
8424
8425 Contains the actual values queried from the graphics API or the platform.
8426 The type of data is indicated by \l limitsType. This is therefore a union.
8427 There are currently two options:
8428
8429 Luminance values in nits:
8430
8431 \code
8432 struct {
8433 float minLuminance;
8434 float maxLuminance;
8435 } luminanceInNits;
8436 \endcode
8437
8438 On Windows the minimum and maximum luminance depends on the screen
8439 brightness. While not relevant for desktops, on laptops the screen
8440 brightness may change at any time. Increasing brightness implies decreased
8441 maximum luminance. In addition, the results may also be dependent on the
8442 HDR Content Brightness set in Windows Settings' System/Display/HDR view,
8443 if there is such a setting.
8444
8445 Note however that the changes made to the laptop screen's brightness or in
8446 the system settings while the application is running are not necessarily
8447 reflected in the returned values, meaning calling hdrInfo() again may still
8448 return the same luminance range as before for the rest of the process'
8449 lifetime. The exact behavior is up to DXGI and Qt has no control over it.
8450
8451 \note The Windows compositor works in scene-referred mode for HDR content.
8452 A color component value of 1.0 corresponds to a luminance of 80 nits. When
8453 rendering non-HDR content (e.g. 2D UI elements), the correction of the
8454 white level is often necessary. (e.g., outputting the fragment color (1, 1,
8455 1) will likely lead to showing a shade of white that is too dim on-screen)
8456 See \l sdrWhiteLevel.
8457
8458 For macOS/iOS, the current maximum and potential maximum color
8459 component values are provided:
8460
8461 \code
8462 struct {
8463 float maxColorComponentValue;
8464 float maxPotentialColorComponentValue;
8465 } colorComponentValue;
8466 \endcode
8467
8468 The value may depend on the screen brightness, which on laptops means that
8469 the result may change in the next call to hdrInfo() if the brightness was
8470 changed in the meantime. The maximum screen brightness implies a maximum
8471 color value of 1.0.
8472
8473 \note Apple's EDR is display-referred. 1.0 corresponds to a luminance level
8474 of SDR white (e.g. 200 nits), the value of which varies based on the screen
8475 brightness and possibly other settings. The exact luminance value for that,
8476 or the maximum luminance of the display, are not exposed to the
8477 applications.
8478
8479 \note It has been observed that the color component values are not set to
8480 the correct larger-than-1 value right away on startup on some macOS
8481 systems, but the values tend to change during or after the first frame.
8482
8483 \sa QRhiSwapChain::hdrInfo()
8484*/
8485
8486/*!
8487 \variable QRhiSwapChainHdrInfo::luminanceBehavior
8488
8489 Describes the platform's presumed behavior with regards to color values.
8490
8491 \sa sdrWhiteLevel
8492 */
8493
8494/*!
8495 \variable QRhiSwapChainHdrInfo::sdrWhiteLevel
8496
8497 On Windows this is the dynamic SDR white level in nits. The value is
8498 dependent on the screen brightness (on laptops), and the SDR or HDR Content
8499 Brightness settings in the Windows settings' System/Display/HDR view.
8500
8501 To perform white level correction for non-HDR (SDR) content, such as 2D UI
8502 elemenents, multiply the final color with sdrWhiteLevel / 80.0 whenever
8503 \l luminanceBehavior is SceneReferred. (assuming Windows and a linear
8504 extended sRGB (scRGB) color space)
8505
8506 On other platforms the value is always a pre-defined value, 200. This may
8507 not match the system's actual SDR white level, but the value of this
8508 variable is not relevant in practice when the \l luminanceBehavior is
8509 DisplayReferred, because then the color component value of 1.0 refers to
8510 the SDR white by default.
8511
8512 \sa luminanceBehavior
8513*/
8514
8515/*!
8516 \return the HDR information for the associated display.
8517
8518 Do not assume that this is a cheap operation. Depending on the platform,
8519 this function makes various platform queries which may have a performance
8520 impact.
8521
8522 \note Can be called before createOrResize() as long as the window is
8523 \l{setWindow()}{set}.
8524
8525 \note What happens when moving a window with an initialized swapchain
8526 between displays (HDR to HDR with different characteristics, HDR to SDR,
8527 etc.) is not currently well-defined and depends heavily on the windowing
8528 system and compositor, with potentially varying behavior between platforms.
8529 Currently QRhi only guarantees that hdrInfo() returns valid data, if
8530 available, for the display to which the swapchain's associated window
8531 belonged at the time of createOrResize().
8532
8533 \sa QRhiSwapChainHdrInfo
8534 */
8535QRhiSwapChainHdrInfo QRhiSwapChain::hdrInfo()
8536{
8537 QRhiSwapChainHdrInfo info;
8538 info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
8539 info.limits.luminanceInNits.minLuminance = 0.0f;
8540 info.limits.luminanceInNits.maxLuminance = 1000.0f;
8541 info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
8542 info.sdrWhiteLevel = 200.0f;
8543 return info;
8544}
8545
8546#ifndef QT_NO_DEBUG_STREAM
8547QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
8548{
8549 QDebugStateSaver saver(dbg);
8550 dbg.nospace() << "QRhiSwapChainHdrInfo(";
8551 switch (info.limitsType) {
8553 dbg.nospace() << " minLuminance=" << info.limits.luminanceInNits.minLuminance
8554 << " maxLuminance=" << info.limits.luminanceInNits.maxLuminance;
8555 break;
8557 dbg.nospace() << " maxColorComponentValue=" << info.limits.colorComponentValue.maxColorComponentValue;
8558 dbg.nospace() << " maxPotentialColorComponentValue=" << info.limits.colorComponentValue.maxPotentialColorComponentValue;
8559 break;
8560 }
8561 switch (info.luminanceBehavior) {
8563 dbg.nospace() << " scene-referred, SDR white level=" << info.sdrWhiteLevel;
8564 break;
8566 dbg.nospace() << " display-referred";
8567 break;
8568 }
8569 dbg.nospace() << ')';
8570 return dbg;
8571}
8572#endif
8573
8574/*!
8575 \class QRhiComputePipeline
8576 \inmodule QtGuiPrivate
8577 \inheaderfile rhi/qrhi.h
8578 \since 6.6
8579 \brief Compute pipeline state resource.
8580
8581 \note Setting the shader resource bindings is mandatory. The referenced
8582 QRhiShaderResourceBindings must already have created() called on it by the
8583 time create() is called.
8584
8585 \note Setting the shader is mandatory.
8586
8587 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8588 for details.
8589 */
8590
8591/*!
8592 \enum QRhiComputePipeline::Flag
8593
8594 Flag values for describing pipeline options.
8595
8596 \value CompileShadersWithDebugInfo Requests compiling shaders with debug
8597 information enabled, when applicable. See
8598 QRhiGraphicsPipeline::CompileShadersWithDebugInfo for more information.
8599 */
8600
8601/*!
8602 \return the resource type.
8603 */
8604QRhiResource::Type QRhiComputePipeline::resourceType() const
8605{
8606 return ComputePipeline;
8607}
8608
8609/*!
8610 \internal
8611 */
8612QRhiComputePipeline::QRhiComputePipeline(QRhiImplementation *rhi)
8613 : QRhiResource(rhi)
8614{
8615}
8616
8617/*!
8618 \fn QRhiComputePipeline::Flags QRhiComputePipeline::flags() const
8619 \return the currently set flags.
8620 */
8621
8622/*!
8623 \fn void QRhiComputePipeline::setFlags(Flags f)
8624 Sets the flags \a f.
8625 */
8626
8627/*!
8628 \fn QRhiShaderStage QRhiComputePipeline::shaderStage() const
8629 \return the currently set shader.
8630 */
8631
8632/*!
8633 \fn void QRhiComputePipeline::setShaderStage(const QRhiShaderStage &stage)
8634
8635 Sets the shader to use. \a stage can only refer to the
8636 \l{QRhiShaderStage::Compute}{compute stage}.
8637 */
8638
8639/*!
8640 \fn QRhiShaderResourceBindings *QRhiComputePipeline::shaderResourceBindings() const
8641 \return the currently associated QRhiShaderResourceBindings object.
8642 */
8643
8644/*!
8645 \fn void QRhiComputePipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
8646
8647 Associates with \a srb describing the resource binding layout and the
8648 resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional. As
8649 with graphics pipelines, the \a srb passed in here can leave the actual
8650 buffer or texture objects unspecified (\nullptr) as long as there is
8651 another,
8652 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
8653 QRhiShaderResourceBindings bound via
8654 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
8655 recording the dispatch call.
8656 */
8657
8658/*!
8659 \struct QRhiIndirectDrawCommand
8660 \inmodule QtGuiPrivate
8661 \inheaderfile rhi/qrhi.h
8662 \since 6.12
8663 \brief Draw command.
8664
8665 A draw command that can be uploaded to a QRhiBuffer of usage
8666 QRhiBuffer::UsageFlag::IndirectBuffer.
8667
8668 \sa QRhiCommandBuffer::drawIndirect()
8669
8670 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8671 for details.
8672 */
8673
8674/*!
8675 \variable QRhiIndirectDrawCommand::vertexCount
8676*/
8677
8678/*!
8679 \variable QRhiIndirectDrawCommand::instanceCount
8680*/
8681
8682/*!
8683 \variable QRhiIndirectDrawCommand::firstVertex
8684*/
8685
8686/*!
8687 \variable QRhiIndirectDrawCommand::firstInstance
8688*/
8689
8690/*!
8691 \struct QRhiIndexedIndirectDrawCommand
8692 \inmodule QtGuiPrivate
8693 \inheaderfile rhi/qrhi.h
8694 \since 6.12
8695 \brief Indexed draw command.
8696
8697 An indexed draw command that can be uploaded to a QRhiBuffer of usage
8698 QRhiBuffer::UsageFlag::IndirectBuffer.
8699
8700 \sa QRhiCommandBuffer::drawIndexedIndirect()
8701
8702 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8703 for details.
8704 */
8705
8706/*!
8707 \variable QRhiIndexedIndirectDrawCommand::indexCount
8708*/
8709
8710/*!
8711 \variable QRhiIndexedIndirectDrawCommand::instanceCount
8712*/
8713
8714/*!
8715 \variable QRhiIndexedIndirectDrawCommand::firstIndex
8716*/
8717
8718/*!
8719 \variable QRhiIndexedIndirectDrawCommand::vertexOffset
8720*/
8721
8722/*!
8723 \variable QRhiIndexedIndirectDrawCommand::firstInstance
8724*/
8725
8726/*!
8727 \struct QRhiDispatchIndirectCommand
8728 \inmodule QtGuiPrivate
8729 \inheaderfile rhi/qrhi.h
8730 \since 6.13
8731 \brief Compute dispatch command.
8732
8733 A compute dispatch command that can be uploaded to a QRhiBuffer of usage
8734 QRhiBuffer::UsageFlag::IndirectBuffer. The fields specify the number of
8735 local work groups along each dimension and have the same meaning as the
8736 \c x, \c y, \c z parameters of QRhiCommandBuffer::dispatch().
8737
8738 \c y and \c z default to 1, so a one dimensional dispatch only needs \c x
8739 to be set. Note that a count of 0 in any dimension is valid and results in
8740 no work groups being launched at all.
8741
8742 \sa QRhiCommandBuffer::dispatchIndirect()
8743
8744 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8745 for details.
8746 */
8747
8748/*!
8749 \variable QRhiDispatchIndirectCommand::x
8750*/
8751
8752/*!
8753 \variable QRhiDispatchIndirectCommand::y
8754*/
8755
8756/*!
8757 \variable QRhiDispatchIndirectCommand::z
8758*/
8759
8760/*!
8761 \class QRhiIndirectCommandBuffer
8762 \inmodule QtGuiPrivate
8763 \inheaderfile rhi/qrhi.h
8764 \since 6.13
8765 \brief A prerecorded batch of indirect draw commands.
8766
8767 A QRhiIndirectCommandBuffer holds a number of draw commands that are
8768 recorded once and can then be replayed any number of times with a single
8769 QRhiCommandBuffer::executeIndirect() call. It is an alternative to the
8770 buffer-based QRhiCommandBuffer::drawIndirect() family of functions. Under
8771 the hood, it may do exactly the same as does (typical with Vulkan, Direct
8772 3D, and OpenGL), or may be implemented differently (Metal).
8773
8774 Create one with QRhi::newIndirectCommandBuffer(), passing in the type and
8775 the maximum number of commands, and call create(). The (maximum) command
8776 count is mandatory, whichever way the commands are going to be provided: it
8777 is the capacity of the object, and create() fails when it is 0.
8778
8779 \badcode
8780 icb = rhi->newIndirectCommandBuffer(QRhiIndirectCommandBuffer::IndexedDraws, 1024);
8781 if (!icb->create()) { error(); }
8782 \endcode
8783
8784 Record commands with draw() or drawIndexed(), then hand the object to a
8785 resource update batch so that the recorded contents reach the GPU.
8786 commitIndirectCommandBuffer() has to be called after recording and before
8787 the pass that executes the commands. It is a no-op when nothing changed
8788 since the last time, so calling it every frame is cheap.
8789
8790 Executing happens inside a render pass:
8791
8792 \badcode
8793 icb->clear();
8794 for (const Item &item : items)
8795 icb->drawIndexed(item.indexCount, 1, item.firstIndex, item.vertexOffset);
8796
8797 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
8798 u->commitIndirectCommandBuffer(icb);
8799
8800 cb->beginPass(rt, Qt::black, { 1.0f, 0 }, u);
8801 cb->setGraphicsPipeline(ps);
8802 cb->setVertexInput(0, 1, &vbufBinding, ibuf, 0, QRhiCommandBuffer::IndexUInt16);
8803 cb->setShaderResources();
8804 cb->executeIndirect(icb);
8805 cb->endPass();
8806 \endcode
8807
8808 The commands can also be generated on the GPU instead of being recorded on
8809 the CPU. In that case fill a buffer with QRhiIndirectDrawCommand or
8810 QRhiIndexedIndirectDrawCommand entries from a compute shader, and call
8811 QRhiCommandBuffer::buildIndirect() with that buffer. That call must happen
8812 outside of any pass. The CPU-side recording functions of
8813 QRhiIndirectCommandBuffer are not used in this case.
8814
8815 \badcode
8816 cb->beginComputePass();
8817 ... // a cb->dispatch() to invoke a compute shader that writes to indirectBuf
8818 cb->endComputePass();
8819
8820 QRhiIndirectCommandBufferBuildInfo buildInfo;
8821 buildInfo.topology = ps->topology();
8822 buildInfo.sourceBuffer = indirectBuf;
8823 buildInfo.commandCount = itemCount; // as many as the compute shader wrote
8824 buildInfo.indexBuffer = indexBuffer;
8825 buildInfo.indexFormat = QRhiCommandBuffer::IndexUInt16;
8826 cb->buildIndirect(icb, buildInfo);
8827
8828 cb->beginPass(rt, Qt::black, { 1.0f, 0 });
8829 cb->setGraphicsPipeline(ps);
8830 cb->setVertexInput(0, 1, &vbufBinding, ibuf, 0, QRhiCommandBuffer::IndexUInt16);
8831 cb->setShaderResources();
8832 cb->executeIndirect(icb);
8833 cb->endPass();
8834 \endcode
8835
8836 When the number of commands is itself decided on the device, set
8837 QRhiIndirectCommandBufferBuildInfo::countBuffer instead of working out
8838 \c itemCount on the CPU. See \l{Command counts} below.
8839
8840 \section2 Command counts
8841
8842 Three counts are involved, and they are not the same thing:
8843
8844 \list
8845
8846 \li maxCommandCount() is the capacity. It is fixed at create() time and
8847 sizes whatever native object the backend needs. Neither of the two ways of
8848 providing commands can exceed it; attempting to does not grow the object.
8849
8850 \li recordedCommandCount() is how many draw() or drawIndexed() calls were
8851 made since the last clear(). It only concerns the CPU-recorded case.
8852
8853 \li commandCount() is how many commands QRhiCommandBuffer::executeIndirect()
8854 issues by default. For a CPU-recorded indirect command buffer that is
8855 recordedCommandCount(). Once QRhiCommandBuffer::buildIndirect() has been
8856 called, isGpuBuilt() returns true and commandCount() is the count resolved
8857 from QRhiIndirectCommandBufferBuildInfo::commandCount instead (but note that
8858 that value is the actual command count only when no
8859 \l{QRhiIndirectCommandBufferBuildInfo::}countBuffer is set, is just a
8860 maximum with a counter buffer present).
8861
8862 \endlist
8863
8864 The size of QRhiIndirectCommandBufferBuildInfo::sourceBuffer plays no part
8865 in any of this: no count is ever derived from it. The buffer is written by
8866 the GPU and is free to be larger than the number of commands actually in
8867 it, so leaving QRhiIndirectCommandBufferBuildInfo::commandCount at 0 does
8868 not mean "as many as fit", it means maxCommandCount().
8869
8870 A device-side count, via QRhiIndirectCommandBufferBuildInfo::countBuffer,
8871 narrows the count further when the commands are executed, and can only
8872 reduce it: the value in the count buffer is clamped to what
8873 commandCount() returns.
8874
8875 Either way, the indirect command buffer is fully prepared before the render
8876 pass begins. That is what separates it from the buffer-based
8877 QRhiCommandBuffer::drawIndirect() family, where some backends (Metal above a
8878 certain draw count, and always for the count variants) have to interrupt and
8879 restart the render pass in order to encode the commands. Such an
8880 interruption costs a QRhiRenderBuffer depth-stencil buffer its contents
8881 unless QRhiRenderBuffer::NoTransientBacking was set, and may also be degrading
8882 performance due to having to reload the color buffer values. With
8883 executeIndirect() the question does not arise.
8884
8885 For Metal, the buffer-based API implies (ahove a certain draw count, or
8886 whhen using the count variants) having to run a compute kernel to create an
8887 MTLIndirectCommandBuffer from the Vulkan/Direct 3D/OpenGL style indirect
8888 buffer. With QRhiIndirectCommandBuffer this is not always necessary, because
8889 now, at least when the commands are generated on the CPU side, an
8890 MTLIndirectCommandBuffer can be created and set up normally, by calling
8891 MTLIndirectCommandBuffer's Objective-C API, instead of having to inject a
8892 compute pass. When generating the commands on the GPU, the extra compute
8893 pass is still necessary, but at least it will not interrupt the render pass,
8894 by design, unlike with the direct buffer-based API. Note however that using
8895 MTLIndirectCommandBuffer natively from C++/Objective-C to perform repeated
8896 CPU-side draw call generation can prove to be quite expensive (when
8897 frequently re-recording a larger set of draw commands), compared to the
8898 GPU-side draw command generation, even though that involves an extra encoding
8899 compute pass to "convert" the Vulkan/Direct 3D/OpenGL style indirect buffer
8900 to what Metal prefers. See the next section.
8901
8902 \section2 Recording on the CPU or building on the GPU
8903
8904 The two ways of populating an indirect command buffer are not equivalent in
8905 cost, and the difference grows with the number of commands.
8906
8907 Recording with draw() or drawIndexed() is work proportional to the number of
8908 commands, and it is repeated whenever the contents change. Where that work
8909 lands depends on the backend: those that keep the commands in a buffer
8910 upload it from QRhiResourceUpdateBatch::commitIndirectCommandBuffer(),
8911 whereas Metal encodes each command individually into a native
8912 \c MTLIndirectCommandBuffer, one native call per command, and does so from
8913 QRhiCommandBuffer::executeIndirect().
8914
8915 Either way the result is cached and keyed on the recorded contents, so an
8916 indirect command buffer that is recorded once and then executed unchanged
8917 frame after frame costs nothing beyond the first few frames. That is the
8918 case CPU recording is meant for: a command set that is stable, or changes
8919 rarely, relative to how often it is executed.
8920
8921 The opposite case - many commands, cleared and re-recorded every frame - is
8922 the one to avoid. Regenerating tens of thousands of commands per frame that
8923 way can be an order of magnitude more expensive on Apple platforms than
8924 filling a QRhiBuffer and calling QRhiCommandBuffer::drawIndexedIndirect() on
8925 it, because of the per-command native encoding. When the command set is both
8926 large and regenerated every frame, generate it on the GPU and use
8927 QRhiCommandBuffer::buildIndirect(); the alternative is to stay with the
8928 buffer-based drawIndirect() family and accept the render pass interruption
8929 it may cause (which is still not recommended, even if it would perform
8930 better).
8931
8932 A given QRhiIndirectCommandBuffer holds one kind of command: either
8933 non-indexed draws (\c Draws) or indexed draws (\c IndexedDraws), never a
8934 mix of the two. This mirrors what the underlying APIs can express: a single
8935 indirect draw call always has one command type and one stride.
8936
8937 The requirements are the same as for the indirect draws this stands in for:
8938 QRhi::DrawIndirect has to be supported, the graphics pipeline should be
8939 created with \l{QRhiGraphicsPipeline::UsesIndirectDraws}{UsesIndirectDraws},
8940 and a count buffer additionally needs QRhi::DrawIndirectCount to be
8941 supported.
8942
8943 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8944 for details.
8945
8946 \sa QRhiCommandBuffer::executeIndirect(), QRhiCommandBuffer::drawIndirect()
8947 */
8948
8949/*!
8950 \enum QRhiIndirectCommandBuffer::Type
8951 Specifies the kind of commands an indirect command buffer holds.
8952
8953 \value Draws Non-indexed draw commands, recorded with draw().
8954 \value IndexedDraws Indexed draw commands, recorded with drawIndexed().
8955 */
8956
8957/*!
8958 \fn QRhiIndirectCommandBuffer::Type QRhiIndirectCommandBuffer::type() const
8959 \return the type of commands this indirect command buffer holds.
8960 */
8961
8962/*!
8963 \fn void QRhiIndirectCommandBuffer::setType(Type t)
8964
8965 Sets the command type \a t. The type is normally specified in
8966 QRhi::newIndirectCommandBuffer(), so this function is only used when it has
8967 to be changed. As with other setters, it only takes effect when calling
8968 create().
8969 */
8970
8971/*!
8972 \fn quint32 QRhiIndirectCommandBuffer::maxCommandCount() const
8973 \return the capacity, i.e. the maximum number of commands.
8974 */
8975
8976/*!
8977 \fn void QRhiIndirectCommandBuffer::setMaxCommandCount(quint32 count)
8978
8979 Sets the capacity, the maximum number of commands, to \a count. The
8980 capacity is normally specified in QRhi::newIndirectCommandBuffer(), so this
8981 function is only used when it has to be changed. As with other setters, it
8982 only takes effect when calling create(), which fails when \a count is 0.
8983
8984 The capacity applies regardless of how the commands are going to be
8985 provided: recording them with draw() and drawIndexed() and building them
8986 with QRhiCommandBuffer::buildIndirect() are both bounded by it.
8987
8988 draw() and drawIndexed() ignore, with a warning, any command past the first
8989 \a count ones. QRhiCommandBuffer::buildIndirect() clamps, also with a
8990 warning, when QRhiIndirectCommandBufferBuildInfo::commandCount is larger.
8991
8992 \sa commandCount(), recordedCommandCount()
8993 */
8994
8995/*!
8996 \fn quint32 QRhiIndirectCommandBuffer::recordedCommandCount() const
8997
8998 \return the number of commands recorded with draw() or drawIndexed() since
8999 the last clear().
9000
9001 This is unaffected by QRhiCommandBuffer::buildIndirect(): once the commands
9002 come from the GPU, whatever was recorded on the CPU is ignored. Use
9003 commandCount() to get the number of commands that will actually be
9004 executed.
9005 */
9006
9007/*!
9008 \fn bool QRhiIndirectCommandBuffer::isGpuBuilt() const
9009
9010 \return \c true when QRhiCommandBuffer::buildIndirect() has been called on
9011 this indirect command buffer, meaning its contents come from a QRhiBuffer
9012 instead of from draw() and drawIndexed().
9013
9014 Once true, this stays true until the next create().
9015 */
9016
9017/*!
9018 \fn quint32 QRhiIndirectCommandBuffer::commandCount() const
9019
9020 \return the number of commands QRhiCommandBuffer::executeIndirect() issues
9021 by default.
9022
9023 This is recordedCommandCount() for a CPU-recorded indirect command buffer,
9024 and the count resolved from
9025 QRhiIndirectCommandBufferBuildInfo::commandCount once
9026 QRhiCommandBuffer::buildIndirect() has been called.
9027
9028 A count buffer, if there is one, can reduce the number of draws further at
9029 execution time. This function does not, and cannot, account for that.
9030 */
9031
9032/*!
9033 \fn virtual bool QRhiIndirectCommandBuffer::create() = 0
9034
9035 Creates the corresponding native objects.
9036
9037 Fails when maxCommandCount() is 0.
9038
9039 A given QRhiIndirectCommandBuffer takes its commands either from draw() and
9040 drawIndexed() followed by
9041 QRhiResourceUpdateBatch::commitIndirectCommandBuffer(), or from
9042 QRhiCommandBuffer::buildIndirect(), but not from both. Moving to the latter
9043 is one-way: clear() does not undo it, and neither does a subsequent
9044 commitIndirectCommandBuffer(); isGpuBuilt() stays true and the commands keep
9045 coming from the buffer. Call create() again to get an indirect command
9046 buffer that is populated from the CPU once more.
9047
9048 \note Like with every other QRhi resource, destroy() gives up the contents,
9049 and so create() starts from an empty indirect command buffer:
9050 recordedCommandCount() is 0 afterwards. Setting a different type() or
9051 maxCommandCount() and calling create() again therefore needs the commands
9052 to be recorded again as well.
9053
9054 \return \c true when successful, \c false when a graphics operation failed.
9055 */
9056
9057/*!
9058 \internal
9059 */
9060QRhiIndirectCommandBuffer::QRhiIndirectCommandBuffer(QRhiImplementation *rhi, Type type_,
9061 quint32 maxCommandCount_)
9062 : QRhiResource(rhi),
9063 m_type(type_), m_maxCommandCount(maxCommandCount_)
9064{
9065}
9066
9067/*!
9068 \return the resource type.
9069 */
9070QRhiResource::Type QRhiIndirectCommandBuffer::resourceType() const
9071{
9072 return IndirectCommandBuffer;
9073}
9074
9075/*!
9076 Discards all commands recorded so far.
9077
9078 Can be called at any time, also before create(). The recorded contents only
9079 become visible to the GPU once the object is passed to
9080 QRhiResourceUpdateBatch::commitIndirectCommandBuffer().
9081
9082 This resets recordedCommandCount() to 0. It does not undo a
9083 QRhiCommandBuffer::buildIndirect(): an indirect command buffer that gets
9084 its commands from the GPU keeps doing so, and commandCount() is unchanged.
9085
9086 \note Clearing and re-recording invalidates whatever the backend cached for
9087 the previous contents, so the per-command cost of recording is paid again.
9088 Call this only when the commands actually have to change. See
9089 \l{Recording on the CPU or building on the GPU} for why that matters at high
9090 command counts.
9091 */
9092void QRhiIndirectCommandBuffer::clear()
9093{
9094 m_data.clear();
9095 m_commandCount = 0;
9096 m_generation += 1;
9097}
9098
9099/*!
9100 Records a non-indexed draw command with \a vertexCount, \a instanceCount,
9101 \a firstVertex, and \a firstInstance.
9102
9103 The semantics are the same as QRhiCommandBuffer::draw().
9104
9105 \note Only valid on an indirect command buffer of type Draws.
9106 */
9107void QRhiIndirectCommandBuffer::draw(quint32 vertexCount, quint32 instanceCount,
9108 quint32 firstVertex, quint32 firstInstance)
9109{
9110 if (m_type != Draws) {
9111 qWarning("QRhiIndirectCommandBuffer: draw() on an IndexedDraws indirect command buffer; ignored");
9112 return;
9113 }
9114 if (m_commandCount == m_maxCommandCount) {
9115 qWarning("QRhiIndirectCommandBuffer: maxCommandCount (%u) reached; command ignored",
9116 m_maxCommandCount);
9117 return;
9118 }
9119 const QRhiIndirectDrawCommand cmd = { vertexCount, instanceCount, firstVertex, firstInstance };
9120 m_data.append(reinterpret_cast<const char *>(&cmd), sizeof(cmd));
9121 m_commandCount += 1;
9122 m_generation += 1;
9123}
9124
9125/*!
9126 Records an indexed draw command with \a indexCount, \a instanceCount, \a
9127 firstIndex, \a vertexOffset, and \a firstInstance.
9128
9129 The semantics are the same as QRhiCommandBuffer::drawIndexed().
9130
9131 \note Only valid on an indirect command buffer of type IndexedDraws.
9132 */
9133void QRhiIndirectCommandBuffer::drawIndexed(quint32 indexCount, quint32 instanceCount,
9134 quint32 firstIndex, qint32 vertexOffset,
9135 quint32 firstInstance)
9136{
9137 if (m_type != IndexedDraws) {
9138 qWarning("QRhiIndirectCommandBuffer: drawIndexed() on a Draws indirect command buffer; ignored");
9139 return;
9140 }
9141 if (m_commandCount == m_maxCommandCount) {
9142 qWarning("QRhiIndirectCommandBuffer: maxCommandCount (%u) reached; command ignored",
9143 m_maxCommandCount);
9144 return;
9145 }
9146 const QRhiIndexedIndirectDrawCommand cmd = { indexCount, instanceCount, firstIndex,
9147 vertexOffset, firstInstance };
9148 m_data.append(reinterpret_cast<const char *>(&cmd), sizeof(cmd));
9149 m_commandCount += 1;
9150 m_generation += 1;
9151}
9152
9153/*!
9154 \struct QRhiIndirectCommandBufferBuildInfo
9155 \inmodule QtGuiPrivate
9156 \inheaderfile rhi/qrhi.h
9157 \since 6.13
9158 \brief Describes how to build an indirect command buffer from a QRhiBuffer.
9159
9160 \sa QRhiCommandBuffer::buildIndirect()
9161
9162 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9163 for details.
9164 */
9165
9166/*!
9167 \variable QRhiIndirectCommandBufferBuildInfo::topology
9168
9169 The topology the commands will be drawn with. Must match the topology of the
9170 graphics pipeline that is set when QRhiCommandBuffer::executeIndirect() is
9171 called. Some backends need it in order to build their native indirect
9172 command buffer, and it is not available to them outside of a render pass.
9173*/
9174
9175/*!
9176 \variable QRhiIndirectCommandBufferBuildInfo::sourceBuffer
9177
9178 The buffer holding the QRhiIndirectDrawCommand or
9179 QRhiIndexedIndirectDrawCommand entries. Must have IndirectBuffer usage.
9180
9181 Its size is not used to work out how many commands there are, see
9182 commandCount.
9183*/
9184
9185/*!
9186 \variable QRhiIndirectCommandBufferBuildInfo::sourceBufferOffset
9187*/
9188
9189/*!
9190 \variable QRhiIndirectCommandBufferBuildInfo::commandCount
9191
9192 The number of commands to take from sourceBuffer. This is what
9193 QRhiIndirectCommandBuffer::commandCount() reports afterwards, and so how
9194 many draws QRhiCommandBuffer::executeIndirect() issues by default.
9195
9196 0 means QRhiIndirectCommandBuffer::maxCommandCount(). It does not mean "as
9197 many as fit in sourceBuffer": a buffer written by the GPU can be larger
9198 than the number of commands in it, so no count is ever derived from its
9199 size. A value above QRhiIndirectCommandBuffer::maxCommandCount() is clamped
9200 to it, with a warning.
9201
9202 \note Specifying countBuffer changes what this value means: it stops being
9203 the number of commands and becomes the \e maximum number of commands, with
9204 the device-side count in countBuffer deciding the actual number. Without a
9205 countBuffer, exactly this many commands are executed.
9206*/
9207
9208/*!
9209 \variable QRhiIndirectCommandBufferBuildInfo::stride
9210
9211 The byte distance between two commands in sourceBuffer. 0 means the size of
9212 the corresponding command struct.
9213*/
9214
9215/*!
9216 \variable QRhiIndirectCommandBufferBuildInfo::countBuffer
9217
9218 An optional buffer whose first quint32 holds the number of commands to
9219 execute. Requires QRhi::DrawIndirectCount.
9220
9221 \note Setting this turns commandCount into an upper bound. The device-side
9222 value is clamped to it, so a count buffer can only ever reduce the number
9223 of draws, never raise it.
9224*/
9225
9226/*!
9227 \variable QRhiIndirectCommandBufferBuildInfo::countBufferOffset
9228*/
9229
9230/*!
9231 \variable QRhiIndirectCommandBufferBuildInfo::indexBuffer
9232
9233 The index buffer the commands index into. Required for IndexedDraws.
9234*/
9235
9236/*!
9237 \variable QRhiIndirectCommandBufferBuildInfo::indexBufferOffset
9238*/
9239
9240/*!
9241 \variable QRhiIndirectCommandBufferBuildInfo::indexFormat
9242*/
9243
9245 Type type,
9246 quint32 maxCommandCount)
9248{
9249}
9250
9255
9257{
9258 // Unconditionally, also when there is nothing else to do: like with every
9259 // other resource, destroy() gives up the contents. Carrying a recording
9260 // over into the next create() would not survive a changed maxCommandCount
9261 // or type.
9262 clear();
9263
9264 if (!valid)
9265 return;
9266
9267 delete buffer;
9268 buffer = nullptr;
9269 uploadedGeneration = 0;
9270 buildInfo = {};
9271 m_gpuBuilt = false;
9272 m_gpuBuiltCommandCount = 0;
9273 valid = false;
9274
9275 if (m_rhi)
9276 m_rhi->unregisterResource(this);
9277}
9278
9280{
9281 // Either way the recorded commands go: they may not fit maxCommandCount()
9282 // or match type() anymore.
9283 if (valid)
9284 destroy();
9285 else
9286 clear();
9287
9288 if (!m_maxCommandCount) {
9289 qWarning("QRhiIndirectCommandBuffer: maxCommandCount is 0");
9290 return false;
9291 }
9292
9293 valid = true;
9294 m_rhi->registerResource(this);
9295 return true;
9296}
9297
9299{
9300 // m_gpuBuilt: the commands come from the source buffer from now on, so
9301 // there is nothing to upload, as documented for commitIndirectCommandBuffer().
9302 if (!valid || m_gpuBuilt || m_data.isEmpty() || uploadedGeneration == m_generation)
9303 return;
9304
9305 if (!buffer) {
9306 const quint32 commandSize = m_type == IndexedDraws ? sizeof(QRhiIndexedIndirectDrawCommand)
9307 : sizeof(QRhiIndirectDrawCommand);
9308 buffer = m_rhi->createBuffer(QRhiBuffer::Static, QRhiBuffer::IndirectBuffer,
9309 m_maxCommandCount * commandSize);
9310 if (!buffer || !buffer->create()) {
9311 delete buffer;
9312 buffer = nullptr;
9313 return;
9314 }
9315 }
9316
9317 u->uploadStaticBuffer(buffer, 0, quint32(m_data.size()), m_data.constData());
9318 uploadedGeneration = m_generation;
9319}
9320
9321void QRhiBufferBackedIndirectCommandBuffer::build(const QRhiIndirectCommandBufferBuildInfo &info)
9322{
9323 buildInfo = info;
9324 quint32 count = info.commandCount ? info.commandCount : m_maxCommandCount;
9325 if (count > m_maxCommandCount) {
9326 qWarning("QRhiIndirectCommandBuffer: buildIndirect() with commandCount %u exceeds "
9327 "maxCommandCount %u; clamping", count, m_maxCommandCount);
9328 count = m_maxCommandCount;
9329 }
9330 m_gpuBuilt = true;
9331 m_gpuBuiltCommandCount = count;
9332}
9333
9335 quint32 firstCommand,
9336 quint32 commandCount)
9337{
9338 const bool indexed = m_type == IndexedDraws;
9339 const quint32 canonicalStride = m_type == IndexedDraws ? sizeof(QRhiIndexedIndirectDrawCommand)
9340 : sizeof(QRhiIndirectDrawCommand);
9341
9342 if (m_gpuBuilt) {
9343 const quint32 stride = buildInfo.stride ? buildInfo.stride : canonicalStride;
9344 const quint32 available = m_gpuBuiltCommandCount > firstCommand
9345 ? m_gpuBuiltCommandCount - firstCommand : 0;
9346 const quint32 count = qMin(commandCount, available);
9347 if (!count)
9348 return;
9349 const quint32 offset = buildInfo.sourceBufferOffset + firstCommand * stride;
9350 if (buildInfo.countBuffer) {
9351 // Note that a non-zero firstCommand shifts the window, but the
9352 // device-side count is still relative to the start of that window.
9353 if (indexed) {
9354 cb->drawIndexedIndirectCount(buildInfo.sourceBuffer, offset,
9355 buildInfo.countBuffer, buildInfo.countBufferOffset,
9356 count, stride);
9357 } else {
9358 cb->drawIndirectCount(buildInfo.sourceBuffer, offset,
9359 buildInfo.countBuffer, buildInfo.countBufferOffset,
9360 count, stride);
9361 }
9362 } else {
9363 if (indexed)
9364 cb->drawIndexedIndirect(buildInfo.sourceBuffer, offset, count, stride);
9365 else
9366 cb->drawIndirect(buildInfo.sourceBuffer, offset, count, stride);
9367 }
9368 return;
9369 }
9370
9371 if (!buffer) {
9372 // Metal encodes on the spot in executeIndirect() and so needs no
9373 // commit. Everywhere else a missing one means drawing nothing.
9374 if (m_commandCount) {
9375 qWarning("QRhiIndirectCommandBuffer: %u command(s) recorded but never flushed with "
9376 "QRhiResourceUpdateBatch::commitIndirectCommandBuffer(); nothing to draw",
9377 m_commandCount);
9378 }
9379 return;
9380 }
9381 if (!m_commandCount)
9382 return;
9383
9384 const quint32 available = m_commandCount > firstCommand ? m_commandCount - firstCommand : 0;
9385 const quint32 count = qMin(commandCount, available);
9386 if (!count)
9387 return;
9388
9389 const quint32 offset = firstCommand * canonicalStride;
9390 if (indexed)
9391 cb->drawIndexedIndirect(buffer, offset, count, canonicalStride);
9392 else
9393 cb->drawIndirect(buffer, offset, count, canonicalStride);
9394}
9395
9396QRhiIndirectCommandBuffer *QRhiImplementation::createIndirectCommandBuffer(QRhiIndirectCommandBuffer::Type type,
9397 quint32 maxCommandCount)
9398{
9399 return new QRhiBufferBackedIndirectCommandBuffer(this, type, maxCommandCount);
9400}
9401
9402void QRhiImplementation::buildIndirect(QRhiCommandBuffer *cb, QRhiIndirectCommandBuffer *icb,
9403 const QRhiIndirectCommandBufferBuildInfo &info)
9404{
9405 Q_UNUSED(cb);
9406 static_cast<QRhiBufferBackedIndirectCommandBuffer *>(icb)->build(info);
9407}
9408
9409void QRhiImplementation::executeIndirect(QRhiCommandBuffer *cb, QRhiIndirectCommandBuffer *icb,
9410 quint32 firstCommand, quint32 commandCount)
9411{
9412 static_cast<QRhiBufferBackedIndirectCommandBuffer *>(icb)->execute(cb, firstCommand, commandCount);
9413}
9414
9415void QRhiImplementation::commitIndirectCommandBuffer(QRhiResourceUpdateBatch *u,
9416 QRhiIndirectCommandBuffer *icb)
9417{
9418 static_cast<QRhiBufferBackedIndirectCommandBuffer *>(icb)->enqueueUpload(u);
9419}
9420
9421/*!
9422 \class QRhiCommandBuffer
9423 \inmodule QtGuiPrivate
9424 \inheaderfile rhi/qrhi.h
9425 \since 6.6
9426 \brief Command buffer resource.
9427
9428 Not creatable by applications at the moment. The only ways to obtain a
9429 valid QRhiCommandBuffer are to get it from the targeted swapchain via
9430 QRhiSwapChain::currentFrameCommandBuffer(), or, in case of rendering
9431 completely offscreen, initializing one via QRhi::beginOffscreenFrame().
9432
9433 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9434 for details.
9435 */
9436
9437/*!
9438 \enum QRhiCommandBuffer::IndexFormat
9439 Specifies the index data type
9440
9441 \value IndexUInt16 Unsigned 16-bit (quint16)
9442 \value IndexUInt32 Unsigned 32-bit (quint32)
9443 */
9444
9445/*!
9446 \enum QRhiCommandBuffer::BeginPassFlag
9447 Flag values for QRhi::beginPass()
9448
9449 \value ExternalContent Specifies that there will be a call to
9450 QRhiCommandBuffer::beginExternal() in this pass. Some backends, Vulkan in
9451 particular, will fail if this flag is not set and beginExternal() is still
9452 called.
9453
9454 \value DoNotTrackResourcesForCompute Specifies that there is no need to
9455 track resources used in this pass if the only purpose of such tracking is
9456 to generate barriers for compute. Implies that there are no compute passes
9457 in the frame. This is an optimization hint that may be taken into account
9458 by certain backends, OpenGL in particular, allowing them to skip certain
9459 operations. When this flag is set for a render pass in a frame, calling
9460 \l{QRhiCommandBuffer::beginComputePass()}{beginComputePass()} in that frame
9461 may lead to unexpected behavior, depending on the resource dependencies
9462 between the render and compute passes.
9463 */
9464
9465/*!
9466 \typedef QRhiCommandBuffer::DynamicOffset
9467
9468 Synonym for std::pair<int, quint32>. The first entry is the binding, the second
9469 is the offset in the buffer.
9470*/
9471
9472/*!
9473 \typedef QRhiCommandBuffer::VertexInput
9474
9475 Synonym for std::pair<QRhiBuffer *, quint32>. The second entry is an offset in
9476 the buffer specified by the first.
9477*/
9478
9479/*!
9480 \internal
9481 */
9482QRhiCommandBuffer::QRhiCommandBuffer(QRhiImplementation *rhi)
9483 : QRhiResource(rhi)
9484{
9485}
9486
9487/*!
9488 \return the resource type.
9489 */
9490QRhiResource::Type QRhiCommandBuffer::resourceType() const
9491{
9492 return CommandBuffer;
9493}
9494
9495static const char *resourceTypeStr(const QRhiResource *res)
9496{
9497 switch (res->resourceType()) {
9498 case QRhiResource::Buffer:
9499 return "Buffer";
9500 case QRhiResource::Texture:
9501 return "Texture";
9502 case QRhiResource::Sampler:
9503 return "Sampler";
9504 case QRhiResource::RenderBuffer:
9505 return "RenderBuffer";
9506 case QRhiResource::RenderPassDescriptor:
9507 return "RenderPassDescriptor";
9508 case QRhiResource::SwapChainRenderTarget:
9509 return "SwapChainRenderTarget";
9510 case QRhiResource::TextureRenderTarget:
9511 return "TextureRenderTarget";
9512 case QRhiResource::ShaderResourceBindings:
9513 return "ShaderResourceBindings";
9514 case QRhiResource::GraphicsPipeline:
9515 return "GraphicsPipeline";
9516 case QRhiResource::SwapChain:
9517 return "SwapChain";
9518 case QRhiResource::ComputePipeline:
9519 return "ComputePipeline";
9520 case QRhiResource::CommandBuffer:
9521 return "CommandBuffer";
9522 case QRhiResource::ShadingRateMap:
9523 return "ShadingRateMap";
9524 case QRhiResource::IndirectCommandBuffer:
9525 return "IndirectCommandBuffer";
9526 }
9527
9528 Q_UNREACHABLE_RETURN("");
9529}
9530
9531QRhiImplementation::~QRhiImplementation()
9532{
9533 qDeleteAll(resUpdPool);
9534
9535 // Be nice and show something about leaked stuff. Though we may not get
9536 // this far with some backends where the allocator or the api may check
9537 // and freak out for unfreed graphics objects in the derived dtor already.
9538#ifndef QT_NO_DEBUG
9539 // debug builds: just do it always
9540 static bool leakCheck = true;
9541#else
9542 // release builds: opt-in
9543 static bool leakCheck = qEnvironmentVariableIntValue("QT_RHI_LEAK_CHECK");
9544#endif
9545 if (!resources.isEmpty()) {
9546 if (leakCheck) {
9547 qWarning("QRhi %p going down with %d unreleased resources that own native graphics objects. This is not nice.",
9548 q, int(resources.size()));
9549 }
9550 for (auto it = resources.cbegin(), end = resources.cend(); it != end; ++it) {
9551 QRhiResource *res = it.key();
9552 const bool ownsNativeResources = it.value();
9553 if (leakCheck && ownsNativeResources)
9554 qWarning(" %s resource %p (%s)", resourceTypeStr(res), res, res->m_objectName.constData());
9555
9556 // Null out the resource's rhi pointer. This is why it makes sense to do null
9557 // checks in the destroy() implementations of the various resource types. It
9558 // allows to survive in bad applications that somehow manage to destroy a
9559 // resource of a QRhi after the QRhi itself.
9560 res->m_rhi = nullptr;
9561 }
9562 }
9563}
9564
9565bool QRhiImplementation::isCompressedFormat(QRhiTexture::Format format) const
9566{
9567 return (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
9568 || (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
9569 || (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12);
9570}
9571
9572bool QRhiImplementation::compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
9573 quint32 *bpl, quint32 *byteSize,
9574 QSize *blockDim) const
9575{
9576 int xdim = 4;
9577 int ydim = 4;
9578 quint32 blockSize = 0;
9579
9580 switch (format) {
9581 case QRhiTexture::BC1:
9582 blockSize = 8;
9583 break;
9584 case QRhiTexture::BC2:
9585 blockSize = 16;
9586 break;
9587 case QRhiTexture::BC3:
9588 blockSize = 16;
9589 break;
9590 case QRhiTexture::BC4:
9591 blockSize = 8;
9592 break;
9593 case QRhiTexture::BC5:
9594 blockSize = 16;
9595 break;
9596 case QRhiTexture::BC6H:
9597 blockSize = 16;
9598 break;
9599 case QRhiTexture::BC7:
9600 blockSize = 16;
9601 break;
9602
9603 case QRhiTexture::ETC2_RGB8:
9604 blockSize = 8;
9605 break;
9606 case QRhiTexture::ETC2_RGB8A1:
9607 blockSize = 8;
9608 break;
9609 case QRhiTexture::ETC2_RGBA8:
9610 blockSize = 16;
9611 break;
9612
9613 case QRhiTexture::ASTC_4x4:
9614 blockSize = 16;
9615 break;
9616 case QRhiTexture::ASTC_5x4:
9617 blockSize = 16;
9618 xdim = 5;
9619 break;
9620 case QRhiTexture::ASTC_5x5:
9621 blockSize = 16;
9622 xdim = ydim = 5;
9623 break;
9624 case QRhiTexture::ASTC_6x5:
9625 blockSize = 16;
9626 xdim = 6;
9627 ydim = 5;
9628 break;
9629 case QRhiTexture::ASTC_6x6:
9630 blockSize = 16;
9631 xdim = ydim = 6;
9632 break;
9633 case QRhiTexture::ASTC_8x5:
9634 blockSize = 16;
9635 xdim = 8;
9636 ydim = 5;
9637 break;
9638 case QRhiTexture::ASTC_8x6:
9639 blockSize = 16;
9640 xdim = 8;
9641 ydim = 6;
9642 break;
9643 case QRhiTexture::ASTC_8x8:
9644 blockSize = 16;
9645 xdim = ydim = 8;
9646 break;
9647 case QRhiTexture::ASTC_10x5:
9648 blockSize = 16;
9649 xdim = 10;
9650 ydim = 5;
9651 break;
9652 case QRhiTexture::ASTC_10x6:
9653 blockSize = 16;
9654 xdim = 10;
9655 ydim = 6;
9656 break;
9657 case QRhiTexture::ASTC_10x8:
9658 blockSize = 16;
9659 xdim = 10;
9660 ydim = 8;
9661 break;
9662 case QRhiTexture::ASTC_10x10:
9663 blockSize = 16;
9664 xdim = ydim = 10;
9665 break;
9666 case QRhiTexture::ASTC_12x10:
9667 blockSize = 16;
9668 xdim = 12;
9669 ydim = 10;
9670 break;
9671 case QRhiTexture::ASTC_12x12:
9672 blockSize = 16;
9673 xdim = ydim = 12;
9674 break;
9675
9676 default:
9677 Q_UNREACHABLE();
9678 break;
9679 }
9680
9681 const quint32 wblocks = quint32((qint64(qMax(0, size.width())) + xdim - 1) / xdim);
9682 const quint32 hblocks = quint32((qint64(qMax(0, size.height())) + ydim - 1) / ydim);
9683
9684 if (blockDim)
9685 *blockDim = QSize(xdim, ydim);
9686
9687 // Compute in 64-bit, as safety for extreme geometry that would not fit.
9688 // wblocks and hblocks are at most 2^29 and blockSize at most 16.
9689 const quint64 bytesPerLine = quint64(wblocks) * quint64(blockSize);
9690 const quint64 totalSize = quint64(wblocks) * quint64(hblocks) * quint64(blockSize);
9691 if (bytesPerLine > std::numeric_limits<quint32>::max()
9692 || totalSize > std::numeric_limits<quint32>::max())
9693 {
9694 qWarning("Compressed texture of size %dx%d with format %d has a byte size of %llu "
9695 "which is too large to be handled",
9696 size.width(), size.height(), int(format), totalSize);
9697 if (bpl)
9698 *bpl = 0;
9699 if (byteSize)
9700 *byteSize = 0;
9701 return false;
9702 }
9703
9704 if (bpl)
9705 *bpl = quint32(bytesPerLine);
9706 if (byteSize)
9707 *byteSize = quint32(totalSize);
9708
9709 return true;
9710}
9711
9712bool QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSize &size,
9713 quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const
9714{
9715 if (isCompressedFormat(format))
9716 return compressedFormatInfo(format, size, bpl, byteSize, nullptr);
9717
9718 quint32 bpc = 0;
9719 switch (format) {
9720 case QRhiTexture::RGBA8:
9721 bpc = 4;
9722 break;
9723 case QRhiTexture::BGRA8:
9724 bpc = 4;
9725 break;
9726 case QRhiTexture::R8:
9727 bpc = 1;
9728 break;
9729 case QRhiTexture::RG8:
9730 bpc = 2;
9731 break;
9732 case QRhiTexture::R16:
9733 bpc = 2;
9734 break;
9735 case QRhiTexture::RG16:
9736 bpc = 4;
9737 break;
9738 case QRhiTexture::RED_OR_ALPHA8:
9739 bpc = 1;
9740 break;
9741
9742 case QRhiTexture::RGBA16F:
9743 bpc = 8;
9744 break;
9745 case QRhiTexture::RGBA32F:
9746 bpc = 16;
9747 break;
9748 case QRhiTexture::R16F:
9749 bpc = 2;
9750 break;
9751 case QRhiTexture::R32F:
9752 bpc = 4;
9753 break;
9754
9755 case QRhiTexture::RGB10A2:
9756 bpc = 4;
9757 break;
9758
9759 case QRhiTexture::D16:
9760 bpc = 2;
9761 break;
9762 case QRhiTexture::D24:
9763 case QRhiTexture::D24S8:
9764 case QRhiTexture::D32F:
9765 bpc = 4;
9766 break;
9767
9768 case QRhiTexture::D32FS8:
9769 bpc = 8;
9770 break;
9771
9772 case QRhiTexture::R8SI:
9773 case QRhiTexture::R8UI:
9774 bpc = 1;
9775 break;
9776 case QRhiTexture::R32SI:
9777 case QRhiTexture::R32UI:
9778 bpc = 4;
9779 break;
9780 case QRhiTexture::RG32SI:
9781 case QRhiTexture::RG32UI:
9782 bpc = 8;
9783 break;
9784 case QRhiTexture::RGBA32SI:
9785 case QRhiTexture::RGBA32UI:
9786 bpc = 16;
9787 break;
9788
9789 default:
9790 Q_UNREACHABLE();
9791 break;
9792 }
9793
9794 const quint32 width = uint(qMax(0, size.width()));
9795 const quint32 height = uint(qMax(0, size.height()));
9796
9797 if (bytesPerPixel)
9798 *bytesPerPixel = bpc;
9799
9800 // Compute in 64-bit, as safety for extreme geometry that would not fit.
9801 const quint64 bytesPerLine = quint64(width) * quint64(bpc);
9802 const quint64 pixelCount = quint64(width) * quint64(height);
9803 if (bytesPerLine > std::numeric_limits<quint32>::max()
9804 || pixelCount > std::numeric_limits<quint32>::max() / bpc)
9805 {
9806 qWarning("Texture of size %dx%d with format %d has a byte size "
9807 "which is too large to be handled",
9808 size.width(), size.height(), int(format));
9809 if (bpl)
9810 *bpl = 0;
9811 if (byteSize)
9812 *byteSize = 0;
9813 return false;
9814 }
9815
9816 if (bpl)
9817 *bpl = quint32(bytesPerLine);
9818 if (byteSize)
9819 *byteSize = quint32(pixelCount * quint64(bpc));
9820
9821 return true;
9822}
9823
9824bool QRhiImplementation::isStencilSupportingFormat(QRhiTexture::Format format) const
9825{
9826 switch (format) {
9827 case QRhiTexture::D24S8:
9828 case QRhiTexture::D32FS8:
9829 return true;
9830 default:
9831 break;
9832 }
9833 return false;
9834}
9835
9836bool QRhiImplementation::sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps)
9837{
9838 if (ps->cbeginShaderStages() == ps->cendShaderStages()) {
9839 qWarning("Cannot build a graphics pipeline without any stages");
9840 return false;
9841 }
9842
9843 bool hasVertexStage = false;
9844 for (auto it = ps->cbeginShaderStages(), itEnd = ps->cendShaderStages(); it != itEnd; ++it) {
9845 if (!it->shader().isValid()) {
9846 qWarning("Empty shader passed to graphics pipeline");
9847 return false;
9848 }
9849 if (it->type() == QRhiShaderStage::Vertex)
9850 hasVertexStage = true;
9851 }
9852 if (!hasVertexStage) {
9853 qWarning("Cannot build a graphics pipeline without a vertex stage");
9854 return false;
9855 }
9856
9857 if (!ps->renderPassDescriptor()) {
9858 qWarning("Cannot build a graphics pipeline without a QRhiRenderPassDescriptor");
9859 return false;
9860 }
9861
9862 if (!ps->shaderResourceBindings()) {
9863 qWarning("Cannot build a graphics pipeline without QRhiShaderResourceBindings");
9864 return false;
9865 }
9866
9867 return true;
9868}
9869
9870bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb)
9871{
9872#ifndef QT_NO_DEBUG
9873 bool bindingsOk = true;
9874 const int CHECKED_BINDINGS_COUNT = 64;
9875 bool bindingSeen[CHECKED_BINDINGS_COUNT] = {};
9876 for (auto it = srb->cbeginBindings(), end = srb->cendBindings(); it != end; ++it) {
9877 const int binding = shaderResourceBindingData(*it)->binding;
9878 if (binding >= CHECKED_BINDINGS_COUNT)
9879 continue;
9880 if (binding < 0) {
9881 qWarning("Invalid binding number %d", binding);
9882 bindingsOk = false;
9883 continue;
9884 }
9885 switch (shaderResourceBindingData(*it)->type()) {
9886 case QRhiShaderResourceBinding::UniformBuffer:
9887 if (!bindingSeen[binding]) {
9888 bindingSeen[binding] = true;
9889 } else {
9890 qWarning("Uniform buffer duplicates an existing binding number %d", binding);
9891 bindingsOk = false;
9892 }
9893 break;
9894 case QRhiShaderResourceBinding::SampledTexture:
9895 if (!bindingSeen[binding]) {
9896 bindingSeen[binding] = true;
9897 } else {
9898 qWarning("Combined image sampler duplicates an existing binding number %d", binding);
9899 bindingsOk = false;
9900 }
9901 break;
9902 case QRhiShaderResourceBinding::Texture:
9903 if (!bindingSeen[binding]) {
9904 bindingSeen[binding] = true;
9905 } else {
9906 qWarning("Texture duplicates an existing binding number %d", binding);
9907 bindingsOk = false;
9908 }
9909 break;
9910 case QRhiShaderResourceBinding::Sampler:
9911 if (!bindingSeen[binding]) {
9912 bindingSeen[binding] = true;
9913 } else {
9914 qWarning("Sampler duplicates an existing binding number %d", binding);
9915 bindingsOk = false;
9916 }
9917 break;
9918 case QRhiShaderResourceBinding::ImageLoad:
9919 case QRhiShaderResourceBinding::ImageStore:
9920 case QRhiShaderResourceBinding::ImageLoadStore:
9921 if (!bindingSeen[binding]) {
9922 bindingSeen[binding] = true;
9923 } else {
9924 qWarning("Image duplicates an existing binding number %d", binding);
9925 bindingsOk = false;
9926 }
9927 break;
9928 case QRhiShaderResourceBinding::BufferLoad:
9929 case QRhiShaderResourceBinding::BufferStore:
9930 case QRhiShaderResourceBinding::BufferLoadStore:
9931 if (!bindingSeen[binding]) {
9932 bindingSeen[binding] = true;
9933 } else {
9934 qWarning("Buffer duplicates an existing binding number %d", binding);
9935 bindingsOk = false;
9936 }
9937 break;
9938 default:
9939 qWarning("Unknown binding type %d", int(shaderResourceBindingData(*it)->type()));
9940 bindingsOk = false;
9941 break;
9942 }
9943 }
9944
9945 if (!bindingsOk) {
9946 qWarning() << *srb;
9947 return false;
9948 }
9949#else
9950 Q_UNUSED(srb);
9951#endif
9952 return true;
9953}
9954
9955bool QRhiImplementation::sanityCheckResourceOwnership(QRhiResource *maybeResource)
9956{
9957 if (maybeResource == nullptr || maybeResource->m_rhi == nullptr)
9958 return true;
9959
9960 if (maybeResource->m_rhi->q != q) {
9961 qWarning("%s %p (%s) belongs to QRhi %p, but client code attempted to use it with QRhi %p. This is wrong.",
9962 resourceTypeStr(maybeResource),
9963 maybeResource,
9964 maybeResource->m_objectName.constData(),
9965 maybeResource->m_rhi->q,
9966 q);
9967 return false;
9968 }
9969
9970 return true;
9971}
9972
9973int QRhiImplementation::effectiveSampleCount(int sampleCount) const
9974{
9975 // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
9976 const int s = qBound(1, sampleCount, 64);
9977 const QList<int> supported = supportedSampleCounts();
9978 int result = 1;
9979
9980 // Stay compatible with Qt 5 in that requesting an unsupported sample count
9981 // is not an error (although we still do a categorized debug print about
9982 // this), and rather a supported value, preferably a close one, not just 1,
9983 // is used instead. This is actually deviating from Qt 5 as that performs a
9984 // clamping only and does not handle cases such as when sample count 2 is
9985 // not supported but 4 is. (OpenGL handles things like that gracefully,
9986 // other APIs may not, so improve this by picking the next largest, or in
9987 // absence of that, the largest value; this with the goal to not reduce
9988 // quality by rather picking a larger-than-requested value than a smaller one)
9989
9990 for (int i = 0, ie = supported.count(); i != ie; ++i) {
9991 // assumes the 'supported' list is sorted
9992 if (supported[i] >= s) {
9993 result = supported[i];
9994 break;
9995 }
9996 }
9997
9998 if (result != s) {
9999 if (result == 1 && !supported.isEmpty())
10000 result = supported.last();
10001 qCDebug(QRHI_LOG_INFO, "Attempted to set unsupported sample count %d, using %d instead",
10002 sampleCount, result);
10003 }
10004
10005 return result;
10006}
10007
10008/*!
10009 \internal
10010 */
10011QRhi::QRhi()
10012{
10013}
10014
10015/*!
10016 Destructor. Destroys the backend and releases resources.
10017 */
10018QRhi::~QRhi()
10019{
10020 if (!d)
10021 return;
10022
10023 if (qrhiDebugHooks.rhiAboutToBeDestroyed)
10024 qrhiDebugHooks.rhiAboutToBeDestroyed(d);
10025
10026 d->runCleanup();
10027
10028 qDeleteAll(d->pendingDeleteResources);
10029 d->pendingDeleteResources.clear();
10030
10031 d->destroy();
10032 delete d;
10033}
10034
10035QRhiImplementation *QRhiImplementation::newInstance(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *importDevice)
10036{
10037 QRhiImplementation *d = nullptr;
10038
10039 switch (impl) {
10040 case QRhi::Null:
10041 d = new QRhiNull(static_cast<QRhiNullInitParams *>(params));
10042 break;
10043 case QRhi::Vulkan:
10044#if QT_CONFIG(vulkan)
10045 d = new QRhiVulkan(static_cast<QRhiVulkanInitParams *>(params),
10046 static_cast<QRhiVulkanNativeHandles *>(importDevice));
10047 break;
10048#else
10049 Q_UNUSED(importDevice);
10050 qWarning("This build of Qt has no Vulkan support");
10051 break;
10052#endif
10053 case QRhi::OpenGLES2:
10054#ifndef QT_NO_OPENGL
10055 d = new QRhiGles2(static_cast<QRhiGles2InitParams *>(params),
10056 static_cast<QRhiGles2NativeHandles *>(importDevice));
10057 break;
10058#else
10059 qWarning("This build of Qt has no OpenGL support");
10060 break;
10061#endif
10062 case QRhi::D3D11:
10063#ifdef Q_OS_WIN
10064 d = new QRhiD3D11(static_cast<QRhiD3D11InitParams *>(params),
10065 static_cast<QRhiD3D11NativeHandles *>(importDevice));
10066 break;
10067#else
10068 qWarning("This platform has no Direct3D 11 support");
10069 break;
10070#endif
10071 case QRhi::Metal:
10072#if QT_CONFIG(metal)
10073 d = new QRhiMetal(static_cast<QRhiMetalInitParams *>(params),
10074 static_cast<QRhiMetalNativeHandles *>(importDevice));
10075 break;
10076#else
10077 qWarning("This platform has no Metal support");
10078 break;
10079#endif
10080 case QRhi::D3D12:
10081#ifdef Q_OS_WIN
10082#ifdef QRHI_D3D12_AVAILABLE
10083 d = new QRhiD3D12(static_cast<QRhiD3D12InitParams *>(params),
10084 static_cast<QRhiD3D12NativeHandles *>(importDevice));
10085 break;
10086#else
10087 qWarning("Qt was built without Direct3D 12 support. "
10088 "This is likely due to having ancient SDK headers (such as d3d12.h) in the Qt build environment. "
10089 "Rebuild Qt with an SDK supporting D3D12 features introduced in Windows 10 version 1703, "
10090 "or use an MSVC build as those typically are built with more up-to-date SDKs.");
10091 break;
10092#endif
10093#else
10094 qWarning("This platform has no Direct3D 12 support");
10095 break;
10096#endif
10097 }
10098
10099 return d;
10100}
10101
10102void QRhiImplementation::prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags, QRhiAdapter *adapter)
10103{
10104 q = rhi;
10105
10106 debugMarkers = flags.testFlag(QRhi::EnableDebugMarkers);
10107 timestamps = flags.testFlag(QRhi::EnableTimestamps);
10108
10109 implType = impl;
10110 implThread = QThread::currentThread();
10111
10112 requestedRhiAdapter = adapter;
10113}
10114
10115QRhi::AdapterList QRhiImplementation::enumerateAdaptersBeforeCreate(QRhiNativeHandles *) const
10116{
10117 return {};
10118}
10119
10120/*!
10121 \overload
10122
10123 Equivalent to create(\a impl, \a params, \a flags, \a importDevice, \c nullptr).
10124 */
10125QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice)
10126{
10127 return create(impl, params, flags, importDevice, nullptr);
10128}
10129
10130/*!
10131 \return a new QRhi instance with a backend for the graphics API specified
10132 by \a impl with the specified \a flags. \return \c nullptr if the
10133 function fails.
10134
10135 \a params must point to an instance of one of the backend-specific
10136 subclasses of QRhiInitParams, such as, QRhiVulkanInitParams,
10137 QRhiMetalInitParams, QRhiD3D11InitParams, QRhiD3D12InitParams,
10138 QRhiGles2InitParams. See these classes for examples on creating a QRhi.
10139
10140 QRhi by design does not implement any fallback logic: if the specified API
10141 cannot be initialized, create() will fail, with warnings printed on the
10142 debug output by the backends. The clients of QRhi, for example Qt Quick,
10143 may however provide additional logic that allow falling back to an API
10144 different than what was requested, depending on the platform. If the
10145 intention is just to test if initialization would succeed when calling
10146 create() at later point, it is preferable to use probe() instead of
10147 create(), because with some backends probing can be implemented in a more
10148 lightweight manner as opposed to create(), which performs full
10149 initialization of the infrastructure and is wasteful if that QRhi instance
10150 is then thrown immediately away.
10151
10152 \a importDevice allows using an already existing graphics device, without
10153 QRhi creating its own. When not null, this parameter must point to an
10154 instance of one of the subclasses of QRhiNativeHandles:
10155 QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles,
10156 QRhiMetalNativeHandles, QRhiGles2NativeHandles. The exact details and
10157 semantics depend on the backand and the underlying graphics API.
10158
10159 Specifying a QRhiAdapter in \a adapter offers a transparent, cross-API
10160 alternative to passing in a \c VkPhysicalDevice via QRhiVulkanNativeHandles,
10161 or an adapter LUID via QRhiD3D12NativeHandles. The ownership of \a adapter
10162 is not taken. See enumerateAdapters() for more information on this approach.
10163
10164 \note \a importDevice and \a adapter cannot be both specified.
10165
10166 \sa probe()
10167 */
10168QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice, QRhiAdapter *adapter)
10169{
10170 if (adapter && importDevice)
10171 qWarning("adapter and importDevice should not both be non-null in QRhi::create()");
10172
10173 std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, importDevice));
10174 if (!rd)
10175 return nullptr;
10176
10177 std::unique_ptr<QRhi> r(new QRhi);
10178 r->d = rd.release();
10179 r->d->prepareForCreate(r.get(), impl, flags, adapter);
10180 if (!r->d->create(flags))
10181 return nullptr;
10182
10183 return r.release();
10184}
10185
10186/*!
10187 \return true if create() can be expected to succeed when called the given
10188 \a impl and \a params.
10189
10190 For some backends this is equivalent to calling create(), checking its
10191 return value, and then destroying the resulting QRhi.
10192
10193 For others, in particular with Metal, there may be a specific probing
10194 implementation, which allows testing in a more lightweight manner without
10195 polluting the debug output with warnings upon failures.
10196
10197 \sa create()
10198 */
10199bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)
10200{
10201 bool ok = false;
10202
10203 // The only place currently where this makes sense is Metal, where the API
10204 // is simple enough so that a special probing function - doing nothing but
10205 // a MTLCreateSystemDefaultDevice - is reasonable. Elsewhere, just call
10206 // create() and then drop the result.
10207
10208 if (impl == Metal) {
10209#if QT_CONFIG(metal)
10210 ok = QRhiMetal::probe(static_cast<QRhiMetalInitParams *>(params));
10211#endif
10212 } else {
10213 QRhi *rhi = create(impl, params);
10214 ok = rhi != nullptr;
10215 delete rhi;
10216 }
10217 return ok;
10218}
10219
10220/*!
10221 \typedef QRhi::AdapterList
10222 \relates QRhi
10223 \since 6.10
10224
10225 Synonym for QVector<QRhiAdapter *>.
10226*/
10227
10228/*!
10229 \return the list of adapters (physical devices) present, or an empty list
10230 when such control is not available with a given graphics API.
10231
10232 Backends where such level of control is not available, the returned list is
10233 always empty. Thus an empty list does not indicate there are no graphics
10234 devices in the system, but that fine-grained control over selecting which
10235 one to use is not available.
10236
10237 Backends for Direct 3D 11, Direct 3D 12, and Vulkan can be expected to fully
10238 support enumerating adapters. Others may not. The backend is specified by \a
10239 impl. A QRhiAdapter returned from this function must only be used in a
10240 create() call with the same \a impl. Some underlying APIs may present
10241 further limitations, with Vulkan in particular the QRhiAdapter is specified
10242 to the QVulkanInstance (\c VkInstance).
10243
10244 The caller is expected to destroy the QRhiAdapter objects in the list. Apart
10245 from querying \l{QRhiAdapter::}{info()}, the only purpose of these objects is
10246 to be passed on to create(), or the corresponding functions in higher layers
10247 such as Qt Quick.
10248
10249 The following snippet, written specifically for Vulkan, shows how to
10250 enumerate the available physical devices and request to create a QRhi for
10251 the chosen one. This in practice is equivalent to passing in a \c
10252 VkPhysicalDevice via a QRhiVulkanNativeHandles to create(), but it involves
10253 less API-specific code on the application side:
10254
10255 \code
10256 QRhiVulkanInitParams initParams;
10257 initParams.inst = &vulkanInstance;
10258 QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::Vulkan, &initParams);
10259 QRhiAdapter *chosenAdapter = nullptr;
10260 for (QRhiAdapter *adapter : adapters) {
10261 if (looksGood(adapter->info())) {
10262 chosenAdapter = adapter;
10263 break;
10264 }
10265 }
10266 QRhi *rhi = QRhi::create(QRhi::Vulkan, &initParams, {}, nullptr, chosenAdapter);
10267 qDeleteAll(adapters);
10268 \endcode
10269
10270 Passing in \a params is required due to some of the underlying graphics
10271 APIs' design. With Vulkan in particular, the QVulkanInstance must be
10272 provided, since enumerating is not possible without it. Other fields in the
10273 backend-specific \a params will not actually be used by this function.
10274
10275 \a nativeHandles is optional. When specified, it must be a valid
10276 QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, or QRhiVulkanNativeHandles,
10277 similarly to create(). However, unlike create(), only the physical device
10278 (in case of Vulkan) or the adapter LUID (in case of D3D) fields are used,
10279 all other fields are ignored. This can be used the restrict the results to a
10280 given adapter. The returned list will contain 1 or 0 elements in this case.
10281
10282 Note how in the previous code snippet the looksGood() function
10283 implementation cannot perform any platform-specific filtering based on the
10284 true adapter / physical device identity, such as the adapter LUID on Windows
10285 or the VkPhysicalDevice with Vulkan. This is because QRhiDriverInfo does not
10286 contain platform-specific data. Instead, use \a nativeHandles to get the
10287 results filtered already inside enumerateAdapters().
10288
10289 The following two snippets, using Direct 3D 12 as an example, are equivalent
10290 in practice:
10291
10292 \code
10293 // enumerateAdapters-based approach from Qt 6.10 on
10294 QRhiD3D12InitParams initParams;
10295 QRhiD3D12NativeHandles nativeHandles;
10296 nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
10297 nativeHandles.adapterLuidHigh = luid.HighPart;
10298 QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::D3D12, &initParams, &nativeHandles);
10299 if (adapters.isEmpty()) { qWarning("Requested adapter was not found"); }
10300 QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, nullptr, adapters[0]);
10301 qDeleteAll(adapters);
10302 \endcode
10303
10304 \code
10305 // traditional approach, more lightweight
10306 QRhiD3D12InitParams initParams;
10307 QRhiD3D12NativeHandles nativeHandles;
10308 nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
10309 nativeHandles.adapterLuidHigh = luid.HighPart;
10310 QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, &nativeHandles, nullptr);
10311 \endcode
10312
10313 \since 6.10
10314 \sa create()
10315 */
10316QRhi::AdapterList QRhi::enumerateAdapters(Implementation impl, QRhiInitParams *params, QRhiNativeHandles *nativeHandles)
10317{
10318 std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, nullptr));
10319 if (!rd)
10320 return {};
10321
10322 return rd->enumerateAdaptersBeforeCreate(nativeHandles);
10323}
10324
10325/*!
10326 \struct QRhiSwapChainProxyData
10327 \inmodule QtGuiPrivate
10328 \inheaderfile rhi/qrhi.h
10329 \since 6.6
10330
10331 \brief Opaque data describing native objects needed to set up a swapchain.
10332
10333 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10334 for details.
10335
10336 \sa QRhi::updateSwapChainProxyData()
10337 */
10338
10339/*!
10340 Generates and returns a QRhiSwapChainProxyData struct containing opaque
10341 data specific to the backend and graphics API specified by \a impl. \a
10342 window is the QWindow a swapchain is targeting.
10343
10344 The returned struct can be passed to QRhiSwapChain::setProxyData(). This
10345 makes sense in threaded rendering systems: this static function is expected
10346 to be called on the \b{main (gui) thread}, unlike all QRhi operations, then
10347 transferred to the thread working with the QRhi and QRhiSwapChain and passed
10348 on to the swapchain. This allows doing native platform queries that are
10349 only safe to be called on the main thread, for example to query the
10350 CAMetalLayer from a NSView, and then passing on the data to the
10351 QRhiSwapChain living on the rendering thread. With the Metal example, doing
10352 the view.layer access on a dedicated rendering thread causes a warning in
10353 the Xcode Thread Checker. With the data proxy mechanism, this is avoided.
10354
10355 When threads are not involved, generating and passing on the
10356 QRhiSwapChainProxyData is not required: backends are guaranteed to be able
10357 to query whatever is needed on their own, and if everything lives on the
10358 main (gui) thread, that should be sufficient.
10359
10360 \note \a impl should match what the QRhi is created with. For example,
10361 calling with QRhi::Metal on a non-Apple platform will not generate any
10362 useful data.
10363 */
10364QRhiSwapChainProxyData QRhi::updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)
10365{
10366#if QT_CONFIG(metal)
10367 if (impl == Metal)
10368 return QRhiMetal::updateSwapChainProxyData(window);
10369#else
10370 Q_UNUSED(impl);
10371 Q_UNUSED(window);
10372#endif
10373 return {};
10374}
10375
10376/*!
10377 \return the backend type for this QRhi.
10378 */
10379QRhi::Implementation QRhi::backend() const
10380{
10381 return d->implType;
10382}
10383
10384/*!
10385 \return a friendly name for the backend \a impl, usually the name of the 3D
10386 API in use.
10387 */
10388const char *QRhi::backendName(Implementation impl)
10389{
10390 switch (impl) {
10391 case QRhi::Null:
10392 return "Null";
10393 case QRhi::Vulkan:
10394 return "Vulkan";
10395 case QRhi::OpenGLES2:
10396 return "OpenGL";
10397 case QRhi::D3D11:
10398 return "D3D11";
10399 case QRhi::Metal:
10400 return "Metal";
10401 case QRhi::D3D12:
10402 return "D3D12";
10403 }
10404
10405 Q_UNREACHABLE_RETURN("Unknown");
10406}
10407
10408/*!
10409 \return the backend type as string for this QRhi.
10410 */
10411const char *QRhi::backendName() const
10412{
10413 return backendName(d->implType);
10414}
10415
10416/*!
10417 \enum QRhiDriverInfo::DeviceType
10418 Specifies the graphics device's type, when the information is available.
10419
10420 In practice this is only applicable with Vulkan and Metal. With Direct 3D
10421 11 and 12, using an adapter with the software flag set leads to the value
10422 \c CpuDevice. Otherwise, and with OpenGL, the value is always UnknownDevice.
10423
10424 \value UnknownDevice
10425 \value IntegratedDevice
10426 \value DiscreteDevice
10427 \value ExternalDevice
10428 \value VirtualDevice
10429 \value CpuDevice
10430*/
10431
10432/*!
10433 \struct QRhiDriverInfo
10434 \inmodule QtGuiPrivate
10435 \inheaderfile rhi/qrhi.h
10436 \since 6.6
10437
10438 \brief Describes the physical device, adapter, or graphics API
10439 implementation that is used by an initialized QRhi.
10440
10441 Graphics APIs offer different levels and kinds of information. The only
10442 value that is available across all APIs is the deviceName, which is a
10443 freetext description of the physical device, adapter, or is a combination
10444 of the strings reported for \c{GL_VENDOR} + \c{GL_RENDERER} +
10445 \c{GL_VERSION}. The deviceId is always 0 for OpenGL. vendorId is always 0
10446 for OpenGL and Metal. deviceType is always UnknownDevice for OpenGL and
10447 Direct 3D.
10448
10449 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10450 for details.
10451 */
10452
10453/*!
10454 \variable QRhiDriverInfo::deviceName
10455
10456 \sa QRhi::driverInfo()
10457*/
10458
10459/*!
10460 \variable QRhiDriverInfo::deviceId
10461
10462 \sa QRhi::driverInfo()
10463*/
10464
10465/*!
10466 \variable QRhiDriverInfo::vendorId
10467
10468 \sa QRhi::driverInfo()
10469*/
10470
10471/*!
10472 \variable QRhiDriverInfo::deviceType
10473
10474 \sa QRhi::driverInfo(), QRhiDriverInfo::DeviceType
10475*/
10476
10477#ifndef QT_NO_DEBUG_STREAM
10478static inline const char *deviceTypeStr(QRhiDriverInfo::DeviceType type)
10479{
10480 switch (type) {
10481 case QRhiDriverInfo::UnknownDevice:
10482 return "Unknown";
10483 case QRhiDriverInfo::IntegratedDevice:
10484 return "Integrated";
10485 case QRhiDriverInfo::DiscreteDevice:
10486 return "Discrete";
10487 case QRhiDriverInfo::ExternalDevice:
10488 return "External";
10489 case QRhiDriverInfo::VirtualDevice:
10490 return "Virtual";
10491 case QRhiDriverInfo::CpuDevice:
10492 return "Cpu";
10493 }
10494
10495 Q_UNREACHABLE_RETURN(nullptr);
10496}
10497QDebug operator<<(QDebug dbg, const QRhiDriverInfo &info)
10498{
10499 QDebugStateSaver saver(dbg);
10500 dbg.nospace() << "QRhiDriverInfo(deviceName=" << info.deviceName
10501 << " deviceId=0x" << Qt::hex << info.deviceId
10502 << " vendorId=0x" << info.vendorId
10503 << " deviceType=" << deviceTypeStr(info.deviceType)
10504 << ')';
10505 return dbg;
10506}
10507#endif
10508
10509/*!
10510 \return metadata for the graphics device used by this successfully
10511 initialized QRhi instance.
10512 */
10513QRhiDriverInfo QRhi::driverInfo() const
10514{
10515 return d->driverInfo();
10516}
10517
10518/*!
10519 \class QRhiAdapter
10520 \inmodule QtGuiPrivate
10521 \inheaderfile rhi/qrhi.h
10522 \since 6.10
10523
10524 \brief Represents a physical graphics device.
10525
10526 Some QRhi backends target graphics APIs that expose the concept of \c
10527 adapters or \c{physical devices}. Call the static \l
10528 {QRhi::}{enumerateAdapters()} function to retrieve a list of the adapters
10529 present in the system. Pass one of the returned QRhiAdapter objects to \l
10530 {QRhi::}{create()} in order to request using the adapter or physical device
10531 the QRhiAdapter corresponds to. Other than exposing the QRhiDriverInfo,
10532 QRhiAdapter is to be treated as an opaque handle.
10533
10534 \note With Vulkan, the QRhiAdapter is valid only as long as the
10535 QVulkanInstance that was used for \l{QRhi::}{enumerateAdapters()} is valid.
10536 This also means that a QRhiAdapter is tied to the Vulkan instance
10537 (QVulkanInstance, \c VkInstance) and cannot be used in the context of
10538 another Vulkan instance.
10539
10540 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10541 for details.
10542 */
10543
10544/*!
10545 \fn virtual QRhiDriverInfo QRhiAdapter::info() const = 0
10546
10547 \return the corresponding QRhiDriverInfo.
10548 */
10549
10550/*!
10551 \internal
10552 */
10553QRhiAdapter::~QRhiAdapter()
10554{
10555}
10556
10557/*!
10558 \return the thread on which the QRhi was \l{QRhi::create()}{initialized}.
10559 */
10560QThread *QRhi::thread() const
10561{
10562 return d->implThread;
10563}
10564
10565/*!
10566 Registers a \a callback that is invoked when the QRhi is destroyed.
10567
10568 The callback will run with the graphics resource still available, so this
10569 provides an opportunity for the application to cleanly release QRhiResource
10570 instances belonging to the QRhi. This is particularly useful for managing
10571 the lifetime of resources stored in \c cache type of objects, where the
10572 cache holds QRhiResources or objects containing QRhiResources.
10573
10574 \sa ~QRhi()
10575 */
10576void QRhi::addCleanupCallback(const CleanupCallback &callback)
10577{
10578 d->addCleanupCallback(callback);
10579}
10580
10581/*!
10582 \overload
10583
10584 Registers \a callback to be invoked when the QRhi is destroyed. This
10585 overload takes an opaque pointer, \a key, that is used to ensure that a
10586 given callback is registered (and so called) only once.
10587
10588 \sa removeCleanupCallback()
10589 */
10590void QRhi::addCleanupCallback(const void *key, const CleanupCallback &callback)
10591{
10592 d->addCleanupCallback(key, callback);
10593}
10594
10595/*!
10596 Deregisters the callback with \a key. If no cleanup callback was registered
10597 with \a key, the function does nothing. Callbacks registered without a key
10598 cannot be removed.
10599
10600 \sa addCleanupCallback()
10601 */
10602void QRhi::removeCleanupCallback(const void *key)
10603{
10604 d->removeCleanupCallback(key);
10605}
10606
10607void QRhiImplementation::runCleanup()
10608{
10609 for (const QRhi::CleanupCallback &f : std::as_const(cleanupCallbacks))
10610 f(q);
10611
10612 cleanupCallbacks.clear();
10613
10614 for (auto it = keyedCleanupCallbacks.cbegin(), end = keyedCleanupCallbacks.cend(); it != end; ++it)
10615 it.value()(q);
10616
10617 keyedCleanupCallbacks.clear();
10618}
10619
10620/*!
10621 \class QRhiResourceUpdateBatch
10622 \inmodule QtGuiPrivate
10623 \inheaderfile rhi/qrhi.h
10624 \since 6.6
10625 \brief Records upload and copy type of operations.
10626
10627 With QRhi it is no longer possible to perform copy type of operations at
10628 arbitrary times. Instead, all such operations are recorded into batches
10629 that are then passed, most commonly, to QRhiCommandBuffer::beginPass().
10630 What then happens under the hood is hidden from the application: the
10631 underlying implementations can defer and implement these operations in
10632 various different ways.
10633
10634 A resource update batch owns no graphics resources and does not perform any
10635 actual operations on its own. It should rather be viewed as a command
10636 buffer for update, upload, and copy type of commands.
10637
10638 To get an available, empty batch from the pool, call
10639 QRhi::nextResourceUpdateBatch().
10640
10641 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10642 for details.
10643 */
10644
10645/*!
10646 \internal
10647 */
10648QRhiResourceUpdateBatch::QRhiResourceUpdateBatch(QRhiImplementation *rhi)
10649 : d(new QRhiResourceUpdateBatchPrivate)
10650{
10651 d->q = this;
10652 d->rhi = rhi;
10653}
10654
10655QRhiResourceUpdateBatch::~QRhiResourceUpdateBatch()
10656{
10657 delete d;
10658}
10659
10660/*!
10661 \return the batch to the pool. This should only be used when the batch is
10662 not passed to one of QRhiCommandBuffer::beginPass(),
10663 QRhiCommandBuffer::endPass(), or QRhiCommandBuffer::resourceUpdate()
10664 because these implicitly call destroy().
10665
10666 \note QRhiResourceUpdateBatch instances must never by \c deleted by
10667 applications.
10668 */
10669void QRhiResourceUpdateBatch::release()
10670{
10671 d->free();
10672}
10673
10674/*!
10675 Copies all queued operations from the \a other batch into this one.
10676
10677 \note \a other may no longer contain valid data after the merge operation,
10678 and must not be submitted, but it will still need to be released by calling
10679 release().
10680
10681 This allows for a convenient pattern where resource updates that are
10682 already known during the initialization step are collected into a batch
10683 that is then merged into another when starting to first render pass later
10684 on:
10685
10686 \code
10687 void init()
10688 {
10689 initialUpdates = rhi->nextResourceUpdateBatch();
10690 initialUpdates->uploadStaticBuffer(vbuf, vertexData);
10691 initialUpdates->uploadStaticBuffer(ibuf, indexData);
10692 // ...
10693 }
10694
10695 void render()
10696 {
10697 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
10698 if (initialUpdates) {
10699 resUpdates->merge(initialUpdates);
10700 initialUpdates->release();
10701 initialUpdates = nullptr;
10702 }
10703 // resUpdates->updateDynamicBuffer(...);
10704 cb->beginPass(rt, clearCol, clearDs, resUpdates);
10705 }
10706 \endcode
10707 */
10708void QRhiResourceUpdateBatch::merge(QRhiResourceUpdateBatch *other)
10709{
10710 d->merge(other->d);
10711}
10712
10713/*!
10714 \return true until the number of buffer and texture operations enqueued
10715 onto this batch is below a reasonable limit.
10716
10717 The return value is false when the number of buffer and/or texture
10718 operations added to this batch have reached, or are about to reach, a
10719 certain limit. The batch is fully functional afterwards as well, but may
10720 need to allocate additional memory. Therefore, a renderer that collects
10721 lots of buffer and texture updates in a single batch when preparing a frame
10722 may want to consider \l{QRhiCommandBuffer::resourceUpdate()}{submitting the
10723 batch} and \l{QRhi::nextResourceUpdateBatch()}{starting a new one} when
10724 this function returns false.
10725 */
10726bool QRhiResourceUpdateBatch::hasOptimalCapacity() const
10727{
10728 return d->hasOptimalCapacity();
10729}
10730
10731/*!
10732 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10733 QRhiBuffer::Dynamic.
10734
10735 The region is specified \a offset and \a size. The actual bytes to write
10736 are specified by \a data which must have at least \a size bytes available.
10737
10738 \a data is copied and can safely be destroyed or changed once this function
10739 returns.
10740
10741 \note If host writes are involved, which is the case with
10742 updateDynamicBuffer() typically as such buffers are backed by host visible
10743 memory with most backends, they may accumulate within a frame. Thus pass 1
10744 reading a region changed by a batch passed to pass 2 may see the changes
10745 specified in pass 2's update batch.
10746
10747 \note QRhi transparently manages double buffering in order to prevent
10748 stalling the graphics pipeline. The fact that a QRhiBuffer may have
10749 multiple native buffer objects underneath can be safely ignored when using
10750 the QRhi and QRhiResourceUpdateBatch.
10751 */
10752void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
10753{
10754 if (size > 0) {
10755 const int idx = d->activeBufferOpCount++;
10756 const int opListSize = d->bufferOps.size();
10757 if (idx < opListSize)
10758 QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, size, data);
10759 else
10760 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, size, data));
10761 }
10762}
10763
10764/*!
10765 \overload
10766 \since 6.10
10767
10768 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10769 QRhiBuffer::Dynamic.
10770
10771 \a data is moved into the batch instead of copied with this overload.
10772 */
10773void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
10774{
10775 if (!data.isEmpty()) {
10776 const int idx = d->activeBufferOpCount++;
10777 const int opListSize = d->bufferOps.size();
10778 if (idx < opListSize)
10779 QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, std::move(data));
10780 else
10781 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, std::move(data)));
10782 }
10783}
10784
10785/*!
10786 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10787 QRhiBuffer::Immutable or QRhiBuffer::Static.
10788
10789 The region is specified \a offset and \a size. The actual bytes to write
10790 are specified by \a data which must have at least \a size bytes available.
10791
10792 \a data is copied and can safely be destroyed or changed once this function
10793 returns.
10794
10795 \note Whether the upload is performed on the GPU timeline, and so is ordered
10796 against the other operations recorded in the same batch, is indicated by the
10797 \l QRhi::StaticBuffersOnGpuTimeline feature. This only matters when
10798 combining uploads with
10799 \l{QRhiResourceUpdateBatch::copyBuffer()}{copyBuffer()} on the same buffer.
10800
10801 \sa copyBuffer()
10802 */
10803void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
10804{
10805 if (size > 0) {
10806 const int idx = d->activeBufferOpCount++;
10807 if (idx < d->bufferOps.size())
10808 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, size, data);
10809 else
10810 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, size, data));
10811 }
10812}
10813
10814/*!
10815 \overload
10816 \since 6.10
10817
10818 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10819 QRhiBuffer::Immutable or QRhiBuffer::Static.
10820
10821 \a data is moved into the batch instead of copied with this overload.
10822 */
10823void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
10824{
10825 if (!data.isEmpty()) {
10826 const int idx = d->activeBufferOpCount++;
10827 if (idx < d->bufferOps.size())
10828 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, std::move(data));
10829 else
10830 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, std::move(data)));
10831 }
10832}
10833
10834/*!
10835 \overload
10836
10837 Enqueues updating the entire QRhiBuffer \a buf created with the type
10838 QRhiBuffer::Immutable or QRhiBuffer::Static.
10839 */
10840void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *data)
10841{
10842 if (buf->size() > 0) {
10843 const int idx = d->activeBufferOpCount++;
10844 if (idx < d->bufferOps.size())
10845 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, 0, data);
10846 else
10847 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, 0, data));
10848 }
10849}
10850
10851/*!
10852 \overload
10853 \since 6.10
10854
10855 Enqueues updating the entire QRhiBuffer \a buf created with the type
10856 QRhiBuffer::Immutable or QRhiBuffer::Static.
10857
10858 \a data is moved into the batch instead of copied with this overload.
10859
10860 \a data size must equal the size of \a buf.
10861 */
10862void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, QByteArray data)
10863{
10864 if (buf->size() > 0 && quint32(data.size()) == buf->size()) {
10865 const int idx = d->activeBufferOpCount++;
10866 if (idx < d->bufferOps.size())
10867 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, std::move(data));
10868 else
10869 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, std::move(data)));
10870 }
10871}
10872
10873/*!
10874 Enqueues reading back a region of the QRhiBuffer \a buf. The size of the
10875 region is specified by \a size in bytes, \a offset is the offset in bytes
10876 to start reading from.
10877
10878 A readback is asynchronous. \a result contains a callback that is invoked
10879 when the operation has completed. The data is provided in
10880 QRhiReadbackResult::data. Upon successful completion that QByteArray
10881 will have a size equal to \a size. On failure the QByteArray will be empty.
10882
10883 \note Reading buffers with a usage different than QRhiBuffer::UniformBuffer
10884 is supported only when the QRhi::ReadBackNonUniformBuffer feature is
10885 reported as supported.
10886
10887 \note The asynchronous readback is guaranteed to have completed when one of
10888 the following conditions is met: \l{QRhi::finish()}{finish()} has been
10889 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
10890 including the frame that issued the readback operation, and the
10891 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
10892 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
10893 QRhi::MaxAsyncReadbackFrames.
10894
10895 \sa readBackTexture(), QRhi::isFeatureSupported(), QRhi::resourceLimit()
10896 */
10897void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
10898{
10899 const int idx = d->activeBufferOpCount++;
10900 if (idx < d->bufferOps.size())
10901 d->bufferOps[idx] = QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result);
10902 else
10903 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result));
10904}
10905
10906/*!
10907 Enqueues a buffer-to-buffer copy operation from \a src into \a dst as
10908 described by \a desc.
10909
10910 The copy is performed on the GPU, without involving the CPU. This is the
10911 preferred way of moving data between two non-Dynamic QRhiBuffer objects.
10912
10913 Availability is indicated by the \l QRhi::BufferToBufferCopy feature. When
10914 that is reported as not supported, which in practice means OpenGL ES 2.0 and
10915 old desktop OpenGL versions, calling this function has no effect.
10916
10917 A \l{QRhiBufferCopyDescription::size()}{size} of 0 in \a desc, which is what
10918 a default constructed description has, means the entire \a src buffer. Watch
10919 out for this when \a dst is smaller than \a src, because the copy then does
10920 not fit and gets dropped, as described below.
10921
10922 \note Neither buffer can be of the type QRhiBuffer::Dynamic, and neither can
10923 have QRhiBuffer::UniformBuffer usage. With some of the underlying 3D APIs
10924 such buffers are backed by host visible memory, or are not real GPU buffers
10925 at all, and so cannot take part in a GPU-side copy.
10926
10927 \note The size and offsets in \a desc should all be multiples of 4. This is a
10928 requirement of the blit encoder in Metal, and it applies on macOS on
10929 Intel-based devices. Other platforms and 3D APIs, including Metal on Apple
10930 Silicon and on iOS, have no such restriction, but portable code has to assume
10931 the strictest of these. Keep in mind that a
10932 \l{QRhiBufferCopyDescription::size()}{size} of 0 leads to using the full size
10933 of \a src, which is not necessarily a multiple of 4 either.
10934
10935 \note Mixing GPU-side copies with host-side updates
10936 (\l{QRhiResourceUpdateBatch::uploadStaticBuffer()}{uploadStaticBuffer()}) on
10937 the same buffer within the same frame follows the order in which the
10938 operations were recorded in the batch, but only when the
10939 \l QRhi::StaticBuffersOnGpuTimeline feature is reported as supported. Where
10940 it is not, which in practice means Metal on macOS on devices without an
10941 Apple GPU, buffer uploads are implemented by writing to host visible memory,
10942 and so the ordering between the two kinds of updates is not defined.
10943 Portable applications need to either avoid the pattern or check the feature
10944 flag.
10945
10946 \since 6.13
10947 \sa copyTexture(), QRhi::isFeatureSupported()
10948 */
10949void QRhiResourceUpdateBatch::copyBuffer(QRhiBuffer *dst, QRhiBuffer *src, const QRhiBufferCopyDescription &desc)
10950{
10951 if (!dst || !src) {
10952 qWarning("Buffer copy with a null source or destination is not supported");
10953 return;
10954 }
10955 if (dst == src) {
10956 qWarning("Buffer copy with matching source and destination is not supported");
10957 return;
10958 }
10959 // Dynamic buffers are host visible, or shadowed on the CPU, with some of
10960 // the backends, and so cannot be the source or the destination of a
10961 // GPU-side copy. UniformBuffer is not necessarily backed by a real GPU
10962 // buffer either.
10963 if (dst->usage().testFlag(QRhiBuffer::UniformBuffer) || src->usage().testFlag(QRhiBuffer::UniformBuffer)) {
10964 qWarning("Buffer copy is not supported for buffers with UniformBuffer usage");
10965 return;
10966 }
10967 if (dst->type() == QRhiBuffer::Dynamic || src->type() == QRhiBuffer::Dynamic) {
10968 qWarning("Buffer copy is not supported for Dynamic buffers");
10969 return;
10970 }
10971
10972 const quint32 size = desc.size() ? desc.size() : src->size();
10973 if (!size)
10974 return;
10975 if (quint64(desc.sourceOffset()) + size > src->size() || quint64(desc.destinationOffset()) + size > dst->size()) {
10976 qWarning("Buffer copy of %u bytes (source offset %u, destination offset %u) "
10977 "does not fit the source (%u bytes) or destination (%u bytes) buffer",
10978 size, desc.sourceOffset(), desc.destinationOffset(),
10979 src->size(), dst->size());
10980 return;
10981 }
10982
10983 const int idx = d->activeBufferOpCount++;
10984 const QRhiResourceUpdateBatchPrivate::BufferOp op = QRhiResourceUpdateBatchPrivate::BufferOp::copy(dst, src,
10985 desc.destinationOffset(), desc.sourceOffset(), size);
10986
10987 if (idx < d->bufferOps.size())
10988 d->bufferOps[idx] = op;
10989 else
10990 d->bufferOps.append(op);
10991}
10992
10993/*!
10994 Enqueues filling \a size bytes of the buffer \a buf, starting at \a offset,
10995 with the byte \a value.
10996
10997 The buffer must have been created with the QRhiBuffer::StorageBuffer usage.
10998 Such buffers are only available when the \l QRhi::Compute feature is
10999 reported as supported, and are never of the type QRhiBuffer::Dynamic. The
11000 clear is performed on the GPU, and it takes effect in the order it was
11001 recorded in, relative to the compute and render passes, and to the other
11002 buffer operations in the batch that are performed on the GPU, such as
11003 copyBuffer(). This makes it suitable for resetting storage buffers
11004 (counters, accumulators) between compute dispatches.
11005
11006 \note \a offset must be a multiple of 4, otherwise the clear is ignored,
11007 with a warning. When \a size is not a multiple of 4, it is rounded down to
11008 the previous multiple of 4, again with a warning, which means the
11009 remaining one to three bytes are left untouched. These are restrictions of
11010 some of the underlying 3D APIs.
11011
11012 \note The clear maps to the native buffer fill or clear operation of the
11013 underlying 3D API, such as \c vkCmdFillBuffer or
11014 \c ClearUnorderedAccessViewUint, without transferring data from the CPU.
11015 The exception is OpenGL ES, which has no way of clearing the contents of a
11016 buffer on the GPU. There the clear is implemented by uploading \a size
11017 bytes of data.
11018
11019 \note Mixing clears with host-side updates
11020 (\l{QRhiResourceUpdateBatch::uploadStaticBuffer()}{uploadStaticBuffer()}) on
11021 the same buffer within the same frame follows the order in which the
11022 operations were recorded in the batch only when the
11023 \l QRhi::StaticBuffersOnGpuTimeline feature is reported as supported. See
11024 copyBuffer() for details.
11025
11026 \since 6.13
11027 \sa copyBuffer()
11028 */
11029void QRhiResourceUpdateBatch::clearStorageBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, quint8 value)
11030{
11031 if (!buf) {
11032 qWarning("Buffer clear with a null buffer is not supported");
11033 return;
11034 }
11035 if (!buf->usage().testFlag(QRhiBuffer::StorageBuffer)) {
11036 qWarning("Buffer clear is only supported for buffers with StorageBuffer usage");
11037 return;
11038 }
11039 // StorageBuffer is not supposed to be combined with Dynamic, but not all
11040 // backends reject it
11041 if (buf->type() == QRhiBuffer::Dynamic) {
11042 qWarning("Buffer clear is not supported for Dynamic buffers");
11043 return;
11044 }
11045 if (offset % 4u) {
11046 qWarning("Buffer clear offset %u is not a multiple of 4", offset);
11047 return;
11048 }
11049 if (quint64(offset) + size > buf->size()) {
11050 qWarning("Buffer clear of %u bytes at offset %u does not fit the buffer (%u bytes)",
11051 size, offset, buf->size());
11052 return;
11053 }
11054 if (size % 4u) {
11055 qWarning("Buffer clear size %u is not a multiple of 4, rounding down", size);
11056 size &= ~3u;
11057 }
11058 if (!size)
11059 return;
11060
11061 const int idx = d->activeBufferOpCount++;
11062 const QRhiResourceUpdateBatchPrivate::BufferOp op = QRhiResourceUpdateBatchPrivate::BufferOp::clear(buf,
11063 offset, size, value);
11064
11065 if (idx < d->bufferOps.size())
11066 d->bufferOps[idx] = op;
11067 else
11068 d->bufferOps.append(op);
11069}
11070
11071/*!
11072 \overload
11073
11074 Enqueues filling the entire buffer \a buf with the byte \a value. When the
11075 size of \a buf is not a multiple of 4, the last one to three bytes are left
11076 untouched, and a warning is printed.
11077
11078 \since 6.13
11079 */
11080void QRhiResourceUpdateBatch::clearStorageBuffer(QRhiBuffer *buf, quint8 value)
11081{
11082 clearStorageBuffer(buf, 0, buf ? buf->size() : 0, value);
11083}
11084
11085/*!
11086 Enqueues uploading the image data for one or more mip levels in one or more
11087 layers of the texture \a tex.
11088
11089 The details of the copy (source QImage or compressed texture data, regions,
11090 target layers and levels) are described in \a desc.
11091 */
11092void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
11093{
11094 if (desc.cbeginEntries() != desc.cendEntries()) {
11095 const int idx = d->activeTextureOpCount++;
11096 if (idx < d->textureOps.size())
11097 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc);
11098 else
11099 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc));
11100 }
11101}
11102
11103/*!
11104 Enqueues uploading the image data for mip level 0 of layer 0 of the texture
11105 \a tex.
11106
11107 \a tex must have an uncompressed format. Its format must also be compatible
11108 with the QImage::format() of \a image. The source data is given in \a
11109 image.
11110 */
11111void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &image)
11112{
11113 uploadTexture(tex,
11114 QRhiTextureUploadEntry(0, 0, QRhiTextureSubresourceUploadDescription(image)));
11115}
11116
11117/*!
11118 Enqueues a texture-to-texture copy operation from \a src into \a dst as
11119 described by \a desc.
11120
11121 \note The source texture \a src must be created with
11122 QRhiTexture::UsedAsTransferSource.
11123
11124 \note The format of the textures must match. With most graphics
11125 APIs the data is copied as-is without any format conversions. If
11126 \a dst and \a src are created with different formats, unspecified
11127 issues may arise.
11128 */
11129void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
11130{
11131 const int idx = d->activeTextureOpCount++;
11132 if (idx < d->textureOps.size())
11133 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc);
11134 else
11135 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc));
11136}
11137
11138/*!
11139 Enqueues a texture-to-host copy operation as described by \a rb.
11140
11141 Normally \a rb will specify a QRhiTexture as the source. However, when the
11142 swapchain in the current frame was created with
11143 QRhiSwapChain::UsedAsTransferSource, it can also be the source of the
11144 readback. For this, leave the texture set to null in \a rb.
11145
11146 Unlike other operations, the results here need to be processed by the
11147 application. Therefore, \a result provides not just the data but also a
11148 callback as operations on the batch are asynchronous by nature:
11149
11150 \code
11151 rhi->beginFrame(swapchain);
11152 cb->beginPass(swapchain->currentFrameRenderTarget(), colorClear, dsClear);
11153 // ...
11154 QRhiReadbackResult *rbResult = new QRhiReadbackResult;
11155 rbResult->completed = [rbResult] {
11156 {
11157 const QImage::Format fmt = QImage::Format_RGBA8888_Premultiplied; // fits QRhiTexture::RGBA8
11158 const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
11159 QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
11160 image.save("result.png");
11161 }
11162 delete rbResult;
11163 };
11164 QRhiResourceUpdateBatch *u = nextResourceUpdateBatch();
11165 QRhiReadbackDescription rb; // no texture -> uses the current backbuffer of sc
11166 u->readBackTexture(rb, rbResult);
11167 cb->endPass(u);
11168 rhi->endFrame(swapchain);
11169 \endcode
11170
11171 \note The texture must be created with QRhiTexture::UsedAsTransferSource.
11172
11173 \note Multisample textures cannot be read back.
11174
11175 \note The readback returns raw byte data, in order to allow the applications
11176 to interpret it in any way they see fit. Be aware of the blending settings
11177 of rendering code: if the blending is set up to rely on premultiplied alpha,
11178 the results of the readback must also be interpreted as Premultiplied.
11179
11180 \note When interpreting the resulting raw data, be aware that the readback
11181 happens with a byte ordered format. A \l{QRhiTexture::RGBA8}{RGBA8} texture
11182 maps therefore to byte ordered QImage formats, such as,
11183 QImage::Format_RGBA8888.
11184
11185 The data of a depth or depth-stencil texture is returned in the following
11186 layout, in native byte order, regardless of the backend. Any bits not
11187 mentioned are zero.
11188
11189 \list
11190 \li \l{QRhiTexture::D16}{D16}: 2 bytes per pixel, a 16-bit normalized unsigned integer.
11191 \li \l{QRhiTexture::D24}{D24}: 4 bytes per pixel, the 24-bit normalized
11192 unsigned integer depth in the upper 24 bits.
11193 \li \l{QRhiTexture::D24S8}{D24S8}: 4 bytes per pixel, the 24-bit
11194 normalized unsigned integer depth in the upper 24 bits and the stencil in
11195 the lower 8 bits.
11196 \li \l{QRhiTexture::D32F}{D32F}: 4 bytes per pixel, a 32-bit float.
11197 \li \l{QRhiTexture::D32FS8}{D32FS8}: 8 bytes per pixel, a 32-bit float
11198 depth, followed by a 32-bit unsigned integer with the stencil in the lower 8
11199 bits.
11200 \endlist
11201
11202 \note With OpenGL ES, reading back a depth or depth-stencil texture is not
11203 supported, see QRhi::ReadBackAnyTextureFormat.
11204
11205 \note The asynchronous readback is guaranteed to have completed when one of
11206 the following conditions is met: \l{QRhi::finish()}{finish()} has been
11207 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
11208 including the frame that issued the readback operation, and the
11209 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
11210 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
11211 QRhi::MaxAsyncReadbackFrames.
11212
11213 A single readback operation copies one mip level of one layer (cubemap face
11214 or 3D slice or texture array element) at a time. The level and layer are
11215 specified by the respective fields in \a rb.
11216
11217 \sa readBackBuffer(), QRhi::resourceLimit()
11218 */
11219void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
11220{
11221 const int idx = d->activeTextureOpCount++;
11222 if (idx < d->textureOps.size())
11223 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result);
11224 else
11225 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result));
11226}
11227
11228/*!
11229 Enqueues a mipmap generation operation for the specified texture \a tex.
11230
11231 2D and cube textures are supported. 1D and 3D textures are supported when
11232 the QRhi::OneDimensionalTextureMipmaps or QRhi::ThreeDimensionalTextureMipmaps
11233 feature is reported as supported, respectively.
11234
11235 \note The texture must be created with QRhiTexture::MipMapped and
11236 QRhiTexture::UsedWithGenerateMips.
11237
11238 \warning QRhi cannot guarantee that mipmaps can be generated for all
11239 supported texture formats. For example, QRhiTexture::RGBA32F is not a \c
11240 filterable format in OpenGL ES 3.0 and Metal on iOS, and therefore the
11241 mipmap generation request may fail. RGBA8 and RGBA16F are typically
11242 filterable, so it is recommended to use these formats when mipmap generation
11243 is desired.
11244 */
11245void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex)
11246{
11247 const int idx = d->activeTextureOpCount++;
11248 if (idx < d->textureOps.size())
11249 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex);
11250 else
11251 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex));
11252}
11253
11254/*!
11255 Enqueues updating the contents of the indirect command buffer \a icb from
11256 the commands recorded on it with QRhiIndirectCommandBuffer::draw() or
11257 QRhiIndirectCommandBuffer::drawIndexed().
11258
11259 Has to be called after recording and before the render pass that executes
11260 the commands. Does nothing when nothing changed since the last time, so
11261 calling it once per frame is inexpensive.
11262
11263 Has no effect on an indirect command buffer that was populated with
11264 QRhiCommandBuffer::buildIndirect() instead.
11265
11266 \note This is where backends that keep the commands in a buffer perform the
11267 upload, but it is not necessarily where the cost of a CPU-recorded indirect
11268 command buffer is: Metal has nothing to upload here and does its per-command
11269 encoding in QRhiCommandBuffer::executeIndirect() instead. An inexpensive
11270 commitIndirectCommandBuffer() therefore does not by itself mean that
11271 recording the commands was inexpensive. See \l QRhiIndirectCommandBuffer for
11272 how the cost of CPU recording scales.
11273
11274 \since 6.13
11275 */
11276void QRhiResourceUpdateBatch::commitIndirectCommandBuffer(QRhiIndirectCommandBuffer *icb)
11277{
11278 Q_ASSERT(icb);
11279 d->rhi->commitIndirectCommandBuffer(this, icb);
11280}
11281
11282/*!
11283 \return an available, empty batch to which copy type of operations can be
11284 recorded.
11285
11286 \note the return value is not owned by the caller and must never be
11287 destroyed. Instead, the batch is returned the pool for reuse by passing
11288 it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or
11289 QRhiCommandBuffer::resourceUpdate(), or by calling
11290 QRhiResourceUpdateBatch::release() on it.
11291
11292 \note Can be called outside beginFrame() - endFrame() as well since a batch
11293 instance just collects data on its own, it does not perform any operations.
11294
11295 Due to not being tied to a frame being recorded, the following sequence is
11296 valid for example:
11297
11298 \code
11299 rhi->beginFrame(swapchain);
11300 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
11301 u->uploadStaticBuffer(buf, data);
11302 // ... do not commit the batch
11303 rhi->endFrame();
11304 // u stays valid (assuming buf stays valid as well)
11305 rhi->beginFrame(swapchain);
11306 swapchain->currentFrameCommandBuffer()->resourceUpdate(u);
11307 // ... draw with buf
11308 rhi->endFrame();
11309 \endcode
11310
11311 \warning The maximum number of batches per QRhi is 64. When this limit is
11312 reached, the function will return null until a batch is returned to the
11313 pool.
11314 */
11315QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
11316{
11317 // By default we prefer spreading out the utilization of the worst case 64
11318 // (but typically 4) batches as much as possible, meaning we won't pick the
11319 // first one even if it's free, but prefer picking one after the last picked
11320 // one. Relevant due to implicit sharing (the backend may hold on to the
11321 // QRhiBufferData until frame no. current+FramesInFlight-1, but
11322 // implementations may vary), combined with the desire to reuse container
11323 // and QRhiBufferData allocations in bufferOps instead of flooding every
11324 // frame with allocs. See free(). In typical Qt Quick scenes this leads to
11325 // eventually seeding all 4 (or more) resource batches with buffer operation
11326 // data allocations which may (*) then be reused in subsequent frames. This
11327 // comes at the expense of using more memory, but has proven good results
11328 // when (CPU) profiling typical Quick/Quick3D apps.
11329 //
11330 // (*) Due to implicit sharing(ish), the exact behavior is unpredictable. If
11331 // a backend holds on to the QRhiBufferData for, e.g., a dynamic buffer
11332 // update, and then there is a new assign() for that same QRhiBufferData
11333 // while the refcount is still 2, it will "detach" (without contents) and
11334 // there is no reuse of the alloc. This is mitigated by the 'choose the one
11335 // afer the last picked one' logic when handing out batches.
11336
11337 auto nextFreeBatch = [this]() -> QRhiResourceUpdateBatch * {
11338 auto isFree = [this](int i) -> QRhiResourceUpdateBatch * {
11339 const quint64 mask = 1ULL << quint64(i);
11340 if (!(d->resUpdPoolMap & mask)) {
11341 d->resUpdPoolMap |= mask;
11342 QRhiResourceUpdateBatch *u = d->resUpdPool[i];
11343 QRhiResourceUpdateBatchPrivate::get(u)->poolIndex = i;
11344 d->lastResUpdIdx = i;
11345 return u;
11346 }
11347 return nullptr;
11348 };
11349 const int poolSize = d->resUpdPool.size();
11350 for (int i = d->lastResUpdIdx + 1; i < poolSize; ++i) {
11351 if (QRhiResourceUpdateBatch *u = isFree(i))
11352 return u;
11353 }
11354 for (int i = 0; i <= d->lastResUpdIdx; ++i) {
11355 if (QRhiResourceUpdateBatch *u = isFree(i))
11356 return u;
11357 }
11358 return nullptr;
11359 };
11360
11361 QRhiResourceUpdateBatch *u = nextFreeBatch();
11362 if (!u) {
11363 const int oldSize = d->resUpdPool.size();
11364 // 4, 8, 12, ..., up to 64
11365 const int newSize = oldSize + qMin(4, qMax(0, 64 - oldSize));
11366 d->resUpdPool.resize(newSize);
11367 for (int i = oldSize; i < newSize; ++i)
11368 d->resUpdPool[i] = new QRhiResourceUpdateBatch(d);
11369 u = nextFreeBatch();
11370 if (!u)
11371 qWarning("Resource update batch pool exhausted (max is 64)");
11372 }
11373
11374 return u;
11375}
11376
11378{
11379 Q_ASSERT(poolIndex >= 0 && rhi->resUpdPool[poolIndex] == q);
11380
11381 quint32 bufferDataTotal = 0;
11382 quint32 bufferLargeAllocTotal = 0;
11383 for (const BufferOp &op : std::as_const(bufferOps)) {
11384 bufferDataTotal += op.data.size();
11385 bufferLargeAllocTotal += op.data.largeAlloc(); // alloc when > 1 KB
11386 }
11387
11388 if (QRHI_LOG_RUB().isDebugEnabled()) {
11389 qDebug() << "[rub] release to pool upd.batch #" << poolIndex
11390 << "/ bufferOps active" << activeBufferOpCount
11391 << "of" << bufferOps.count()
11392 << "data" << bufferDataTotal
11393 << "largeAlloc" << bufferLargeAllocTotal
11394 << "textureOps active" << activeTextureOpCount
11395 << "of" << textureOps.count();
11396 }
11397
11400
11401 const quint64 mask = 1ULL << quint64(poolIndex);
11402 rhi->resUpdPoolMap &= ~mask;
11403 poolIndex = -1;
11404
11405 // textureOps is cleared, to not keep the potentially large image pixel
11406 // data alive, but it is expected that the container keeps the list alloc
11407 // at least. Only trimOpList() goes for the more aggressive route with squeeze.
11408 textureOps.clear();
11409
11410 // bufferOps is not touched in many cases, to allow reusing allocations
11411 // (incl. in the elements' QRhiBufferData) as much as possible when this
11412 // batch is used again in the future, which is important for performance, in
11413 // particular with Qt Quick where it is easy for scenes to produce lots of,
11414 // typically small buffer changes on every frame.
11415 //
11416 // However, ensure that even in the unlikely case of having the max number
11417 // of batches (64) created in resUpdPool, no more than 64 MB in total is
11418 // used up by buffer data just to help future reuse. For simplicity, if
11419 // there is more than 1 MB data -> clear. Applications with frequent, huge
11420 // buffer updates probably have other bottlenecks anyway.
11421 if (bufferLargeAllocTotal > 1024 * 1024)
11422 bufferOps.clear();
11423}
11424
11426{
11427 int combinedSize = activeBufferOpCount + other->activeBufferOpCount;
11428 if (bufferOps.size() < combinedSize)
11429 bufferOps.resize(combinedSize);
11430 for (int i = activeBufferOpCount; i < combinedSize; ++i)
11431 bufferOps[i] = std::move(other->bufferOps[i - activeBufferOpCount]);
11433
11434 combinedSize = activeTextureOpCount + other->activeTextureOpCount;
11435 if (textureOps.size() < combinedSize)
11436 textureOps.resize(combinedSize);
11437 for (int i = activeTextureOpCount; i < combinedSize; ++i)
11438 textureOps[i] = std::move(other->textureOps[i - activeTextureOpCount]);
11440}
11441
11447
11449{
11450 // Unlike free(), this is expected to aggressively deallocate all memory
11451 // used by both the buffer and texture operation lists. (i.e. using
11452 // squeeze() to only keep the stack prealloc of the QVLAs)
11453 //
11454 // This (e.g. just the destruction of bufferOps elements) may have a
11455 // non-negligible performance impact e.g. with Qt Quick with scenes where
11456 // there are lots of buffer operations per frame.
11457
11459 bufferOps.clear();
11460 bufferOps.squeeze();
11461
11463 textureOps.clear();
11464 textureOps.squeeze();
11465}
11466
11467/*!
11468 Sometimes committing resource updates is necessary or just more convenient
11469 without starting a render pass. Calling this function with \a
11470 resourceUpdates is an alternative to passing \a resourceUpdates to a
11471 beginPass() call (or endPass(), which would be typical in case of readbacks).
11472
11473 \note Cannot be called inside a pass.
11474 */
11475void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
11476{
11477 if (resourceUpdates)
11478 m_rhi->resourceUpdate(this, resourceUpdates);
11479}
11480
11481/*!
11482 Records starting a new render pass targeting the render target \a rt.
11483
11484 \a resourceUpdates, when not null, specifies a resource update batch that
11485 is to be committed and then released.
11486
11487 The color and depth/stencil buffers of the render target are normally
11488 cleared. The clear values are specified in \a colorClearValue and \a
11489 depthStencilClearValue. The exception is when the render target was created
11490 with QRhiTextureRenderTarget::PreserveColorContents and/or
11491 QRhiTextureRenderTarget::PreserveDepthStencilContents. The clear values are
11492 ignored then.
11493
11494 \note Enabling preserved color or depth contents leads to decreased
11495 performance depending on the underlying hardware. Mobile GPUs with tiled
11496 architecture benefit from not having to reload the previous contents into
11497 the tile buffer. Similarly, a QRhiTextureRenderTarget with a QRhiTexture as
11498 the depth buffer is less efficient than a QRhiRenderBuffer since using a
11499 depth texture triggers requiring writing the data out to it, while with
11500 renderbuffers this is not needed (as the API does not allow sampling or
11501 reading from a renderbuffer).
11502
11503 \note Do not assume that any state or resource bindings persist between
11504 passes.
11505
11506 \note The QRhiCommandBuffer's \c set and \c draw functions can only be
11507 called inside a pass. Also, with the exception of setGraphicsPipeline(),
11508 they expect to have a pipeline set already on the command buffer.
11509 Unspecified issues may arise otherwise, depending on the backend.
11510
11511 If \a rt is a QRhiTextureRenderTarget, beginPass() performs a check to see
11512 if the texture and renderbuffer objects referenced from the render target
11513 are up-to-date. This is similar to what setShaderResources() does for
11514 QRhiShaderResourceBindings. If any of the attachments had been rebuilt
11515 since QRhiTextureRenderTarget::create(), an implicit call to create() is
11516 made on \a rt. Therefore, if \a rt has a QRhiTexture color attachment \c
11517 texture, and one needs to make the texture a different size, the following
11518 is then valid:
11519 \code
11520 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ { texture } });
11521 rt->create();
11522 // ...
11523 texture->setPixelSize(new_size);
11524 texture->create();
11525 cb->beginPass(rt, colorClear, dsClear); // this is ok, no explicit rt->create() is required before
11526 \endcode
11527
11528 \a flags allow controlling certain advanced functionality. One commonly used
11529 flag is \c ExternalContents. This should be specified whenever
11530 beginExternal() will be called within the pass started by this function.
11531
11532 \sa endPass(), BeginPassFlags
11533 */
11534void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
11535 const QColor &colorClearValue,
11536 const QRhiDepthStencilClearValue &depthStencilClearValue,
11537 QRhiResourceUpdateBatch *resourceUpdates,
11538 BeginPassFlags flags)
11539{
11540 m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates, flags);
11541}
11542
11543/*!
11544 Records ending the current render pass.
11545
11546 \a resourceUpdates, when not null, specifies a resource update batch that
11547 is to be committed and then released.
11548
11549 \sa beginPass()
11550 */
11551void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates)
11552{
11553 m_rhi->endPass(this, resourceUpdates);
11554}
11555
11556/*!
11557 Records setting a new graphics pipeline \a ps.
11558
11559 \note This function must be called before recording other \c set or \c draw
11560 commands on the command buffer.
11561
11562 \note QRhi will optimize out unnecessary invocations within a pass, so
11563 therefore overoptimizing to avoid calls to this function is not necessary
11564 on the applications' side.
11565
11566 \note This function can only be called inside a render pass, meaning
11567 between a beginPass() and endPass() call.
11568
11569 \note The new graphics pipeline \a ps must be a valid pointer.
11570
11571 Setting a graphics pipeline that does not have the
11572 \l{QRhiGraphicsPipeline::}{UsesScissor} flag will either disable scissoring,
11573 with graphics APIs where that is applicable, or set the scissor rectangle to
11574 match the viewport that was last set (with graphics APIs where scissoring is
11575 effectively always active), in order to ensure a uniform behavior across QRhi
11576 backends.
11577 */
11578void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)
11579{
11580 Q_ASSERT(ps != nullptr);
11581 m_rhi->setGraphicsPipeline(this, ps);
11582}
11583
11584/*!
11585 Records binding a set of shader resources, such as, uniform buffers or
11586 textures, that are made visible to one or more shader stages.
11587
11588 \a srb can be null in which case the current graphics or compute pipeline's
11589 associated QRhiShaderResourceBindings is used. When \a srb is non-null, it
11590 must be
11591 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible},
11592 meaning the layout (number of bindings, the type and binding number of each
11593 binding) must fully match the QRhiShaderResourceBindings that was
11594 associated with the pipeline at the time of calling the pipeline's create().
11595
11596 There are cases when a seemingly unnecessary setShaderResources() call is
11597 mandatory: when rebuilding a resource referenced from \a srb, for example
11598 changing the size of a QRhiBuffer followed by a QRhiBuffer::create(), this
11599 is the place where associated native objects (such as descriptor sets in
11600 case of Vulkan) are updated to refer to the current native resources that
11601 back the QRhiBuffer, QRhiTexture, QRhiSampler objects referenced from \a
11602 srb. In this case setShaderResources() must be called even if \a srb is
11603 the same as in the last call.
11604
11605 When \a srb is not null, the QRhiShaderResourceBindings object the pipeline
11606 was built with in create() is guaranteed to be not accessed in any form. In
11607 fact, it does not need to be valid even at this point: destroying the
11608 pipeline's associated srb after create() and instead explicitly specifying
11609 another, \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout
11610 compatible} one in every setShaderResources() call is valid.
11611
11612 \a dynamicOffsets allows specifying buffer offsets for uniform buffers that
11613 were associated with \a srb via
11614 QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(). This is
11615 different from providing the offset in the \a srb itself: dynamic offsets
11616 do not require building a new QRhiShaderResourceBindings for every
11617 different offset, can avoid writing the underlying descriptors (with
11618 backends where applicable), and so they may be more efficient. Each element
11619 of \a dynamicOffsets is a \c binding - \c offset pair.
11620 \a dynamicOffsetCount specifies the number of elements in \a dynamicOffsets.
11621
11622 \note All offsets in \a dynamicOffsets must be byte aligned to the value
11623 returned from QRhi::ubufAlignment().
11624
11625 \note Some backends may limit the number of supported dynamic offsets.
11626 Avoid using a \a dynamicOffsetCount larger than 8.
11627
11628 \note QRhi will optimize out unnecessary invocations within a pass (taking
11629 the conditions described above into account), so therefore overoptimizing
11630 to avoid calls to this function is not necessary on the applications' side.
11631
11632 \note This function can only be called inside a render or compute pass,
11633 meaning between a beginPass() and endPass(), or beginComputePass() and
11634 endComputePass().
11635 */
11636void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb,
11637 int dynamicOffsetCount,
11638 const DynamicOffset *dynamicOffsets)
11639{
11640 m_rhi->setShaderResources(this, srb, dynamicOffsetCount, dynamicOffsets);
11641}
11642
11643/*!
11644 Records vertex input bindings.
11645
11646 The index buffer used by subsequent drawIndexed() commands is specified by
11647 \a indexBuf, \a indexOffset, and \a indexFormat. \a indexBuf can be set to
11648 null when indexed drawing is not needed.
11649
11650 Vertex buffer bindings are batched. \a startBinding specifies the first
11651 binding number. The recorded command then binds each buffer from \a
11652 bindings to the binding point \c{startBinding + i} where \c i is the index
11653 in \a bindings. Each element in \a bindings specifies a QRhiBuffer and an
11654 offset.
11655
11656 \note Some backends may limit the number of vertex buffer bindings. Avoid
11657 using a \a bindingCount larger than 8.
11658
11659 Superfluous vertex input and index changes in the same pass are ignored
11660 automatically with most backends and therefore applications do not need to
11661 overoptimize to avoid calls to this function.
11662
11663 \note This function can only be called inside a render pass, meaning
11664 between a beginPass() and endPass() call.
11665
11666 As a simple example, take a vertex shader with two inputs:
11667
11668 \badcode
11669 layout(location = 0) in vec4 position;
11670 layout(location = 1) in vec3 color;
11671 \endcode
11672
11673 and assume we have the data available in interleaved format, using only 2
11674 floats for position (so 5 floats per vertex: x, y, r, g, b). A QRhiGraphicsPipeline for
11675 this shader can then be created using the input layout:
11676
11677 \code
11678 QRhiVertexInputLayout inputLayout;
11679 inputLayout.setBindings({
11680 { 5 * sizeof(float) }
11681 });
11682 inputLayout.setAttributes({
11683 { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
11684 { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
11685 });
11686 \endcode
11687
11688 Here there is one buffer binding (binding number 0), with two inputs
11689 referencing it. When recording the pass, once the pipeline is set, the
11690 vertex bindings can be specified simply like the following, assuming vbuf
11691 is the QRhiBuffer with all the interleaved position+color data:
11692
11693 \code
11694 const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
11695 cb->setVertexInput(0, 1, &vbufBinding);
11696 \endcode
11697 */
11698void QRhiCommandBuffer::setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
11699 QRhiBuffer *indexBuf, quint32 indexOffset,
11700 IndexFormat indexFormat)
11701{
11702 m_rhi->setVertexInput(this, startBinding, bindingCount, bindings, indexBuf, indexOffset, indexFormat);
11703}
11704
11705/*!
11706 Records setting the active viewport rectangle specified in \a viewport.
11707
11708 With backends where the underlying graphics API has scissoring always
11709 enabled, this function also sets the scissor to match the viewport whenever
11710 the active QRhiGraphicsPipeline does not have
11711 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set.
11712
11713 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
11714 bottom-left.
11715
11716 \note This function can only be called inside a render pass, meaning
11717 between a beginPass() and endPass() call.
11718 */
11719void QRhiCommandBuffer::setViewport(const QRhiViewport &viewport)
11720{
11721 m_rhi->setViewport(this, viewport);
11722}
11723
11724/*!
11725 Records setting the active scissor rectangle specified in \a scissor.
11726
11727 This can only be called when the bound pipeline has
11728 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set. When the flag is
11729 set on the active pipeline, this function must be called because scissor
11730 testing will get enabled and so a scissor rectangle must be provided.
11731
11732 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
11733 bottom-left.
11734
11735 \note This function can only be called inside a render pass, meaning
11736 between a beginPass() and endPass() call.
11737 */
11738void QRhiCommandBuffer::setScissor(const QRhiScissor &scissor)
11739{
11740 m_rhi->setScissor(this, scissor);
11741}
11742
11743/*!
11744 Records setting the active blend constants to \a c.
11745
11746 This can only be called when the bound pipeline has
11747 QRhiGraphicsPipeline::UsesBlendConstants set.
11748
11749 \note This function can only be called inside a render pass, meaning
11750 between a beginPass() and endPass() call.
11751 */
11752void QRhiCommandBuffer::setBlendConstants(const QColor &c)
11753{
11754 m_rhi->setBlendConstants(this, c);
11755}
11756
11757/*!
11758 Records setting the active stencil reference value to \a refValue.
11759
11760 This can only be called when the bound pipeline has
11761 QRhiGraphicsPipeline::UsesStencilRef set.
11762
11763 The value stays in effect for the rest of the render pass, also when other
11764 pipelines are bound, but it is only used by pipelines with
11765 QRhiGraphicsPipeline::UsesStencilRef set. Pipelines without the flag always
11766 use a stencil reference value of 0. Each render pass starts with a stencil
11767 reference value of 0, regardless of what was set in earlier passes.
11768
11769 \note This function can only be called inside a render pass, meaning between
11770 a beginPass() and endPass() call.
11771 */
11772void QRhiCommandBuffer::setStencilRef(quint32 refValue)
11773{
11774 m_rhi->setStencilRef(this, refValue);
11775}
11776
11777/*!
11778 Records setting the push constant data for the currently bound graphics or
11779 compute pipeline. \a size bytes are taken from \a data and placed at byte
11780 offset \a offset within the push constant block. Both \a offset and \a
11781 size must be a multiple of 4.
11782
11783 Push constants are a small, pipeline-layout-resident block of data that can
11784 be updated between draw calls without touching any
11785 QRhiShaderResourceBindings. This makes them suitable for per-draw values
11786 such as an index into a storage buffer, avoiding a setShaderResources()
11787 call per draw.
11788
11789 The shaders declare the block in the usual way, for example:
11790
11791 \badcode
11792 layout(push_constant) uniform PC { uint objectIndex; } pc;
11793 \endcode
11794
11795 \note A push constant block defaults to the std430 layout, unlike a
11796 uniform block. There an array of scalars or of \c vec2 is tightly packed,
11797 and so are the columns of a matrix with two rows (\c mat2, \c mat3x2,
11798 \c mat4x2). Neither can be expressed in a Direct3D constant buffer, so a
11799 block that has such a member has to be declared with
11800 \c{layout(push_constant, std140)} in order to be usable with the D3D
11801 backends. (qsb reports an error when baking such a shader for HLSL) Blocks
11802 with only scalars, vectors, and \c mat3 or \c mat4 matrices, which is what
11803 push constants are mostly used for, are unaffected.
11804
11805 QRhi derives the push constant range from the shader reflection data of the
11806 pipeline's shader stages, so no extra declaration is needed on the
11807 QRhiGraphicsPipeline or QRhiComputePipeline.
11808
11809 \note This is only functional when the PushConstants feature is reported as
11810 supported. The maximum size of the block is reported by the
11811 MaxPushConstantsSize resource limit.
11812
11813 \note With Metal, push constants are not supported with a graphics pipeline
11814 that uses tessellation. Calling this function while such a pipeline is
11815 bound has no effect, apart from a warning.
11816
11817 \note Must be called inside a pass, after setGraphicsPipeline() or
11818 setComputePipeline().
11819
11820 \note The data does not persist. It has to be set again in every pass and
11821 after every change of pipeline. The backends differ in how much they would
11822 otherwise retain, so relying on anything else is not portable.
11823
11824 \since 6.13
11825 */
11826void QRhiCommandBuffer::setPushConstants(quint32 offset, quint32 size, const void *data)
11827{
11828 m_rhi->setPushConstants(this, offset, size, data);
11829}
11830
11831/*!
11832 Sets the shading rate for the following draw calls to \a coarsePixelSize.
11833
11834 The default is 1x1.
11835
11836 Functional only when the \l QRhi::VariableRateShading feature is reported as
11837 supported and the QRhiGraphicsPipeline(s) bound on the command buffer were
11838 declaring \l QRhiGraphicsPipeline::UsesShadingRate when creating them.
11839
11840 Call \l QRhi::supportedShadingRates() to check what shading rates are
11841 supported for a given sample count.
11842
11843 When both a QRhiShadingRateMap and this function are in use, the higher of
11844 the two shading rates is used for each tile. There is currently no control
11845 offered over the combiner behavior.
11846
11847 \since 6.9
11848 */
11849void QRhiCommandBuffer::setShadingRate(const QSize &coarsePixelSize)
11850{
11851 m_rhi->setShadingRate(this, coarsePixelSize);
11852}
11853
11854/*!
11855 Records a non-indexed draw.
11856
11857 The number of vertices is specified in \a vertexCount. For instanced
11858 drawing set \a instanceCount to a value other than 1. \a firstVertex is the
11859 index of the first vertex to draw. When drawing multiple instances, the
11860 first instance ID is specified by \a firstInstance.
11861
11862 \note \a firstInstance may not be supported, and is ignored when the
11863 QRhi::BaseInstance feature is reported as not supported. The first instance
11864 ID is always 0 in that case. QRhi::BaseInstance is never supported with
11865 OpenGL ES, and therefore portable applications should not be designed to
11866 rely on this argument.
11867
11868 \note Shaders that need to access the index of the current vertex or
11869 instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
11870 Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
11871 gl_InstanceID.
11872
11873 \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
11874 include the base value with some of the underlying 3D APIs. This is
11875 indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
11876 on a base instance value cannot be avoided, applications are advised to pass
11877 in the value as a uniform conditionally based on what that feature reports,
11878 and add it to \c gl_InstanceIndex in the shader.
11879
11880 \note This function can only be called inside a render pass, meaning
11881 between a beginPass() and endPass() call.
11882 */
11883void QRhiCommandBuffer::draw(quint32 vertexCount,
11884 quint32 instanceCount,
11885 quint32 firstVertex,
11886 quint32 firstInstance)
11887{
11888 m_rhi->draw(this, vertexCount, instanceCount, firstVertex, firstInstance);
11889}
11890
11891/*!
11892 Records an indexed draw.
11893
11894 The number of vertices is specified in \a indexCount. \a firstIndex is the
11895 base index. The effective offset in the index buffer is given by
11896 \c{indexOffset + firstIndex * n} where \c n is 2 or 4 depending on the
11897 index element type. \c indexOffset is specified in setVertexInput().
11898
11899 \note The effective offset in the index buffer must be 4 byte aligned with
11900 some backends (for example, Metal). With these backends the
11901 \l{QRhi::NonFourAlignedEffectiveIndexBufferOffset}{NonFourAlignedEffectiveIndexBufferOffset}
11902 feature will be reported as not-supported.
11903
11904 \a vertexOffset (also called \c{base vertex}) is a signed value that is
11905 added to the element index before indexing into the vertex buffer. Support
11906 for this is not always available, and the value is ignored when the feature
11907 QRhi::BaseVertex is reported as unsupported.
11908
11909 For instanced drawing set \a instanceCount to a value other than 1. When
11910 drawing multiple instances, the first instance ID is specified by \a
11911 firstInstance.
11912
11913 \note \a firstInstance may not be supported, and is ignored when the
11914 QRhi::BaseInstance feature is reported as not supported. The first instance
11915 ID is always 0 in that case. QRhi::BaseInstance is never supported with
11916 OpenGL ES, and therefore portable applications should not be designed to
11917 rely on this argument.
11918
11919 \note Shaders that need to access the index of the current vertex or
11920 instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
11921 Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
11922 gl_InstanceID.
11923
11924 \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
11925 include the base value with some of the underlying 3D APIs. This is
11926 indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
11927 on a base instance value cannot be avoided, applications are advised to pass
11928 in the value as a uniform conditionally based on what that feature reports,
11929 and add it to \c gl_InstanceIndex in the shader.
11930
11931 \note This function can only be called inside a render pass, meaning
11932 between a beginPass() and endPass() call.
11933 */
11934void QRhiCommandBuffer::drawIndexed(quint32 indexCount,
11935 quint32 instanceCount,
11936 quint32 firstIndex,
11937 qint32 vertexOffset,
11938 quint32 firstInstance)
11939{
11940 m_rhi->drawIndexed(this, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
11941}
11942
11943/*!
11944 Records a non-indexed, indirect draw.
11945
11946 The draw parameters are provided by the buffer specified in \a indirectBuffer,
11947 which must contain an array of elements of type QRhiIndirectDrawCommand.
11948 The parameters in QRhiIndirectDrawCommand have the same meaning as in draw().
11949
11950 The offset, in bytes, from which the parameters are read in the buffer is specified
11951 by \a indirectBufferOffset.
11952
11953 \a drawCount specifies the number of such draw commands to issue.
11954
11955 \a stride indicates the byte size of each individual draw command structure
11956 in the buffer. This allows interleaving custom data between commands if needed.
11957 The value must be a multiple of 4 and greater than or equal to sizeof(QRhiIndirectDrawCommand).
11958
11959 \note A \a drawCount value greater than 1 is only natively supported if the
11960 QRhi::DrawIndirectMulti feature is reported as supported.
11961 Otherwise, this function emulates multi-draw by recording multiple draw calls,
11962 offering no performance benefit over repeated draw() calls.
11963
11964 \note Leaving \a stride at its default is recommended whenever performance
11965 matters. With Direct 3D 12 a non-default stride prevents issuing a single
11966 native multi-draw, forcing the backend to record one command per draw
11967 instead. For a large \a drawCount this can be an order of magnitude slower,
11968 which defeats the purpose of the indirect draw. Vulkan, OpenGL, and Metal
11969 pass the stride on to their native multi-draw entry points and are not
11970 affected. Rather than interleaving custom data between the commands, keep
11971 that data in a separate buffer and index into it.
11972
11973 \note The render pass interruption and the render target consequences and
11974 limitations described for drawIndexedIndirect() apply here as well.
11975
11976 \note Therefore, portable applications should consider always using
11977 QRhiIndirectCommandBuffer and executeIndirect() instead of the
11978 draw*Indirect*() family of functions.
11979
11980 \note This function can only be called inside a render pass, meaning
11981 between a beginPass() and endPass() call.
11982
11983 \since 6.12
11984
11985 \sa drawIndexedIndirect(), drawIndirectCount(), drawIndexedIndirectCount()
11986 */
11987void QRhiCommandBuffer::drawIndirect(QRhiBuffer *indirectBuffer,
11988 quint32 indirectBufferOffset,
11989 quint32 drawCount,
11990 quint32 stride)
11991{
11992 Q_ASSERT(indirectBuffer);
11993 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
11994 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
11995 Q_ASSERT(stride >= sizeof(QRhiIndirectDrawCommand));
11996 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
11997 m_rhi->drawIndirect(this, indirectBuffer, indirectBufferOffset, drawCount, stride);
11998}
11999
12000/*!
12001 Records an indexed, indirect draw.
12002
12003 The draw parameters are provided by the buffer specified in \a indirectBuffer,
12004 which must contain an array of elements of type QRhiIndexedIndirectDrawCommand.
12005 The parameters in QRhiIndexedIndirectDrawCommand have the same meaning as in drawIndexed().
12006
12007 The offset, in bytes, from which the parameters are read in the buffer is specified
12008 by \a indirectBufferOffset.
12009
12010 \a drawCount specifies the number of such draw commands to issue.
12011
12012 \a stride indicates the byte size of each individual draw command structure
12013 in the buffer. This allows interleaving custom data between commands if needed.
12014 The value must be a multiple of 4 and greater than or equal to sizeof(QRhiIndexedIndirectDrawCommand).
12015
12016 \note A \a drawCount value greater than 1 is only natively supported if the
12017 QRhi::DrawIndirectMulti feature is reported as supported.
12018 Otherwise, this function emulates multi-draw by recording multiple draw calls,
12019 offering no performance benefit over repeated drawIndexed() calls.
12020
12021 \note Leaving \a stride at its default is recommended whenever performance
12022 matters. With Direct 3D 12 a non-default stride prevents issuing a single
12023 native multi-draw, forcing the backend to record one command per draw
12024 instead. For a large \a drawCount this can be an order of magnitude slower,
12025 which defeats the purpose of the indirect draw. Vulkan, OpenGL, and Metal
12026 pass the stride on to their native multi-draw entry points and are not
12027 affected. Rather than interleaving custom data between the commands, keep
12028 that data in a separate buffer and index into it.
12029
12030 \note With some backends a large \a drawCount is implemented by interrupting
12031 and then restarting the render pass internally due to launching a compute
12032 kernel to encode commands into an indirect command buffer. With Metal this
12033 happens above a certain \a drawCount (e.g., 128). This has consequences for
12034 the render targets: color attachment contents are preserved automatically,
12035 but a QRhiRenderBuffer serving as the depth-stencil buffer only keeps its
12036 contents if it was created with QRhiRenderBuffer::NoTransientBacking, which
12037 means that, with Metal, rendering errors may occur if the depth-stencil
12038 buffer is a QRhiRenderBuffer without the NoTransientBacking flag and the \a
12039 drawCount is above the threshold. Recording the same commands into a
12040 QRhiIndirectCommandBuffer and issuing them with executeIndirect() avoids
12041 this altogether: that never interrupts the pass.
12042
12043 \note Therefore, portable applications should consider always using
12044 QRhiIndirectCommandBuffer and executeIndirect() instead of the
12045 draw*Indirect*() family of functions.
12046
12047 \note This function can only be called inside a render pass, meaning
12048 between a beginPass() and endPass() call.
12049
12050 \since 6.12
12051
12052 \sa drawIndirect(), drawIndirectCount(), drawIndexedIndirectCount()
12053 */
12054void QRhiCommandBuffer::drawIndexedIndirect(QRhiBuffer *indirectBuffer,
12055 quint32 indirectBufferOffset,
12056 quint32 drawCount,
12057 quint32 stride)
12058{
12059 Q_ASSERT(indirectBuffer);
12060 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12061 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12062 Q_ASSERT(stride >= sizeof(QRhiIndexedIndirectDrawCommand));
12063 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
12064 m_rhi->drawIndexedIndirect(this, indirectBuffer, indirectBufferOffset, drawCount, stride);
12065}
12066
12067/*!
12068 Records a non-indexed, indirect draw, with the draw count itself read
12069 from a buffer at execution time.
12070
12071 Draw parameters are read from \a indirectBuffer at byte offset
12072 \a indirectBufferOffset as an array of QRhiIndirectDrawCommand entries
12073 spaced \a stride bytes apart. The number of draws issued is the 32-bit
12074 unsigned integer stored at \a countBufferOffset in \a countBuffer, clamped
12075 to \a maxDrawCount.
12076
12077 Both buffers must have QRhiBuffer::IndirectBuffer usage. Offsets must be
12078 4-byte aligned; \a stride must be 4-byte aligned and at least
12079 sizeof(QRhiIndirectDrawCommand).
12080
12081 Only available when \l QRhi::DrawIndirectCount is reported as supported.
12082 On other backends this is a no-op and a warning is logged. With Metal there
12083 are additional requirements, see QRhi::DrawIndirectCount.
12084
12085 \note Unlike with drawIndirect(), a non-default \a stride does not prevent
12086 the use of a single native multi-draw here. With Direct 3D 12 it does mean
12087 that an additional command signature is created and cached for each
12088 distinct stride value, so sticking to one stride is still preferable.
12089
12090 \note The value in \a countBuffer is read as a \e signed 32-bit integer by
12091 OpenGL, unlike the other backends. Counts above \c INT_MAX are therefore
12092 not portable, and neither is relying on any particular behavior for a count
12093 that exceeds \a maxDrawCount, beyond the clamping described above.
12094
12095 \note With some backends, Metal in particular, the render pass is always
12096 interrupted and restarted internally because the draw commands have to be
12097 encoded on the GPU. Color attachment contents are preserved automatically,
12098 but a QRhiRenderBuffer serving as the depth-stencil buffer only keeps its
12099 contents if it was created with QRhiRenderBuffer::NoTransientBacking.
12100 Building a QRhiIndirectCommandBuffer with buildIndirect(),
12101 which happens before the pass begins, and issuing it with
12102 executeIndirect() avoids this: that never interrupts the pass, and supports
12103 a device-side count just the same.
12104
12105 \note Therefore, portable applications should consider always using
12106 QRhiIndirectCommandBuffer and executeIndirect() instead of the
12107 draw*Indirect*() family of functions.
12108
12109 \note \a maxDrawCount is not a free upper bound. With Metal it sizes the
12110 indirect command buffer that the draw commands are encoded into, and that
12111 buffer is shared, grows on demand, and is never shrunk again for the
12112 lifetime of the QRhi. It also determines how many encoding threads are
12113 dispatched every time. Passing the capacity of \a indirectBuffer instead of
12114 a realistic upper bound therefore has a real cost.
12115
12116 \note Only valid inside a render pass.
12117
12118 \since 6.13
12119
12120 \sa drawIndirect(), drawIndexedIndirect(), drawIndexedIndirectCount()
12121 */
12122void QRhiCommandBuffer::drawIndirectCount(QRhiBuffer *indirectBuffer,
12123 quint32 indirectBufferOffset,
12124 QRhiBuffer *countBuffer,
12125 quint32 countBufferOffset,
12126 quint32 maxDrawCount,
12127 quint32 stride)
12128{
12129 Q_ASSERT(indirectBuffer);
12130 Q_ASSERT(countBuffer);
12131 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12132 Q_ASSERT(countBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12133 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12134 Q_ASSERT_X((countBufferOffset & 3u) == 0u, Q_FUNC_INFO, "countBufferOffset must be a multiple of 4");
12135 Q_ASSERT(stride >= sizeof(QRhiIndirectDrawCommand));
12136 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
12137 m_rhi->drawIndirectCount(this, indirectBuffer, indirectBufferOffset,
12138 countBuffer, countBufferOffset, maxDrawCount, stride);
12139}
12140
12141/*!
12142 Indexed variant of drawIndirectCount(). \a indirectBuffer contains, at byte
12143 offset \a indirectBufferOffset, QRhiIndexedIndirectDrawCommand entries,
12144 spaced \a stride bytes apart, and \a stride must be at least
12145 sizeof(QRhiIndexedIndirectDrawCommand). All other requirements, including
12146 how \a countBuffer, \a countBufferOffset and \a maxDrawCount are
12147 interpreted, are as described for drawIndirectCount().
12148
12149 \note The render pass interruption described for drawIndirectCount() applies
12150 here as well.
12151
12152 \note Therefore, portable applications should consider always using
12153 QRhiIndirectCommandBuffer and executeIndirect() instead of the
12154 draw*Indirect*() family of functions.
12155
12156 \note Only valid inside a render pass.
12157
12158 \since 6.13
12159
12160 \sa drawIndirect(), drawIndexedIndirect(), drawIndirectCount()
12161 */
12162void QRhiCommandBuffer::drawIndexedIndirectCount(QRhiBuffer *indirectBuffer,
12163 quint32 indirectBufferOffset,
12164 QRhiBuffer *countBuffer,
12165 quint32 countBufferOffset,
12166 quint32 maxDrawCount,
12167 quint32 stride)
12168{
12169 Q_ASSERT(indirectBuffer);
12170 Q_ASSERT(countBuffer);
12171 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12172 Q_ASSERT(countBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12173 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12174 Q_ASSERT_X((countBufferOffset & 3u) == 0u, Q_FUNC_INFO, "countBufferOffset must be a multiple of 4");
12175 Q_ASSERT(stride >= sizeof(QRhiIndexedIndirectDrawCommand));
12176 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
12177 m_rhi->drawIndexedIndirectCount(this, indirectBuffer, indirectBufferOffset,
12178 countBuffer, countBufferOffset, maxDrawCount, stride);
12179}
12180
12181/*!
12182 Records populating the indirect command buffer \a icb from the buffer and
12183 parameters described by \a info.
12184
12185 This is the GPU-driven counterpart of recording draw() or drawIndexed()
12186 calls on the QRhiIndirectCommandBuffer: the commands come from
12187 \c{info.sourceBuffer}, which is typically written by a compute shader
12188 earlier in the frame. Any commands recorded on the CPU side are ignored
12189 from this point on.
12190
12191 \c{info.topology} and, for an indirect command buffer of type
12192 QRhiIndirectCommandBuffer::IndexedDraws, \c{info.indexBuffer} have to be
12193 specified because some backends need them in order to build their native
12194 indirect command buffer object, and neither is available outside of a
12195 render pass. They must match what is set on the command buffer when
12196 executeIndirect() is called.
12197
12198 \c{info.commandCount} is the number of commands to take from
12199 \c{info.sourceBuffer}, and becomes what
12200 QRhiIndirectCommandBuffer::commandCount() reports from here on. Leaving it
12201 at 0 means \a{icb}'s QRhiIndirectCommandBuffer::maxCommandCount(); a larger
12202 value is clamped to that, with a warning. The size of
12203 \c{info.sourceBuffer} is not consulted. When \c{info.countBuffer} is set,
12204 \c{info.commandCount} becomes an upper bound instead, with the device-side
12205 count deciding how many commands are executed.
12206
12207 \note This function must be called outside of any pass. That is the entire
12208 point: it gives backends that need to run a compute shader in order to
12209 build their native indirect command buffer a place to do so without having
12210 to interrupt and restart the render pass.
12211
12212 \sa executeIndirect(), QRhiIndirectCommandBuffer
12213 */
12214void QRhiCommandBuffer::buildIndirect(QRhiIndirectCommandBuffer *icb,
12215 const QRhiIndirectCommandBufferBuildInfo &info)
12216{
12217 Q_ASSERT(icb);
12218 Q_ASSERT(info.sourceBuffer);
12219 Q_ASSERT(info.sourceBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12220 Q_ASSERT_X((info.sourceBufferOffset & 3u) == 0u, Q_FUNC_INFO,
12221 "sourceBufferOffset must be a multiple of 4");
12222 Q_ASSERT_X((info.stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
12223 Q_ASSERT(!info.countBuffer || info.countBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12224 Q_ASSERT_X((info.countBufferOffset & 3u) == 0u, Q_FUNC_INFO,
12225 "countBufferOffset must be a multiple of 4");
12226 m_rhi->buildIndirect(this, icb, info);
12227}
12228
12229/*!
12230 Records executing the commands held by the indirect command buffer \a icb,
12231 starting at \a firstCommand and executing at most \a commandCount of them.
12232 By default all commands are executed.
12233
12234 Everything else - the graphics pipeline, the vertex and index buffers, the
12235 shader resources, the viewport, the scissor - is taken from the current
12236 state of the command buffer, exactly like with drawIndirect().
12237
12238 The number of draws issued is \c{qMin(commandCount, icb->commandCount() -
12239 firstCommand)}, so leaving \a commandCount at its default executes
12240 everything from \a firstCommand onwards. What
12241 QRhiIndirectCommandBuffer::commandCount() means depends on how \a icb was
12242 populated: it is the number of draw() and drawIndexed() calls recorded on
12243 it, or, after a buildIndirect(), the count resolved from
12244 QRhiIndirectCommandBufferBuildInfo::commandCount. Nothing is drawn when \a
12245 firstCommand is at or past that count.
12246
12247 When \a icb was populated by recording draw() or drawIndexed() calls on it,
12248 the recorded contents must have been flushed with
12249 QRhiResourceUpdateBatch::commitIndirectCommandBuffer() beforehand. When it
12250 was populated with buildIndirect(), and a count buffer was specified there,
12251 the device-side count reduces the number of draws further: the number
12252 actually executed is the smallest of that, \a commandCount, and what is
12253 left in \a icb after \a firstCommand.
12254
12255 \warning With a count buffer some backends, Metal in particular, cannot combine
12256 the device-side count with a subrange. \a firstCommand and \a commandCount
12257 are then ignored, printing a warning, and all commands up to the device-side
12258 count are executed.
12259
12260 \note An indirect command buffer that was populated by recording draw() or
12261 drawIndexed() calls on it can be executed any number of times, but within
12262 one frame all those executions must use the same topology, index buffer,
12263 index buffer offset and index format: some backends bake these into their
12264 native indirect command buffer at the first executeIndirect() of the frame.
12265 A mismatch is reported with a warning, and handled by falling back to
12266 ordinary draw calls.
12267
12268 \note Unlike drawIndirect(), drawIndexedIndirect(), drawIndirectCount() and
12269 drawIndexedIndirectCount(), this never causes the render pass to be
12270 interrupted and restarted internally, whatever the number of commands.
12271 Commands built with buildIndirect() were prepared before the pass began, and
12272 CPU-recorded ones need no compute work to encode. The consequences described
12273 for those functions therefore do not apply here. Color attachment contents
12274 are not at risk, and a QRhiRenderBuffer serving as the depth-stencil buffer
12275 keeps its contents without needing QRhiRenderBuffer::NoTransientBacking.
12276
12277 \note The CPU cost of this call is not constant for a CPU-recorded indirect
12278 command buffer. When the recorded contents changed since the last execution,
12279 some backends do their per-command native encoding here rather than in
12280 QRhiResourceUpdateBatch::commitIndirectCommandBuffer(), which for a large
12281 command set re-recorded every frame can dominate the time spent between
12282 beginPass() and endPass(). See \l QRhiIndirectCommandBuffer for how the cost
12283 of CPU recording scales.
12284
12285 \note This function can only be called inside a render pass.
12286
12287 \sa buildIndirect(), drawIndirect(), QRhiIndirectCommandBuffer
12288 */
12289void QRhiCommandBuffer::executeIndirect(QRhiIndirectCommandBuffer *icb,
12290 quint32 firstCommand,
12291 quint32 commandCount)
12292{
12293 Q_ASSERT(icb);
12294 m_rhi->executeIndirect(this, icb, firstCommand, commandCount);
12295}
12296
12297/*!
12298 Records a named debug group on the command buffer with the specified \a
12299 name. This is shown in graphics debugging tools such as
12300 \l{https://renderdoc.org/}{RenderDoc} and
12301 \l{https://developer.apple.com/xcode/}{XCode}. The end of the grouping is
12302 indicated by debugMarkEnd().
12303
12304 \note Ignored when QRhi::DebugMarkers are not supported or
12305 QRhi::EnableDebugMarkers is not set.
12306
12307 \note Can be called anywhere within the frame, both inside and outside of passes.
12308 */
12309void QRhiCommandBuffer::debugMarkBegin(const QByteArray &name)
12310{
12311 m_rhi->debugMarkBegin(this, name);
12312}
12313
12314/*!
12315 Records the end of a debug group.
12316
12317 \note Ignored when QRhi::DebugMarkers are not supported or
12318 QRhi::EnableDebugMarkers is not set.
12319
12320 \note Can be called anywhere within the frame, both inside and outside of passes.
12321 */
12322void QRhiCommandBuffer::debugMarkEnd()
12323{
12324 m_rhi->debugMarkEnd(this);
12325}
12326
12327/*!
12328 Inserts a debug message \a msg into the command stream.
12329
12330 \note Ignored when QRhi::DebugMarkers are not supported or
12331 QRhi::EnableDebugMarkers is not set.
12332
12333 \note With some backends debugMarkMsg() is only supported inside a pass and
12334 is ignored when called outside a pass. With others it is recorded anywhere
12335 within the frame.
12336 */
12337void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)
12338{
12339 m_rhi->debugMarkMsg(this, msg);
12340}
12341
12342/*!
12343 Records starting a new compute pass.
12344
12345 \a resourceUpdates, when not null, specifies a resource update batch that
12346 is to be committed and then released.
12347
12348 \note Do not assume that any state or resource bindings persist between
12349 passes.
12350
12351 \note A compute pass can record setComputePipeline(), setShaderResources(),
12352 and dispatch() calls, not graphics ones. General functionality, such as,
12353 debug markers and beginExternal() is available both in render and compute
12354 passes.
12355
12356 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
12357 is reported as supported.
12358
12359 \a flags is not currently used.
12360 */
12361void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates, BeginPassFlags flags)
12362{
12363 m_rhi->beginComputePass(this, resourceUpdates, flags);
12364}
12365
12366/*!
12367 Records ending the current compute pass.
12368
12369 \a resourceUpdates, when not null, specifies a resource update batch that
12370 is to be committed and then released.
12371 */
12372void QRhiCommandBuffer::endComputePass(QRhiResourceUpdateBatch *resourceUpdates)
12373{
12374 m_rhi->endComputePass(this, resourceUpdates);
12375}
12376
12377/*!
12378 Records setting a new compute pipeline \a ps.
12379
12380 \note This function must be called before recording setShaderResources() or
12381 dispatch() commands on the command buffer.
12382
12383 \note QRhi will optimize out unnecessary invocations within a pass, so
12384 therefore overoptimizing to avoid calls to this function is not necessary
12385 on the applications' side.
12386
12387 \note This function can only be called inside a compute pass, meaning
12388 between a beginComputePass() and endComputePass() call.
12389 */
12390void QRhiCommandBuffer::setComputePipeline(QRhiComputePipeline *ps)
12391{
12392 m_rhi->setComputePipeline(this, ps);
12393}
12394
12395/*!
12396 Records dispatching compute work items, with \a x, \a y, and \a z
12397 specifying the number of local workgroups in the corresponding dimension.
12398
12399 \note This function can only be called inside a compute pass, meaning
12400 between a beginComputePass() and endComputePass() call.
12401
12402 \note \a x, \a y, and \a z must fit the limits from the underlying graphics
12403 API implementation at run time. The maximum values are typically 65535.
12404
12405 \note Watch out for possible limits on the local workgroup size as well.
12406 This is specified in the shader, for example: \c{layout(local_size_x = 16,
12407 local_size_y = 16) in;}. For example, with OpenGL the minimum value mandated
12408 by the specification for the number of invocations in a single local work
12409 group (the product of \c local_size_x, \c local_size_y, and \c local_size_z)
12410 is 1024, while with OpenGL ES (3.1) the value may be as low as 128. This
12411 means that the example given above may be rejected by some OpenGL ES
12412 implementations as the number of invocations is 256.
12413 */
12414void QRhiCommandBuffer::dispatch(int x, int y, int z)
12415{
12416 m_rhi->dispatch(this, x, y, z);
12417}
12418
12419/*!
12420 Records an indirect compute dispatch.
12421
12422 The work group counts are read by the device from \a indirectBuffer at
12423 \a indirectBufferOffset, as a single QRhiDispatchIndirectCommand.
12424 \a indirectBuffer must have QRhiBuffer::IndirectBuffer usage and
12425 \a indirectBufferOffset must be 4-byte aligned.
12426
12427 Only one dispatch per call; no native multi-dispatch variant exists.
12428 Requires \l QRhi::DispatchIndirect.
12429
12430 \note Only valid inside a compute pass.
12431
12432 \since 6.13
12433 */
12434void QRhiCommandBuffer::dispatchIndirect(QRhiBuffer *indirectBuffer,
12435 quint32 indirectBufferOffset)
12436{
12437 Q_ASSERT(indirectBuffer);
12438 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12439 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12440 m_rhi->dispatchIndirect(this, indirectBuffer, indirectBufferOffset);
12441}
12442
12443/*!
12444 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
12445 QRhiVulkanCommandBufferNativeHandles. The returned value is \nullptr when
12446 exposing the underlying native resources is not supported by, or not
12447 applicable to, the backend.
12448
12449 \sa QRhiVulkanCommandBufferNativeHandles,
12450 QRhiMetalCommandBufferNativeHandles, beginExternal(), endExternal()
12451 */
12452const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
12453{
12454 return m_rhi->nativeHandles(this);
12455}
12456
12457/*!
12458 To be called when the application before the application is about to
12459 enqueue commands to the current pass' command buffer by calling graphics
12460 API functions directly.
12461
12462 \note This is only available when the intent was declared upfront in
12463 beginPass() or beginComputePass(). Therefore this function must only be
12464 called when the pass recording was started with specifying
12465 QRhiCommandBuffer::ExternalContent.
12466
12467 With Vulkan, Metal, or Direct3D 12 one can query the native command buffer
12468 or encoder objects via nativeHandles() and enqueue commands to them. With
12469 OpenGL or Direct3D 11 the (device) context can be retrieved from
12470 QRhi::nativeHandles(). However, this must never be done without ensuring
12471 the QRhiCommandBuffer's state stays up-to-date. Hence the requirement for
12472 wrapping any externally added command recording between beginExternal() and
12473 endExternal(). Conceptually this is the same as QPainter's
12474 \l{QPainter::beginNativePainting()}{beginNativePainting()} and
12475 \l{QPainter::endNativePainting()}{endNativePainting()} functions.
12476
12477 For OpenGL in particular, this function has an additional task: it makes
12478 sure the context is made current on the current thread.
12479
12480 \note Once beginExternal() is called, no other render pass specific
12481 functions (\c set* or \c draw*) must be called on the
12482 QRhiCommandBuffer until endExternal().
12483
12484 \warning Some backends may return a native command buffer object from
12485 QRhiCommandBuffer::nativeHandles() that is different from the primary one
12486 when inside a beginExternal() - endExternal() block. Therefore it is
12487 important to (re)query the native command buffer object after calling
12488 beginExternal(). In practical terms this means that with Vulkan for example
12489 the externally recorded Vulkan commands are placed onto a secondary command
12490 buffer (with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT).
12491 nativeHandles() returns this secondary command buffer when called between
12492 begin/endExternal.
12493
12494 \sa endExternal(), nativeHandles()
12495 */
12496void QRhiCommandBuffer::beginExternal()
12497{
12498 m_rhi->beginExternal(this);
12499}
12500
12501/*!
12502 To be called once the externally added commands are recorded to the command
12503 buffer or context.
12504
12505 \note All QRhiCommandBuffer state must be assumed as invalid after calling
12506 this function. Pipelines, vertex and index buffers, and other state must be
12507 set again if more draw calls are recorded after the external commands.
12508
12509 \sa beginExternal(), nativeHandles()
12510 */
12511void QRhiCommandBuffer::endExternal()
12512{
12513 m_rhi->endExternal(this);
12514}
12515
12516/*!
12517 \return the last available timestamp, in seconds, when
12518 \l QRhi::EnableTimestamps was enabled when creating the QRhi. The value
12519 indicates the elapsed time on the GPU during the last completed frame.
12520
12521 \note Do not expect results other than 0 when the QRhi::Timestamps feature
12522 is not reported as supported, or when QRhi::EnableTimestamps was not passed
12523 to QRhi::create(). There are exceptions to this, because with some graphics
12524 APIs (Metal) timings are available without having to perform extra
12525 operations (timestamp queries), but portable applications should always
12526 consciously opt-in to timestamp collection when they know it is needed, and
12527 call this function accordingly.
12528
12529 Care must be exercised with the interpretation of the value, as its
12530 precision and granularity is often not controlled by Qt, and depends on the
12531 underlying graphics API and its implementation. In particular, comparing
12532 the values between different graphics APIs and hardware is discouraged and
12533 may be meaningless.
12534
12535 The timing values will likely become available asynchronously. The returned
12536 value may therefore be 0 (e.g., for the first 1-2 frames) or the last known
12537 value referring to some previous frame. The value my also become 0 again
12538 under certain conditions, such as when resizing the window. It can be
12539 expected that the most up-to-date available value is retrieved in
12540 beginFrame() and becomes queriable via this function once beginFrame()
12541 returns.
12542
12543 \note Do not assume that the value refers to the previous
12544 (\c{currently_recorded - 1}) frame. It may refer to \c{currently_recorded -
12545 2} or \c{currently_recorded - 3} as well. The exact behavior may depend on
12546 the graphics API and its implementation.
12547
12548 Watch out for the consequences of GPU frequency scaling and GPU clock
12549 changes, depending on the platform. For example, on Windows the returned
12550 timing may vary in a quite wide range between frames with modern graphics
12551 cards, even when submitting frames with a similar, or the same workload.
12552 This is out of scope for Qt to control and solve, generally speaking.
12553 However, the D3D12 backend automatically calls
12554 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-setstablepowerstate}{ID3D12Device::SetStablePowerState()}
12555 whenever the environment variable \c QT_D3D_STABLE_POWER_STATE is set to a
12556 non-zero value. This can greatly stabilize the result. It can also have a
12557 non-insignificant effect on the CPU-side timings measured via QElapsedTimer
12558 for example, especially when offscreen frames are involved.
12559
12560 \note Do not and never ship applications to production with
12561 \c QT_D3D_STABLE_POWER_STATE set. See the Windows API documentation for details.
12562
12563 \sa QRhi::Timestamps, QRhi::EnableTimestamps
12564 */
12565double QRhiCommandBuffer::lastCompletedGpuTime()
12566{
12567 return m_rhi->lastCompletedGpuTime(this);
12568}
12569
12570/*!
12571 \return the value (typically an offset) \a v aligned to the uniform buffer
12572 alignment given by ubufAlignment().
12573 */
12574int QRhi::ubufAligned(int v) const
12575{
12576 const int byteAlign = ubufAlignment();
12577 return (v + byteAlign - 1) & ~(byteAlign - 1);
12578}
12579
12580/*!
12581 \return the number of mip levels for a given \a size.
12582 */
12583int QRhi::mipLevelsForSize(const QSize &size)
12584{
12585 return qFloor(std::log2(qMax(size.width(), size.height()))) + 1;
12586}
12587
12588/*!
12589 \return the texture image size for a given \a mipLevel, calculated based on
12590 the level 0 size given in \a baseLevelSize.
12591 */
12592QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)
12593{
12594 const int w = qMax(1, baseLevelSize.width() >> mipLevel);
12595 const int h = qMax(1, baseLevelSize.height() >> mipLevel);
12596 return QSize(w, h);
12597}
12598
12599/*!
12600 \return \c true if the underlying graphics API has the Y axis pointing up
12601 in framebuffers and images.
12602
12603 In practice this is \c true for OpenGL only.
12604 */
12605bool QRhi::isYUpInFramebuffer() const
12606{
12607 return d->isYUpInFramebuffer();
12608}
12609
12610/*!
12611 \return \c true if the underlying graphics API has the Y axis pointing up
12612 in its normalized device coordinate system.
12613
12614 In practice this is \c false for Vulkan only.
12615
12616 \note clipSpaceCorrMatrix() includes the corresponding adjustment (to make
12617 Y point up) in its returned matrix.
12618 */
12619bool QRhi::isYUpInNDC() const
12620{
12621 return d->isYUpInNDC();
12622}
12623
12624/*!
12625 \return \c true if the underlying graphics API uses depth range [0, 1] in
12626 clip space.
12627
12628 In practice this is \c false for OpenGL only, because OpenGL uses a
12629 post-projection depth range of [-1, 1]. (not to be confused with the
12630 NDC-to-window mapping controlled by glDepthRange(), which uses a range of
12631 [0, 1], unless overridden by the QRhiViewport) In some OpenGL versions
12632 glClipControl() could be used to change this, but the OpenGL backend of
12633 QRhi does not use that function as it is not available in OpenGL ES or
12634 OpenGL versions lower than 4.5.
12635
12636 \note clipSpaceCorrMatrix() includes the corresponding adjustment in its
12637 returned matrix. Therefore, many users of QRhi do not need to take any
12638 further measures apart from pre-multiplying their projection matrices with
12639 clipSpaceCorrMatrix(). However, some graphics techniques, such as, some
12640 types of shadow mapping, involve working with and outputting depth values
12641 in the shaders. These will need to query and take the value of this
12642 function into account as appropriate.
12643 */
12644bool QRhi::isClipDepthZeroToOne() const
12645{
12646 return d->isClipDepthZeroToOne();
12647}
12648
12649/*!
12650 \return a matrix that can be used to allow applications keep using
12651 OpenGL-targeted vertex data and perspective projection matrices (such as,
12652 the ones generated by QMatrix4x4::perspective()), regardless of the active
12653 QRhi backend.
12654
12655 In a typical renderer, once \c{this_matrix * mvp} is used instead of just
12656 \c mvp, vertex data with Y up and viewports with depth range 0 - 1 can be
12657 used without considering what backend (and so graphics API) is going to be
12658 used at run time. This way branching based on isYUpInNDC() and
12659 isClipDepthZeroToOne() can be avoided (although such logic may still become
12660 required when implementing certain advanced graphics techniques).
12661
12662 See
12663 \l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this
12664 page} for a discussion of the topic from Vulkan perspective.
12665 */
12666QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
12667{
12668 return d->clipSpaceCorrMatrix();
12669}
12670
12671/*!
12672 \return \c true if the specified texture \a format modified by \a flags is
12673 supported.
12674
12675 The query is supported both for uncompressed and compressed formats.
12676 */
12677bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
12678{
12679 return d->isTextureFormatSupported(format, flags);
12680}
12681
12682/*!
12683 \return \c true if the specified \a feature is supported
12684 */
12685bool QRhi::isFeatureSupported(QRhi::Feature feature) const
12686{
12687 return d->isFeatureSupported(feature);
12688}
12689
12690/*!
12691 \return the value for the specified resource \a limit.
12692
12693 The values are expected to be queried by the backends upon initialization,
12694 meaning calling this function is a light operation.
12695 */
12696int QRhi::resourceLimit(ResourceLimit limit) const
12697{
12698 return d->resourceLimit(limit);
12699}
12700
12701/*!
12702 \return a pointer to the backend-specific collection of native objects
12703 for the device, context, and similar concepts used by the backend.
12704
12705 Cast to QRhiVulkanNativeHandles, QRhiD3D11NativeHandles,
12706 QRhiD3D12NativeHandles, QRhiGles2NativeHandles, or QRhiMetalNativeHandles
12707 as appropriate.
12708
12709 \note No ownership is transferred, neither for the returned pointer nor for
12710 any native objects.
12711 */
12712const QRhiNativeHandles *QRhi::nativeHandles()
12713{
12714 return d->nativeHandles();
12715}
12716
12717/*!
12718 With OpenGL this makes the OpenGL context current on the current thread.
12719 The function has no effect with other backends.
12720
12721 Calling this function is relevant typically in Qt framework code, when one
12722 has to ensure external OpenGL code provided by the application can still
12723 run like it did before with direct usage of OpenGL, as long as the QRhi is
12724 using the OpenGL backend.
12725
12726 \return false when failed, similarly to QOpenGLContext::makeCurrent(). When
12727 the operation failed, isDeviceLost() can be called to determine if there
12728 was a loss of context situation. Such a check is equivalent to checking via
12729 QOpenGLContext::isValid().
12730
12731 \sa QOpenGLContext::makeCurrent(), QOpenGLContext::isValid()
12732 */
12733bool QRhi::makeThreadLocalNativeContextCurrent()
12734{
12735 return d->makeThreadLocalNativeContextCurrent();
12736}
12737
12738/*!
12739 With backends and graphics APIs where applicable, this function allows to
12740 provide additional arguments to the \b next submission of commands to the
12741 graphics command queue.
12742
12743 In particular, with Vulkan this allows passing in a list of Vulkan semaphore
12744 objects for \c vkQueueSubmit() to signal and wait on. \a params must then be
12745 a \l QRhiVulkanQueueSubmitParams. This becomes essential in certain advanced
12746 use cases, such as when performing native Vulkan calls that involve having
12747 to wait on and signal VkSemaphores that the application's custom Vulkan
12748 rendering or compute code manages. In addition, this also allows specifying
12749 additional semaphores to wait on in the next \c vkQueuePresentKHR().
12750
12751 \note This function affects the next queue submission only, which will
12752 happen in endFrame(), endOffscreenFrame(), or finish(). The enqueuing of
12753 present happens in endFrame().
12754
12755 With many other backends the implementation of this function is a no-op.
12756
12757 \since 6.9
12758 */
12759void QRhi::setQueueSubmitParams(QRhiNativeHandles *params)
12760{
12761 d->setQueueSubmitParams(params);
12762}
12763
12764/*!
12765 Attempts to release resources in the backend's caches. This can include both
12766 CPU and GPU resources. Only memory and resources that can be recreated
12767 automatically are in scope. As an example, if the backend's
12768 QRhiGraphicsPipeline implementation maintains a cache of shader compilation
12769 results, calling this function leads to emptying that cache, thus
12770 potentially freeing up memory and graphics resources.
12771
12772 Calling this function makes sense in resource constrained environments,
12773 where at a certain point there is a need to ensure minimal resource usage,
12774 at the expense of performance.
12775 */
12776void QRhi::releaseCachedResources()
12777{
12778 d->releaseCachedResources();
12779
12780 for (QRhiResourceUpdateBatch *u : d->resUpdPool) {
12781 if (u->d->poolIndex < 0)
12782 u->d->trimOpLists();
12783 }
12784}
12785
12786/*!
12787 \return true if the graphics device was lost.
12788
12789 The loss of the device is typically detected in beginFrame(), endFrame() or
12790 QRhiSwapChain::createOrResize(), depending on the backend and the underlying
12791 native APIs. The most common is endFrame() because that is where presenting
12792 happens. With some backends QRhiSwapChain::createOrResize() can also fail
12793 due to a device loss. Therefore this function is provided as a generic way
12794 to check if a device loss was detected by a previous operation.
12795
12796 When the device is lost, no further operations should be done via the QRhi.
12797 Rather, all QRhi resources should be released, followed by destroying the
12798 QRhi. A new QRhi can then be attempted to be created. If successful, all
12799 graphics resources must be reinitialized. If not, try again later,
12800 repeatedly.
12801
12802 While simple applications may decide to not care about device loss,
12803 on the commonly used desktop platforms a device loss can happen
12804 due to a variety of reasons, including physically disconnecting the
12805 graphics adapter, disabling the device or driver, uninstalling or upgrading
12806 the graphics driver, or due to errors that lead to a graphics device reset.
12807 Some of these can happen under perfectly normal circumstances as well, for
12808 example the upgrade of the graphics driver to a newer version is a common
12809 task that can happen at any time while a Qt application is running. Users
12810 may very well expect applications to be able to survive this, even when the
12811 application is actively using an API like OpenGL or Direct3D.
12812
12813 Qt's own frameworks built on top of QRhi, such as, Qt Quick, can be
12814 expected to handle and take appropriate measures when a device loss occurs.
12815 If the data for graphics resources, such as textures and buffers, are still
12816 available on the CPU side, such an event may not be noticeable on the
12817 application level at all since graphics resources can seamlessly be
12818 reinitialized then. However, applications and libraries working directly
12819 with QRhi are expected to be prepared to check and handle device loss
12820 situations themselves.
12821
12822 \note With OpenGL, applications may need to opt-in to context reset
12823 notifications by setting QSurfaceFormat::ResetNotification on the
12824 QOpenGLContext. This is typically done by enabling the flag in
12825 QRhiGles2InitParams::format. Keep in mind however that some systems may
12826 generate context resets situations even when this flag is not set.
12827 */
12828bool QRhi::isDeviceLost() const
12829{
12830 return d->isDeviceLost();
12831}
12832
12833/*!
12834 \return a binary data blob with data collected from the
12835 QRhiGraphicsPipeline and QRhiComputePipeline successfully created during
12836 the lifetime of this QRhi.
12837
12838 By saving and then, in subsequent runs of the same application, reloading
12839 the cache data, pipeline and shader creation times can potentially be
12840 reduced. What exactly the cache and its serialized version includes is not
12841 specified, is always specific to the backend used, and in some cases also
12842 dependent on the particular implementation of the graphics API.
12843
12844 When the PipelineCacheDataLoadSave is reported as unsupported, the returned
12845 QByteArray is empty.
12846
12847 When the EnablePipelineCacheDataSave flag was not specified when calling
12848 create(), the returned QByteArray may be empty, even when the
12849 PipelineCacheDataLoadSave feature is supported.
12850
12851 When the returned data is non-empty, it is always specific to the Qt
12852 version and QRhi backend. In addition, in some cases there is a strong
12853 dependency to the graphics device and the exact driver version used. QRhi
12854 takes care of adding the appropriate header and safeguards that ensure that
12855 the data can always be passed safely to setPipelineCacheData(), therefore
12856 attempting to load data from a run on another version of a driver will be
12857 handled safely and gracefully.
12858
12859 \note Calling releaseCachedResources() may, depending on the backend, clear
12860 the pipeline data collected. A subsequent call to this function may then
12861 not return any data.
12862
12863 See EnablePipelineCacheDataSave for further details about this feature.
12864
12865 \note Minimize the number of calls to this function. Retrieving the blob is
12866 not always a cheap operation, and therefore this function should only be
12867 called at a low frequency, ideally only once e.g. when closing the
12868 application.
12869
12870 \sa setPipelineCacheData(), create(), isFeatureSupported()
12871 */
12872QByteArray QRhi::pipelineCacheData()
12873{
12874 return d->pipelineCacheData();
12875}
12876
12877/*!
12878 Loads \a data into the pipeline cache, when applicable.
12879
12880 When the PipelineCacheDataLoadSave is reported as unsupported, the function
12881 is safe to call, but has no effect.
12882
12883 The blob returned by pipelineCacheData() is always specific to the Qt
12884 version, the QRhi backend, and, in some cases, also to the graphics device,
12885 and a given version of the graphics driver. QRhi takes care of adding the
12886 appropriate header and safeguards that ensure that the data can always be
12887 passed safely to this function. If there is a mismatch, e.g. because the
12888 driver has been upgraded to a newer version, or because the data was
12889 generated from a different QRhi backend, a warning is printed and \a data
12890 is safely ignored.
12891
12892 With Vulkan, this maps directly to VkPipelineCache. Calling this function
12893 creates a new Vulkan pipeline cache object, with its initial data sourced
12894 from \a data. The pipeline cache object is then used by all subsequently
12895 created QRhiGraphicsPipeline and QRhiComputePipeline objects, thus
12896 accelerating, potentially, the pipeline creation.
12897
12898 With other APIs there is no real pipeline cache, but they may provide a
12899 cache with bytecode from shader compilations (D3D) or program binaries
12900 (OpenGL). In applications that perform a lot of shader compilation from
12901 source at run time this can provide a significant boost in subsequent runs
12902 if the "pipeline cache" is pre-seeded from an earlier run using this
12903 function.
12904
12905 \note QRhi cannot give any guarantees that \a data has an effect on the
12906 pipeline and shader creation performance. With APIs like Vulkan, it is up
12907 to the driver to decide if \a data is used for some purpose, or if it is
12908 ignored.
12909
12910 See EnablePipelineCacheDataSave for further details about this feature.
12911
12912 \note This mechanism offered by QRhi is independent of the drivers' own
12913 internal caching mechanism, if any. This means that, depending on the
12914 graphics API and its implementation, the exact effects of retrieving and
12915 then reloading \a data are not predictable. Improved performance may not be
12916 visible at all in case other caching mechanisms outside of Qt's control are
12917 already active.
12918
12919 \note Minimize the number of calls to this function. Loading the blob is
12920 not always a cheap operation, and therefore this function should only be
12921 called at a low frequency, ideally only once e.g. when starting the
12922 application.
12923
12924 \warning Serialized pipeline cache data is assumed to be trusted content. Qt
12925 performs robust parsing of the header and metadata included in \a data,
12926 application developers are however advised to never pass in data from
12927 untrusted sources.
12928
12929 \sa pipelineCacheData(), isFeatureSupported()
12930 */
12931void QRhi::setPipelineCacheData(const QByteArray &data)
12932{
12933 d->setPipelineCacheData(data);
12934}
12935
12936/*!
12937 \struct QRhiStats
12938 \inmodule QtGuiPrivate
12939 \inheaderfile rhi/qrhi.h
12940 \since 6.6
12941
12942 \brief Statistics provided from the underlying memory allocator.
12943
12944 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
12945 for details.
12946 */
12947
12948/*!
12949 \variable QRhiStats::totalPipelineCreationTime
12950
12951 The total time in milliseconds spent in graphics and compute pipeline
12952 creation, which usually involves shader compilation or cache lookups, and
12953 potentially expensive processing.
12954
12955 \note The value should not be compared between different backends since the
12956 concept of "pipelines" and what exactly happens under the hood during, for
12957 instance, a call to QRhiGraphicsPipeline::create(), differ greatly between
12958 graphics APIs and their implementations.
12959
12960 \sa QRhi::statistics()
12961*/
12962
12963/*!
12964 \variable QRhiStats::blockCount
12965
12966 Statistic reported from the Vulkan or D3D12 memory allocator.
12967
12968 \sa QRhi::statistics()
12969*/
12970
12971/*!
12972 \variable QRhiStats::allocCount
12973
12974 Statistic reported from the Vulkan or D3D12 memory allocator.
12975
12976 \sa QRhi::statistics()
12977*/
12978
12979/*!
12980 \variable QRhiStats::usedBytes
12981
12982 Statistic reported from the Vulkan or D3D12 memory allocator.
12983
12984 \sa QRhi::statistics()
12985*/
12986
12987/*!
12988 \variable QRhiStats::unusedBytes
12989
12990 Statistic reported from the Vulkan or D3D12 memory allocator.
12991
12992 \sa QRhi::statistics()
12993*/
12994
12995/*!
12996 \variable QRhiStats::totalUsageBytes
12997
12998 Valid only with D3D12 currently. Matches IDXGIAdapter3::QueryVideoMemoryInfo().
12999
13000 \sa QRhi::statistics()
13001*/
13002
13003#ifndef QT_NO_DEBUG_STREAM
13004QDebug operator<<(QDebug dbg, const QRhiStats &info)
13005{
13006 QDebugStateSaver saver(dbg);
13007 dbg.nospace() << "QRhiStats("
13008 << "totalPipelineCreationTime=" << info.totalPipelineCreationTime
13009 << " blockCount=" << info.blockCount
13010 << " allocCount=" << info.allocCount
13011 << " usedBytes=" << info.usedBytes
13012 << " unusedBytes=" << info.unusedBytes
13013 << " totalUsageBytes=" << info.totalUsageBytes
13014 << ')';
13015 return dbg;
13016}
13017#endif
13018
13019/*!
13020 Gathers and returns statistics about the timings and allocations of
13021 graphics resources.
13022
13023 Data about memory allocations is only available with some backends, where
13024 such operations are under Qt's control. With graphics APIs where there is
13025 no lower level control over resource memory allocations, this will never be
13026 supported and all relevant fields in the results are 0.
13027
13028 With Vulkan in particular, the values are valid always, and are queried
13029 from the underlying memory allocator library. This gives an insight into
13030 the memory requirements of the active buffers and textures.
13031
13032 The same is true for Direct 3D 12. In addition to the memory allocator
13033 library's statistics, here the result also includes a \c totalUsageBytes
13034 field which reports the total size including additional resources that are
13035 not under the memory allocator library's control (swapchain buffers,
13036 descriptor heaps, etc.), as reported by DXGI.
13037
13038 The values correspond to all types of memory used, combined. (i.e. video +
13039 system in case of a discreet GPU)
13040
13041 Additional data, such as the total time in milliseconds spent in graphics
13042 and compute pipeline creation (which usually involves shader compilation or
13043 cache lookups, and potentially expensive processing) is available with most
13044 backends.
13045
13046 \note The elapsed times for operations such as pipeline creation may be
13047 affected by various factors. The results should not be compared between
13048 different backends since the concept of "pipelines" and what exactly
13049 happens under the hood during, for instance, a call to
13050 QRhiGraphicsPipeline::create(), differ greatly between graphics APIs and
13051 their implementations.
13052
13053 \note Additionally, many drivers will likely employ various caching
13054 strategies for shaders, programs, pipelines. (independently of Qt's own
13055 similar facilities, such as setPipelineCacheData() or the OpenGL-specific
13056 program binary disk cache). Because such internal behavior is transparent
13057 to the API client, Qt and QRhi have no knowledge or control over the exact
13058 caching strategy, persistency, invalidation of the cached data, etc. When
13059 reading timings, such as the time spent on pipeline creation, the potential
13060 presence and unspecified behavior of driver-level caching mechanisms should
13061 be kept in mind.
13062 */
13063QRhiStats QRhi::statistics() const
13064{
13065 return d->statistics();
13066}
13067
13068/*!
13069 \return a new graphics pipeline resource.
13070
13071 \sa QRhiResource::destroy()
13072 */
13073QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
13074{
13075 return d->createGraphicsPipeline();
13076}
13077
13078/*!
13079 \return a new compute pipeline resource.
13080
13081 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
13082 is reported as supported.
13083
13084 \sa QRhiResource::destroy()
13085 */
13086QRhiComputePipeline *QRhi::newComputePipeline()
13087{
13088 return d->createComputePipeline();
13089}
13090
13091/*!
13092 \return a new shader resource binding collection resource.
13093
13094 \sa QRhiResource::destroy()
13095 */
13096QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
13097{
13098 return d->createShaderResourceBindings();
13099}
13100
13101/*!
13102 \return a new buffer with the specified \a type, \a usage, and \a size.
13103
13104 \note Some \a usage and \a type combinations may not be supported by all
13105 backends. See \l{QRhiBuffer::UsageFlag}{UsageFlags} and
13106 \l{QRhi::NonDynamicUniformBuffers}{the feature flags}.
13107
13108 \note Backends may choose to allocate buffers bigger than \a size. This is
13109 done transparently to applications, so there are no special restrictions on
13110 the value of \a size. QRhiBuffer::size() will always report back the value
13111 that was requested in \a size.
13112
13113 \sa QRhiResource::destroy()
13114 */
13115QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type,
13116 QRhiBuffer::UsageFlags usage,
13117 quint32 size)
13118{
13119 return d->createBuffer(type, usage, size);
13120}
13121
13122/*!
13123 \return a new renderbuffer with the specified \a type, \a pixelSize, \a
13124 sampleCount, and \a flags.
13125
13126 When \a backingFormatHint is set to a texture format other than
13127 QRhiTexture::UnknownFormat, it may be used by the backend to decide what
13128 format to use for the storage backing the renderbuffer.
13129
13130 \note \a backingFormatHint becomes relevant typically when multisampling
13131 and floating point texture formats are involved: rendering into a
13132 multisample QRhiRenderBuffer and then resolving into a non-RGBA8
13133 QRhiTexture implies (with some graphics APIs) that the storage backing the
13134 QRhiRenderBuffer uses the matching non-RGBA8 format. That means that
13135 passing a format like QRhiTexture::RGBA32F is important, because backends
13136 will typically opt for QRhiTexture::RGBA8 by default, which would then
13137 break later on due to attempting to set up RGBA8->RGBA32F multisample
13138 resolve in the color attachment(s) of the QRhiTextureRenderTarget.
13139
13140 \sa QRhiResource::destroy()
13141 */
13142QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type,
13143 const QSize &pixelSize,
13144 int sampleCount,
13145 QRhiRenderBuffer::Flags flags,
13146 QRhiTexture::Format backingFormatHint)
13147{
13148 return d->createRenderBuffer(type, pixelSize, sampleCount, flags, backingFormatHint);
13149}
13150
13151/*!
13152 \return a new 1D or 2D texture with the specified \a format, \a pixelSize, \a
13153 sampleCount, and \a flags.
13154
13155 A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This
13156 function will implicitly set this flag if the \a pixelSize height is 0.
13157
13158 \note \a format specifies the requested internal and external format,
13159 meaning the data to be uploaded to the texture will need to be in a
13160 compatible format, while the native texture may (but is not guaranteed to,
13161 in case of OpenGL at least) use this format internally.
13162
13163 \note 1D textures are only functional when the OneDimensionalTextures feature is
13164 reported as supported at run time. Further, mipmaps on 1D textures are only
13165 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
13166
13167 \sa QRhiResource::destroy()
13168 */
13169QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
13170 const QSize &pixelSize,
13171 int sampleCount,
13172 QRhiTexture::Flags flags)
13173{
13174 if (pixelSize.height() == 0)
13175 flags |= QRhiTexture::OneDimensional;
13176
13177 return d->createTexture(format, pixelSize, 1, 0, sampleCount, flags);
13178}
13179
13180/*!
13181 \return a new 1D, 2D or 3D texture with the specified \a format, \a width, \a
13182 height, \a depth, \a sampleCount, and \a flags.
13183
13184 This overload is suitable for 3D textures because it allows specifying \a
13185 depth. A 3D texture must have QRhiTexture::ThreeDimensional set in \a
13186 flags, but using this overload that can be omitted because the flag is set
13187 implicitly whenever \a depth is greater than 0. For 1D, 2D and cube textures \a
13188 depth should be set to 0.
13189
13190 A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This overload
13191 will implicitly set this flag if both \a height and \a depth are 0.
13192
13193 \note 3D textures are only functional when the ThreeDimensionalTextures
13194 feature is reported as supported at run time.
13195
13196 \note 1D textures are only functional when the OneDimensionalTextures feature is
13197 reported as supported at run time. Further, mipmaps on 1D textures are only
13198 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
13199
13200 \overload
13201 */
13202QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
13203 int width, int height, int depth,
13204 int sampleCount,
13205 QRhiTexture::Flags flags)
13206{
13207 if (depth > 0)
13208 flags |= QRhiTexture::ThreeDimensional;
13209
13210 if (height == 0 && depth == 0)
13211 flags |= QRhiTexture::OneDimensional;
13212
13213 return d->createTexture(format, QSize(width, height), depth, 0, sampleCount, flags);
13214}
13215
13216/*!
13217 \return a new 1D or 2D texture array with the specified \a format, \a arraySize,
13218 \a pixelSize, \a sampleCount, and \a flags.
13219
13220 This function implicitly sets QRhiTexture::TextureArray in \a flags.
13221
13222 A 1D texture array must have QRhiTexture::OneDimensional set in \a flags. This
13223 function will implicitly set this flag if the \a pixelSize height is 0.
13224
13225 \note Do not confuse texture arrays with arrays of textures. A QRhiTexture
13226 created by this function is usable with 1D or 2D array samplers in the shader, for
13227 example: \c{layout(binding = 1) uniform sampler2DArray texArr;}. Arrays of
13228 textures refers to a list of textures that are exposed to the shader via
13229 QRhiShaderResourceBinding::sampledTextures() and a count > 1, and declared
13230 in the shader for example like this: \c{layout(binding = 1) uniform
13231 sampler2D textures[4];}
13232
13233 \note This is only functional when the TextureArrays feature is reported as
13234 supported at run time.
13235
13236 \note 1D textures are only functional when the OneDimensionalTextures feature is
13237 reported as supported at run time. Further, mipmaps on 1D textures are only
13238 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
13239
13240
13241 \sa newTexture()
13242 */
13243QRhiTexture *QRhi::newTextureArray(QRhiTexture::Format format,
13244 int arraySize,
13245 const QSize &pixelSize,
13246 int sampleCount,
13247 QRhiTexture::Flags flags)
13248{
13249 flags |= QRhiTexture::TextureArray;
13250
13251 if (pixelSize.height() == 0)
13252 flags |= QRhiTexture::OneDimensional;
13253
13254 return d->createTexture(format, pixelSize, 1, arraySize, sampleCount, flags);
13255}
13256
13257/*!
13258 \return a new sampler with the specified magnification filter \a magFilter,
13259 minification filter \a minFilter, mipmapping mode \a mipmapMode, and the
13260 addressing (wrap) modes \a addressU, \a addressV, and \a addressW.
13261
13262 \note Setting \a mipmapMode to a value other than \c None implies that
13263 images for all relevant mip levels will be provided either via
13264 \l{QRhiResourceUpdateBatch::uploadTexture()}{texture uploads} or by calling
13265 \l{QRhiResourceUpdateBatch::generateMips()}{generateMips()} on the texture
13266 that is used with this sampler. Attempting to use the sampler with a
13267 texture that has no data for all relevant mip levels will lead to rendering
13268 errors, with the exact behavior dependent on the underlying graphics API.
13269
13270 \sa QRhiResource::destroy()
13271 */
13272QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter,
13273 QRhiSampler::Filter minFilter,
13274 QRhiSampler::Filter mipmapMode,
13275 QRhiSampler::AddressMode addressU,
13276 QRhiSampler::AddressMode addressV,
13277 QRhiSampler::AddressMode addressW)
13278{
13279 return d->createSampler(magFilter, minFilter, mipmapMode, addressU, addressV, addressW);
13280}
13281
13282/*!
13283 \return a new shading rate map object.
13284
13285 \since 6.9
13286 */
13287QRhiShadingRateMap *QRhi::newShadingRateMap()
13288{
13289 return d->createShadingRateMap();
13290}
13291
13292/*!
13293 \return a new indirect command buffer that holds commands of the specified
13294 \a type, with room for \a maxCommandCount of them.
13295
13296 \a maxCommandCount cannot be 0, otherwise create() fails. It is the upper
13297 bound for both ways of providing commands: recording them with
13298 QRhiIndirectCommandBuffer::draw() or
13299 QRhiIndirectCommandBuffer::drawIndexed(), and generating them on the GPU
13300 and calling QRhiCommandBuffer::buildIndirect(). Backends allocate their
13301 native objects, and the QRhiBuffer holding the recorded commands, based on
13302 it, which is why it is fixed up front instead of growing on demand.
13303
13304 \sa QRhiIndirectCommandBuffer::setMaxCommandCount(), QRhiIndirectCommandBuffer
13305
13306 \since 6.13
13307 */
13308QRhiIndirectCommandBuffer *QRhi::newIndirectCommandBuffer(QRhiIndirectCommandBuffer::Type type,
13309 quint32 maxCommandCount)
13310{
13311 return d->createIndirectCommandBuffer(type, maxCommandCount);
13312}
13313
13314/*!
13315 \return a new texture render target with color and depth/stencil
13316 attachments given in \a desc, and with the specified \a flags.
13317
13318 \sa QRhiResource::destroy()
13319 */
13320
13321QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
13322 QRhiTextureRenderTarget::Flags flags)
13323{
13324 return d->createTextureRenderTarget(desc, flags);
13325}
13326
13327/*!
13328 \return a new swapchain.
13329
13330 \sa QRhiResource::destroy(), QRhiSwapChain::createOrResize()
13331 */
13332QRhiSwapChain *QRhi::newSwapChain()
13333{
13334 return d->createSwapChain();
13335}
13336
13337/*!
13338 Starts a new frame targeting the next available buffer of \a swapChain.
13339
13340 A frame consists of resource updates and one or more render and compute
13341 passes.
13342
13343 \a flags can indicate certain special cases.
13344
13345 The high level pattern of rendering into a QWindow using a swapchain:
13346
13347 \list
13348
13349 \li Create a swapchain.
13350
13351 \li Call QRhiSwapChain::createOrResize() whenever the surface size is
13352 different than before.
13353
13354 \li Call QRhiSwapChain::destroy() on
13355 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed.
13356
13357 \li Then on every frame:
13358 \badcode
13359 beginFrame(sc);
13360 updates = nextResourceUpdateBatch();
13361 updates->...
13362 QRhiCommandBuffer *cb = sc->currentFrameCommandBuffer();
13363 cb->beginPass(sc->currentFrameRenderTarget(), colorClear, dsClear, updates);
13364 ...
13365 cb->endPass();
13366 ... // more passes as necessary
13367 endFrame(sc);
13368 \endcode
13369
13370 \endlist
13371
13372 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
13373 value on failure. Some of these should be treated as soft, "try again
13374 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
13375 the swapchain is to be resized or updated by calling
13376 QRhiSwapChain::createOrResize(). The application should then attempt to
13377 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
13378 lost but this may also be recoverable by releasing all resources, including
13379 the QRhi itself, and then recreating all resources. See isDeviceLost() for
13380 further discussion.
13381
13382 \sa endFrame(), beginOffscreenFrame(), isDeviceLost()
13383 */
13384QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
13385{
13386 if (d->inFrame)
13387 qWarning("Attempted to call beginFrame() within a still active frame; ignored");
13388
13389 qCDebug(QRHI_LOG_RUB) << "[rub] new frame";
13390
13391 QRhi::FrameOpResult r = !d->inFrame ? d->beginFrame(swapChain, flags) : FrameOpSuccess;
13392 if (r == FrameOpSuccess)
13393 d->inFrame = true;
13394
13395 return r;
13396}
13397
13398/*!
13399 Ends, commits, and presents a frame that was started in the last
13400 beginFrame() on \a swapChain.
13401
13402 Double (or triple) buffering is managed internally by the QRhiSwapChain and
13403 QRhi.
13404
13405 \a flags can optionally be used to change the behavior in certain ways.
13406 Passing QRhi::SkipPresent skips queuing the Present command or calling
13407 swapBuffers.
13408
13409 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
13410 value on failure. Some of these should be treated as soft, "try again
13411 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
13412 the swapchain is to be resized or updated by calling
13413 QRhiSwapChain::createOrResize(). The application should then attempt to
13414 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
13415 lost but this may also be recoverable by releasing all resources, including
13416 the QRhi itself, and then recreating all resources. See isDeviceLost() for
13417 further discussion.
13418
13419 \sa beginFrame(), isDeviceLost()
13420 */
13421QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags)
13422{
13423 const bool wasInFrame = d->inFrame;
13424 if (!wasInFrame)
13425 qWarning("Attempted to call endFrame() without an active frame; ignored");
13426
13427 QRhi::FrameOpResult r = wasInFrame ? d->endFrame(swapChain, flags) : FrameOpSuccess;
13428 d->inFrame = false;
13429 // deleteLater is a high level QRhi concept the backends know
13430 // nothing about - handle it here.
13431 qDeleteAll(d->pendingDeleteResources);
13432 d->pendingDeleteResources.clear();
13433
13434 if (wasInFrame && qrhiDebugHooks.frameEnd) {
13435 QRhiCommandBuffer *cb = (r == FrameOpSuccess && swapChain)
13436 ? swapChain->currentFrameCommandBuffer() : nullptr;
13437 qrhiDebugHooks.frameEnd(d, swapChain, cb);
13438 }
13439
13440 return r;
13441}
13442
13443/*!
13444 \return true when there is an active frame, meaning there was a
13445 beginFrame() (or beginOffscreenFrame()) with no corresponding endFrame()
13446 (or endOffscreenFrame()) yet.
13447
13448 \sa currentFrameSlot(), beginFrame(), endFrame()
13449 */
13450bool QRhi::isRecordingFrame() const
13451{
13452 return d->inFrame;
13453}
13454
13455/*!
13456 \return the current frame slot index while recording a frame. Unspecified
13457 when called outside an active frame (that is, when isRecordingFrame() is \c
13458 false).
13459
13460 With backends like Vulkan or Metal, it is the responsibility of the QRhi
13461 backend to block whenever starting a new frame and finding the CPU is
13462 already \c{FramesInFlight - 1} frames ahead of the GPU (because the command
13463 buffer submitted in frame no. \c{current} - \c{FramesInFlight} has not yet
13464 completed).
13465
13466 Resources that tend to change between frames (such as, the native buffer
13467 object backing a QRhiBuffer with type QRhiBuffer::Dynamic) exist in
13468 multiple versions, so that each frame, that can be submitted while a
13469 previous one is still being processed, works with its own copy, thus
13470 avoiding the need to stall the pipeline when preparing the frame. (The
13471 contents of a resource that may still be in use in the GPU should not be
13472 touched, but simply always waiting for the previous frame to finish would
13473 reduce GPU utilization and ultimately, performance and efficiency.)
13474
13475 Conceptually this is somewhat similar to copy-on-write schemes used by some
13476 C++ containers and other types. It may also be similar to what an OpenGL or
13477 Direct 3D 11 implementation performs internally for certain type of objects.
13478
13479 In practice, such double (or triple) buffering resources is realized in
13480 the Vulkan, Metal, and similar QRhi backends by having a fixed number of
13481 native resource (such as, VkBuffer) \c slots behind a QRhiResource. That
13482 can then be indexed by a frame slot index running 0, 1, ..,
13483 FramesInFlight-1, and then wrapping around.
13484
13485 All this is managed transparently to the users of QRhi. However,
13486 applications that integrate rendering done directly with the graphics API
13487 may want to perform a similar double or triple buffering of their own
13488 graphics resources. That is then most easily achieved by knowing the values
13489 of the maximum number of in-flight frames (retrievable via resourceLimit())
13490 and the current frame (slot) index (returned by this function).
13491
13492 \sa isRecordingFrame(), beginFrame(), endFrame()
13493 */
13494int QRhi::currentFrameSlot() const
13495{
13496 return d->currentFrameSlot;
13497}
13498
13499/*!
13500 Starts a new offscreen frame. Provides a command buffer suitable for
13501 recording rendering commands in \a cb. \a flags is used to indicate
13502 certain special cases, just like with beginFrame().
13503
13504 \note The QRhiCommandBuffer stored to *cb is not owned by the caller.
13505
13506 Rendering without a swapchain is possible as well. The typical use case is
13507 to use it in completely offscreen applications, e.g. to generate image
13508 sequences by rendering and reading back without ever showing a window.
13509
13510 Usage in on-screen applications (so beginFrame, endFrame,
13511 beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) is possible too.
13512
13513 When a \l{QRhiResourceUpdateBatch::readBackTexture()}{texture} or
13514 \l{QRhiResourceUpdateBatch::readBackBuffer()}{buffer} readback was
13515 scheduled, offscreen frames do not let the CPU potentially generate another
13516 frame while the GPU is still processing the previous one. This has the side
13517 effect that if readbacks are scheduled, the results are guaranteed to be
13518 available once endOffscreenFrame() returns. That is not the case with frames
13519 targeting a swapchain: there the GPU is potentially better utilized, but
13520 working with readback operations needs more care from the application
13521 because endFrame(), unlike endOffscreenFrame(), does not guarantee that the
13522 results from the readback are available at that point.
13523
13524 The skeleton of rendering a frame without a swapchain and then reading the
13525 frame contents back could look like the following:
13526
13527 \code
13528 QRhiReadbackResult rbResult;
13529 QRhiCommandBuffer *cb;
13530 rhi->beginOffscreenFrame(&cb);
13531 cb->beginPass(rt, colorClear, dsClear);
13532 // ...
13533 u = nextResourceUpdateBatch();
13534 u->readBackTexture(rb, &rbResult);
13535 cb->endPass(u);
13536 rhi->endOffscreenFrame();
13537 // image data available in rbResult
13538 \endcode
13539
13540 \sa endOffscreenFrame(), beginFrame()
13541 */
13542QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags)
13543{
13544 const bool wasInFrame = d->inFrame;
13545 if (wasInFrame)
13546 qWarning("Attempted to call beginOffscreenFrame() within a still active frame; ignored");
13547
13548 qCDebug(QRHI_LOG_RUB) << "[rub] new offscreen frame";
13549
13550 QRhi::FrameOpResult r = !wasInFrame ? d->beginOffscreenFrame(cb, flags) : FrameOpSuccess;
13551 if (r == FrameOpSuccess) {
13552 d->inFrame = true;
13553 if (!wasInFrame)
13554 d->currentOffscreenCb = *cb;
13555 }
13556
13557 return r;
13558}
13559
13560/*!
13561 Ends, submits, and potentially waits for the offscreen frame.
13562
13563 Unlike endFrame(), this function will block and wait for completion of the
13564 GPU-side work when there are active buffer or texture readbacks.
13565
13566 \a flags is not currently used.
13567
13568 \sa beginOffscreenFrame()
13569 */
13570QRhi::FrameOpResult QRhi::endOffscreenFrame(EndFrameFlags flags)
13571{
13572 const bool wasInFrame = d->inFrame;
13573 if (!wasInFrame)
13574 qWarning("Attempted to call endOffscreenFrame() without an active frame; ignored");
13575
13576 QRhi::FrameOpResult r = wasInFrame ? d->endOffscreenFrame(flags) : FrameOpSuccess;
13577 d->inFrame = false;
13578 qDeleteAll(d->pendingDeleteResources);
13579 d->pendingDeleteResources.clear();
13580
13581 if (wasInFrame && qrhiDebugHooks.frameEnd) {
13582 QRhiCommandBuffer *cb = r == FrameOpSuccess ? d->currentOffscreenCb : nullptr;
13583 qrhiDebugHooks.frameEnd(d, nullptr, cb);
13584 }
13585 d->currentOffscreenCb = nullptr;
13586
13587 return r;
13588}
13589
13590/*!
13591 Waits for any work on the graphics queue (where applicable) to complete,
13592 then executes all deferred operations, like completing readbacks and
13593 resource releases. Can be called inside and outside of a frame, but not
13594 inside a pass. Inside a frame it implies submitting any work on the
13595 command buffer.
13596
13597 \note Avoid this function. One case where it may be needed is when the
13598 results of an enqueued readback in a swapchain-based frame are needed at a
13599 fixed given point and so waiting for the results is desired.
13600 */
13601QRhi::FrameOpResult QRhi::finish()
13602{
13603 return d->finish();
13604}
13605
13606/*!
13607 \return the list of supported sample counts.
13608
13609 A typical example would be (1, 2, 4, 8).
13610
13611 With some backend this list of supported values is fixed in advance, while
13612 with some others the (physical) device properties indicate what is
13613 supported at run time.
13614
13615 \sa QRhiRenderBuffer::setSampleCount(), QRhiTexture::setSampleCount(),
13616 QRhiGraphicsPipeline::setSampleCount(), QRhiSwapChain::setSampleCount()
13617 */
13618QList<int> QRhi::supportedSampleCounts() const
13619{
13620 return d->supportedSampleCounts();
13621}
13622
13623/*!
13624 \return the minimum uniform buffer offset alignment in bytes. This is
13625 typically 256.
13626
13627 Attempting to bind a uniform buffer region with an offset not aligned to
13628 this value will lead to failures depending on the backend and the
13629 underlying graphics API.
13630
13631 \sa ubufAligned()
13632 */
13633int QRhi::ubufAlignment() const
13634{
13635 return d->ubufAlignment();
13636}
13637
13638/*!
13639 \return The list of supported variable shading rates for the specified \a sampleCount.
13640
13641 1x1 is always supported.
13642
13643 \since 6.9
13644 */
13645QList<QSize> QRhi::supportedShadingRates(int sampleCount) const
13646{
13647 return d->supportedShadingRates(sampleCount);
13648}
13649
13650Q_CONSTINIT static QBasicAtomicInteger<QRhiGlobalObjectIdGenerator::Type> counter = Q_BASIC_ATOMIC_INITIALIZER(0);
13651
13652QRhiGlobalObjectIdGenerator::Type QRhiGlobalObjectIdGenerator::newId()
13653{
13654 return counter.fetchAndAddRelaxed(1) + 1;
13655}
13656
13658{
13659 return m_buffers.isEmpty() && m_textures.isEmpty();
13660}
13661
13663{
13664 m_buffers.clear();
13665 m_textures.clear();
13666}
13667
13673
13674void QRhiPassResourceTracker::registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
13675 const UsageState &state)
13676{
13677 auto it = m_buffers.find(buf);
13678 if (it != m_buffers.end()) {
13679 Buffer &b = it->second;
13680 if (Q_UNLIKELY(b.access != *access)) {
13681 const QByteArray name = buf->name();
13682 qWarning("Buffer %p (%s) used with different accesses within the same pass, this is not allowed.",
13683 buf, name.constData());
13684 return;
13685 }
13686 if (b.stage != *stage) {
13687 b.stage = earlierStage(b.stage, *stage);
13688 *stage = b.stage;
13689 }
13690 return;
13691 }
13692
13693 Buffer b;
13694 b.slot = slot;
13695 b.access = *access;
13696 b.stage = *stage;
13697 b.stateAtPassBegin = state; // first use -> initial state
13698 m_buffers.append(buf, b);
13699}
13700
13706
13713
13715 const UsageState &state)
13716{
13717 auto it = m_textures.find(tex);
13718 if (it != m_textures.end()) {
13719 Texture &t = it->second;
13720 if (t.access != *access) {
13721 // Different subresources of a texture may be used for both load
13722 // and store in the same pass. (think reading from one mip level
13723 // and writing to another one in a compute shader) This we can
13724 // handle by treating the entire resource as read-write.
13725 if (Q_LIKELY(isImageLoadStore(t.access) && isImageLoadStore(*access))) {
13727 *access = t.access;
13728 } else {
13729 const QByteArray name = tex->name();
13730 qWarning("Texture %p (%s) used with different accesses within the same pass, this is not allowed.",
13731 tex, name.constData());
13732 }
13733 }
13734 if (t.stage != *stage) {
13735 t.stage = earlierStage(t.stage, *stage);
13736 *stage = t.stage;
13737 }
13738 return;
13739 }
13740
13741 Texture t;
13742 t.access = *access;
13743 t.stage = *stage;
13744 t.stateAtPassBegin = state; // first use -> initial state
13745 m_textures.append(tex, t);
13746}
13747
13748QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
13749{
13750 // pick the earlier stage (as this is going to be dstAccessMask)
13751 if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
13753 if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
13755 if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
13757 if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
13759 if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
13761 if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
13763
13764 Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::BufVertexStage);
13765}
13766
13767QRhiPassResourceTracker::TextureStage QRhiPassResourceTracker::toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
13768{
13769 // pick the earlier stage (as this is going to be dstAccessMask)
13770 if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
13772 if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
13774 if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
13776 if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
13778 if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
13780 if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
13782
13783 Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::TexVertexStage);
13784}
13785
13786QSize QRhiImplementation::clampedSubResourceUploadSize(QSize size, QPoint dstPos, int level, QSize textureSizeAtLevelZero, bool warn)
13787{
13788 const QSize subResSize = q->sizeForMipLevel(level, textureSizeAtLevelZero);
13789 const bool outOfBoundsHoriz = dstPos.x() + size.width() > subResSize.width();
13790 const bool outOfBoundsVert = dstPos.y() + size.height() > subResSize.height();
13791 if (Q_UNLIKELY(outOfBoundsHoriz || outOfBoundsVert)) {
13792 if (warn) {
13793 qWarning("Invalid texture upload issued; size %dx%d dst.position %d,%d dst.subresource size %dx%d; size will be clamped",
13794 size.width(), size.height(), dstPos.x(), dstPos.y(), subResSize.width(), subResSize.height());
13795 }
13796 if (outOfBoundsHoriz)
13797 size.setWidth(subResSize.width() - dstPos.x());
13798 if (outOfBoundsVert)
13799 size.setHeight(subResSize.height() - dstPos.y());
13800 }
13801 return size;
13802}
13803
13804// Clamps size so that reading the image with a source row stride of bpl does
13805// not go past dataSize bytes. bpl may be 0, meaning the data is tightly packed.
13806// Returns a size with a height of 0 when not even a single row can be
13807// satisfied, in which case the caller is expected to skip the copy.
13808QSize QRhiImplementation::clampedSubResourceUploadSizeForSourceData(QSize size, quint32 bpl,
13809 quint32 bytesPerPixel,
13810 qsizetype dataSize, bool warn)
13811{
13812 if (size.isEmpty() || !bytesPerPixel)
13813 return size;
13814
13815 const quint64 rowBytes = quint64(bytesPerPixel) * quint64(size.width());
13816 if (!bpl)
13817 bpl = quint32(qMin(rowBytes, quint64(std::numeric_limits<quint32>::max())));
13818
13819 if (quint64(bpl) < rowBytes) {
13820 if (warn) {
13821 qWarning("Invalid texture upload issued; source row stride %u is smaller than the %llu "
13822 "bytes a row of %d pixels needs; upload will be skipped",
13823 bpl, rowBytes, size.width());
13824 }
13825 return QSize(size.width(), 0);
13826 }
13827
13828 // Row y is read from y * bpl and needs rowBytes bytes, so the last row ends
13829 // at (height - 1) * bpl + rowBytes.
13830 const quint64 needed = quint64(bpl) * quint64(size.height() - 1) + rowBytes;
13831 if (quint64(dataSize) >= needed)
13832 return size;
13833
13834 int rows = 0;
13835 if (quint64(dataSize) >= rowBytes)
13836 rows = int((quint64(dataSize) - rowBytes) / quint64(bpl)) + 1;
13837
13838 if (warn) {
13839 qWarning("Invalid texture upload issued; %lld bytes of data cannot back a %dx%d upload with "
13840 "source row stride %u (needs %llu bytes); height will be clamped to %d",
13841 qint64(dataSize), size.width(), size.height(), bpl, needed, rows);
13842 }
13843
13844 return QSize(size.width(), rows);
13845}
13846
13847QT_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:842
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:853
void execute(QRhiCommandBuffer *cb, quint32 firstCommand, quint32 commandCount)
Definition qrhi.cpp:9334
QRhiBufferBackedIndirectCommandBuffer(QRhiImplementation *rhi, Type type, quint32 maxCommandCount)
\variable QRhiIndirectCommandBufferBuildInfo::topology
Definition qrhi.cpp:9244
void enqueueUpload(QRhiResourceUpdateBatch *u)
Definition qrhi.cpp:9298
void build(const QRhiIndirectCommandBufferBuildInfo &info)
Definition qrhi.cpp:9321
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
Definition qrhi.cpp:9256
bool create() override
Creates the corresponding native objects.
Definition qrhi.cpp:9279
bool isEmpty() const
Definition qrhi.cpp:13657
void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage, const UsageState &state)
Definition qrhi.cpp:13674
void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage, const UsageState &state)
Definition qrhi.cpp:13714
QRhiImplementation * rhi
Definition qrhi_p.h:746
static const int BUFFER_OPS_STATIC_ALLOC
Definition qrhi_p.h:738
void merge(QRhiResourceUpdateBatchPrivate *other)
Definition qrhi.cpp:11425
QRhiResourceUpdateBatch * q
Definition qrhi_p.h:745
static const int TEXTURE_OPS_STATIC_ALLOC
Definition qrhi_p.h:742
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
static const char * resourceTypeStr(const QRhiResource *res)
Definition qrhi.cpp:9495
static QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a, QRhiPassResourceTracker::BufferStage b)
Definition qrhi.cpp:13668
QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
Definition qrhi.cpp:8547
static bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess access)
Definition qrhi.cpp:13707
static const char * deviceTypeStr(QRhiDriverInfo::DeviceType type)
\variable QRhiDriverInfo::deviceName
Definition qrhi.cpp:10478
static auto & emplaceData(QRhiShaderResourceBinding::Data &d)
Definition qrhi.cpp:6212
static QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a, QRhiPassResourceTracker::TextureStage b)
Definition qrhi.cpp:13701
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:1616
LimitsType limitsType
Definition qrhi.h:1627
LuminanceBehavior luminanceBehavior
Definition qrhi.h:1638