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.
818
819 \value WideLines Indicates that lines with a width other than 1 are
820 supported. When reported as not supported, the line width set on the
821 graphics pipeline state is ignored. This can always be false with some
822 backends (D3D11, D3D12, Metal). With Vulkan, the value depends on the
823 implementation. With OpenGL, wide lines are not supported in core profile
824 contexts.
825
826 \value VertexShaderPointSize Indicates that the size of rasterized points
827 set via \c{gl_PointSize} in the vertex shader is taken into account. When
828 reported as not supported, drawing points with a size other than 1 is not
829 supported. Setting \c{gl_PointSize} in the shader is still valid then, but
830 is ignored. (for example, when generating HLSL, the assignment is silently
831 dropped from the generated code) Note that some APIs (Metal, Vulkan)
832 require the point size to be set in the shader explicitly whenever drawing
833 points, even when the size is 1, as they do not automatically default to 1.
834
835 \value BaseVertex Indicates that
836 \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} supports the \c
837 vertexOffset argument. When reported as not supported, the vertexOffset
838 value in an indexed draw is ignored. In practice this feature will be
839 unsupported with OpenGL and OpenGL ES versions lower than 3.2, and with
840 Metal on older iOS devices, including the iOS Simulator.
841
842 \value BaseInstance Indicates that instanced draw commands support the \c
843 firstInstance argument. When reported as not supported, the firstInstance
844 value is ignored and the instance ID starts from 0. In practice this feature
845 will be unsupported with Metal on older iOS devices, including the iOS
846 Simulator, and with OpenGL ES, which has no support for draw calls with a
847 base instance at all. With OpenGL it needs version 4.2 or newer, or
848 \c GL_ARB_base_instance. Applications relying on a non-zero base instance
849 should be aware of the InstanceIndexIncludesBaseInstance feature as well.
850
851 \value TriangleFanTopology Indicates that QRhiGraphicsPipeline::setTopology()
852 supports QRhiGraphicsPipeline::TriangleFan. In practice this feature will be
853 unsupported with Metal and Direct 3D 11/12.
854
855 \value ReadBackNonUniformBuffer Indicates that
856 \l{QRhiResourceUpdateBatch::readBackBuffer()}{reading buffer contents} is
857 supported for QRhiBuffer instances with a usage different than
858 UniformBuffer. In practice this feature will be unsupported with OpenGL ES
859 2.0.
860
861 \value ReadBackNonBaseMipLevel Indicates that specifying a mip level other
862 than 0 is supported when reading back texture contents. When not supported,
863 specifying a non-zero level in QRhiReadbackDescription leads to returning
864 an all-zero image. In practice this feature will be unsupported with OpenGL
865 ES 2.0.
866
867 \value TexelFetch Indicates that texelFetch() and textureLod() are available
868 in shaders. In practice this will be reported as unsupported with OpenGL ES
869 2.0 and OpenGL 2.x contexts, because GLSL 100 es and versions before 130 do
870 not support these functions.
871
872 \value RenderToNonBaseMipLevel Indicates that specifying a mip level other
873 than 0 is supported when creating a QRhiTextureRenderTarget with a
874 QRhiTexture as its color attachment. When not supported, create() will fail
875 whenever the target mip level is not zero. In practice this feature will be
876 unsupported with OpenGL ES 2.0.
877
878 \value IntAttributes Indicates that specifying input attributes with
879 signed and unsigned integer types for a shader pipeline is supported. When
880 not supported,
881 \l{QRhiGraphicsPipeline::create()}{QRhiGraphicsPipeline::create()} will
882 succeed but show a warning message and the values of the target attributes
883 will be broken. In practice this feature will be unsupported with OpenGL ES
884 2.0 and OpenGL 2.x.
885
886 \value ScreenSpaceDerivatives Indicates that functions such as dFdx(),
887 dFdy(), and fwidth() are supported in shaders. In practice this feature will
888 be unsupported with OpenGL ES 2.0 without the GL_OES_standard_derivatives
889 extension.
890
891 \value ReadBackAnyTextureFormat Indicates that reading back texture
892 contents can be expected to work for any QRhiTexture::Format. Backends
893 other than OpenGL can be expected to return true for this feature. When
894 reported as false, which will typically happen with OpenGL, only the
895 formats QRhiTexture::RGBA8 and QRhiTexture::BGRA8 are guaranteed to be
896 supported for readbacks. In addition, with OpenGL, but not OpenGL ES,
897 reading back the 1 byte per component formats QRhiTexture::R8 and
898 QRhiTexture::RED_OR_ALPHA8 are supported as well. Reading back floating
899 point formats QRhiTexture::RGBA16F and RGBA32F may work too with OpenGL, as
900 long as the implementation provides support for these, but QRhi can give no
901 guarantees, as indicated by this flag.
902
903 \value PipelineCacheDataLoadSave Indicates that the pipelineCacheData() and
904 setPipelineCacheData() functions are functional. When not supported, the
905 functions will not perform any action, the retrieved blob is always empty,
906 and thus no benefits can be expected from retrieving and, during a
907 subsequent run of the application, reloading the pipeline cache content.
908
909 \value ImageDataStride Indicates that specifying a custom stride (row
910 length) for raw image data in texture uploads is supported. When not
911 supported (which can happen when the underlying API is OpenGL ES 2.0 without
912 support for GL_UNPACK_ROW_LENGTH),
913 QRhiTextureSubresourceUploadDescription::setDataStride() must not be used.
914
915 \value RenderBufferImport Indicates that QRhiRenderBuffer::createFrom() is
916 supported. For most graphics APIs this is not sensible because
917 QRhiRenderBuffer encapsulates texture objects internally, just like
918 QRhiTexture. With OpenGL however, renderbuffer object exist as a separate
919 object type in the API, and in certain environments (for example, where one
920 may want to associated a renderbuffer object with an EGLImage object) it is
921 important to allow wrapping an existing OpenGL renderbuffer object with a
922 QRhiRenderBuffer.
923
924 \value ThreeDimensionalTextures Indicates that 3D textures are supported.
925 In practice this feature will be unsupported with OpenGL and OpenGL ES
926 versions lower than 3.0.
927
928 \value RenderTo3DTextureSlice Indicates that rendering to a slice in a 3D
929 texture is supported. This can be unsupported with Vulkan 1.0 due to
930 relying on VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT which is a Vulkan 1.1
931 feature.
932
933 \value TextureArrays Indicates that texture arrays are supported and
934 QRhi::newTextureArray() is functional. Note that even when texture arrays
935 are not supported, arrays of textures are still available as those are two
936 independent features.
937
938 \value Tessellation Indicates that the tessellation control and evaluation
939 stages are supported. When reported as supported, the topology of a
940 QRhiGraphicsPipeline can be set to
941 \l{QRhiGraphicsPipeline::Patches}{Patches}, the number of control points
942 can be set via
943 \l{QRhiGraphicsPipeline::setPatchControlPointCount()}{setPatchControlPointCount()},
944 and shaders for tessellation control and evaluation can be specified in the
945 QRhiShaderStage list. Tessellation shaders have portability issues between
946 APIs (for example, translating GLSL/SPIR-V to HLSL is problematic due to
947 the way hull shaders are structured, whereas Metal uses a somewhat
948 different tessellation pipeline than others), and therefore unexpected
949 issues may still arise, even though basic functionality is implemented
950 across all the underlying APIs. For Direct 3D in particular, handwritten
951 HLSL hull and domain shaders must be injected into each QShader for the
952 tessellation control and evaluation stages, respectively, since qsb cannot
953 generate these from SPIR-V. Note that isoline tessellation should be
954 avoided as it will not be supported by all backends. The maximum patch
955 control point count portable between backends is 32.
956
957 \value GeometryShader Indicates that the geometry shader stage is supported.
958 When supported, a geometry shader can be specified in the QRhiShaderStage
959 list. Geometry Shaders are considered an experimental feature in QRhi and
960 can only be expected to be supported with Vulkan, Direct 3D 11 and 12,
961 OpenGL (3.2+) and OpenGL ES (3.2+), assuming the implementation reports it
962 as supported at run time. Starting with Qt 6.11 geometry shaders are
963 automatically translated to HLSL, and therefore no injection of handwritten
964 HLSL geometry shaders is necessary anymore (but note that gl_in and
965 expressions such as gl_in[0].gl_Position are not supported; rather, pass the
966 position as an output variable from the vertex shader). Geometry shaders are
967 not supported with Metal.
968
969 \value TextureArrayRange Indicates that for
970 \l{QRhi::newTextureArray()}{texture arrays} it is possible to specify a
971 range that is exposed to the shaders. Normally all array layers are exposed
972 and it is up to the shader to select the layer (via the third coordinate
973 passed to texture() when sampling the \c sampler2DArray). When supported,
974 calling QRhiTexture::setArrayRangeStart() and
975 QRhiTexture::setArrayRangeLength() before
976 \l{QRhiTexture::create()}{building} or
977 \l{QRhiTexture::createFrom()}{importing} the native texture has an effect,
978 and leads to selecting only the specified range from the array. This will
979 be necessary in special cases, such as when working with accelerated video
980 decoding and Direct 3D 11, because a texture array with both
981 \c{D3D11_BIND_DECODER} and \c{D3D11_BIND_SHADER_RESOURCE} on it is only
982 usable as a shader resource if a single array layer is selected. Note that
983 all this is applicable only when the texture is used as a
984 QRhiShaderResourceBinding::SampledTexture or
985 QRhiShaderResourceBinding::Texture shader resource, and is not compatible
986 with image load/store. This feature is only available with some backends as
987 it does not map well to all graphics APIs, and it is only meant to provide
988 support for special cases anyhow. In practice the feature can be expected to
989 be supported with Direct3D 11/12, Vulkan and Metal.
990
991 \value NonFillPolygonMode Indicates that setting a PolygonMode other than
992 the default Fill is supported for QRhiGraphicsPipeline. A common use case
993 for changing the mode to Line is to get wireframe rendering. This however
994 is not available as a core OpenGL ES feature, and is optional with Vulkan
995 as well as some mobile GPUs may not offer the feature.
996
997 \value OneDimensionalTextures Indicates that 1D textures are supported.
998 In practice this feature will be unsupported on OpenGL ES.
999
1000 \value OneDimensionalTextureMipmaps Indicates that generating 1D texture
1001 mipmaps is supported. In practice this feature will be unsupported on
1002 backends that do not report support for
1003 \l{OneDimensionalTextures}, Metal, and Direct 3D 12.
1004
1005 \value HalfAttributes Indicates that specifying input attributes with half
1006 precision (16bit) floating point types for a shader pipeline is supported.
1007 When not supported,
1008 \l{QRhiGraphicsPipeline::create()}{QRhiGraphicsPipeline::create()} will
1009 succeed but show a warning message and the values of the target attributes
1010 will be broken. In practice this feature will be unsupported in some OpenGL
1011 ES 2.0 and OpenGL 2.x
1012 implementations. Note that while Direct3D 11/12 does support half precision
1013 input attributes, it does not support the half3 type. The D3D backends pass
1014 half3 attributes as half4. To ensure cross platform compatibility, half3
1015 inputs should be padded to 8 bytes.
1016
1017 \value RenderToOneDimensionalTexture Indicates that 1D texture render
1018 targets are supported. In practice this feature will be unsupported on
1019 backends that do not report support for
1020 \l{OneDimensionalTextures}, and Metal.
1021
1022 \value ThreeDimensionalTextureMipmaps Indicates that generating 3D texture
1023 mipmaps is supported. This is typically supported with all backends starting
1024 with Qt 6.10.
1025
1026 \value MultiView Indicates that multiview, see e.g.
1027 \l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_multiview.html}{VK_KHR_multiview}
1028 is supported. With OpenGL ES 2.0, Direct 3D 11, and OpenGL (ES)
1029 implementations without \c{GL_OVR_multiview2} this feature will not be
1030 supported. With Vulkan 1.1 and newer, and Direct 3D 12 multiview is
1031 typically supported. When reported as supported, creating a
1032 QRhiTextureRenderTarget with a QRhiColorAttachment that references a texture
1033 array and has \l{QRhiColorAttachment::setMultiViewCount()}{multiViewCount}
1034 set enables recording a render pass that uses multiview rendering. In addition,
1035 any QRhiGraphicsPipeline used in that render pass must have
1036 \l{QRhiGraphicsPipeline::setMultiViewCount()}{the same view count set}. Note that
1037 multiview is only available in combination with 2D texture arrays. It cannot
1038 be used to optimize the rendering into individual textures (e.g. two, for
1039 the left and right eyes). Rather, the target of a multiview render pass is
1040 always a texture array, automatically rendering to the layer (array element)
1041 corresponding to each view. Therefore this feature implies \l TextureArrays
1042 as well. Multiview rendering is not supported in combination with
1043 tessellation or geometry shaders. See QRhiColorAttachment::setMultiViewCount()
1044 for further details on multiview rendering. This enum value has been introduced in Qt 6.7.
1045
1046 \value TextureViewFormat Indicates that setting a
1047 \l{QRhiTexture::setWriteViewFormat()}{view format} on a QRhiTexture is
1048 effective. When reported as supported, setting the read (sampling) or write
1049 (render target / image load-store) view mode changes the texture's viewing
1050 format. When unsupported, setting a view format has no effect. Note that Qt
1051 has no knowledge or control over format compatibility or resource view rules
1052 in the underlying 3D API and its implementation. Passing in unsuitable,
1053 incompatible formats may lead to errors and unspecified behavior. This is
1054 provided mainly to allow "casting" rendering into a texture created with an
1055 sRGB format to non-sRGB to avoid the unwanted linear->sRGB conversion on
1056 shader writes. Other types of casting may or may not be functional,
1057 depending on the underlying API. Currently implemented for Vulkan and Direct
1058 3D 12 and Metal. With D3D12 the feature is available only if
1059 \c CastingFullyTypedFormatSupported is supported, see
1060 \l{https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html} (and
1061 note that QRhi always uses fully typed formats for textures.) This enum
1062 value has been introduced in Qt 6.8.
1063
1064 \value ResolveDepthStencil Indicates that resolving a multisample depth or
1065 depth-stencil texture is supported. Otherwise,
1066 \l{QRhiTextureRenderTargetDescription::setDepthResolveTexture()}{setting a
1067 depth resolve texture} is not functional and must be avoided. Direct 3D 11
1068 and 12 have no support for resolving depth/depth-stencil formats, and
1069 therefore this feature will never be supported with those. Vulkan 1.0 has no
1070 API to request resolving a depth-stencil attachment. Therefore, with Vulkan
1071 this feature will only be supported with Vulkan 1.2 and up, and on 1.1
1072 implementations with the appropriate extensions present. This feature is
1073 provided for the rare case when resolving into a non-multisample depth
1074 texture becomes necessary, for example when rendering into an
1075 OpenXR-provided depth texture (XR_KHR_composition_layer_depth). This enum
1076 value has been introduced in Qt 6.8.
1077
1078 \value VariableRateShading Indicates that per-draw (per-pipeline) variable
1079 rate shading is supported. When reported as supported, \l
1080 QRhiCommandBuffer::setShadingRate() is functional and has an effect for
1081 QRhiGraphicsPipeline objects that declared \l
1082 QRhiGraphicsPipeline::UsesShadingRate in their flags. Call \l
1083 QRhi::supportedShadingRates() to check which rates are supported. (1x1 is
1084 always supported, other typical values are 2x2, 1x2, 2x1, 2x4, 4x2, 4x4).
1085 This feature can be expected to be supported with Direct 3D 12 and Vulkan,
1086 assuming the implementation and GPU used at run time supports VRS. This enum
1087 value has been introduced in Qt 6.9.
1088
1089 \value VariableRateShadingMap Indicates that image-based specification of
1090 the shading rate is possible. The "image" is not necessarily a texture, it
1091 may be a native 3D API object, depending on the underlying backend and
1092 graphics API at run time. In practice this feature can be expected to be
1093 supported with Direct 3D 12, Vulkan, and Metal, assuming the GPU is modern
1094 enough to support VRS. To check if D3D12/Vulkan-style image-based VRS is
1095 supported, use VariableRateShadingMapWithTexture instead. When this feature
1096 is reported as supported, there are two possibilities: when
1097 VariableRateShadingMapWithTexture is also true, then QRhiShadingRateMap
1098 consumes QRhiTexture objects via the createFrom() overload taking a
1099 QRhiTexture argument. When VariableRateShadingMapWithTexture is false, then
1100 QRhiShadingRateMap consumes some other type of native objects, for example
1101 an MTLRasterizationRateMap in case of Metal. Use the createFrom() overload
1102 taking a NativeShadingRateMap in this case. This enum value has been
1103 introduced in Qt 6.9.
1104
1105 \value VariableRateShadingMapWithTexture Indicates that image-based
1106 specification of the shading rate is supported via regular textures. In
1107 practice this may be supported with Direct 3D 12 and Vulkan. This enum value
1108 has been introduced in Qt 6.9.
1109
1110 \value PerRenderTargetBlending Indicates that per rendertarget blending is
1111 supported i.e. different render targets in MRT framebuffer can have different
1112 blending modes. In practice this can be expected to be supported everywhere
1113 except OpenGL ES, where it is only available with GLES 3.2 implementations.
1114 This enum value has been introduced in Qt 6.9.
1115
1116 \value SampleVariables Indicates that gl_SampleID, gl_SamplePosition,
1117 gl_SampleMaskIn and gl_SampleMask variables are available in fragment shaders.
1118 In practice this can be expected to be supported everywhere except OpenGL ES,
1119 where it is only available with GLES 3.2 implementations.
1120 This enum value has been introduced in Qt 6.9.
1121
1122 \value InstanceIndexIncludesBaseInstance Indicates that \c gl_InstanceIndex
1123 includes the base instance (the \c firstInstance argument in draw calls) in
1124 its value. When this feature is unsupported, but BaseInstance is, it
1125 indicates that \c gl_InstanceIndex always starts at 0, not the base value.
1126 In practice this will be the case for Direct 3D 11 and 12 at the moment.
1127 With Vulkan and Metal this feature is expected to be reported as supported
1128 always. This enum value has been introduced in Qt 6.11.
1129
1130 \value [since 6.11] DepthClamp Indicates that enabling depth clamping is
1131 supported. When reported as unsupported, which will be the case with OpenGL
1132 ES, OpenGL versions before 3.2 without the relevant extension present, and
1133 Metal on the iOS Simulator, calling \l{QRhiGraphicsPipeline::setDepthClamp()}
1134 with an argument of \c true has no effect.
1135
1136 \value [since 6.12] DrawIndirect Indicates that the
1137 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
1138 and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}
1139 functions are available.
1140 In practice this can be expected to be supported everywhere except on
1141 OpenGL ES < 3.1.
1142
1143 \value [since 6.12] DrawIndirectMulti Indicates that a drawCount > 1 is natively
1144 supported by the backend in \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
1145 and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}.
1146 Otherwise, multiple draw calls are issued on the CPU by the RHI.
1147 In practice this can be expected to be supported on Vulkan 1.1+, OpenGL
1148 4.3+, D3D12, and Metal.
1149
1150 \value [since 6.12] ShaderDrawParameters Indicates that the \c{gl_BaseInstance},
1151 \c{gl_BaseVertex} and \c{gl_DrawID} built-in variables are available in shaders.
1152 In practice this can be expected to be supported on Vulkan 1.1+ and with desktop OpenGL
1153 4.6 or \c{GL_ARB_shader_draw_parameters}.
1154
1155 \value [since 6.13] DispatchIndirect Indicates that the
1156 \l{QRhiCommandBuffer::dispatchIndirect()}{dispatchIndirect()} function is
1157 available, allowing compute work group counts to be sourced from a
1158 \l QRhiBuffer at execution time. In practice this can be expected to be
1159 supported wherever the \l Compute feature is reported as supported, that is,
1160 on Vulkan, OpenGL 4.3+ / OpenGL ES 3.1+, Direct3D 11/12, and Metal.
1161
1162 \value [since 6.13] DrawIndirectCount Indicates that the
1163 \l{QRhiCommandBuffer::drawIndirectCount()}{drawIndirectCount()} and
1164 \l{QRhiCommandBuffer::drawIndexedIndirectCount()}{drawIndexedIndirectCount()}
1165 functions are available. These are GPU-driven multi-draw variants where the
1166 actual draw count is read from a buffer at execution time, capped to a
1167 CPU-supplied \c maxDrawCount. In practice this can be expected to be
1168 supported with Vulkan 1.2 and newer, when both the \c drawIndirectCount and
1169 \c multiDrawIndirect device features are present, with OpenGL 4.6 or when
1170 \c GL_ARB_indirect_parameters is available, with Direct3D 12, and with Metal
1171 on devices supporting Metal 3 and indirect command buffers. Direct3D 11 does
1172 not expose an equivalent entry point. Note that with Vulkan the two device
1173 features are queried from the physical device. When importing an existing
1174 VkDevice, the application must make sure the features were enabled when that
1175 device was created, because this cannot be queried afterwards. With Metal
1176 there is a further requirement that this feature flag cannot reflect: the
1177 graphics pipeline must have
1178 \l{QRhiGraphicsPipeline::UsesIndirectDraws}{UsesIndirectDraws} set, without
1179 which the draw is skipped with a warning.
1180
1181 \value [since 6.13] BufferToBufferCopy Indicates that the
1182 \l{QRhiResourceUpdateBatch::copyBuffer()}{copyBuffer()} function is
1183 available, allowing the contents of a QRhiBuffer to be copied into another
1184 QRhiBuffer on the GPU, without a readback to the CPU. In practice this can
1185 be expected to be supported everywhere except with OpenGL ES 2.0 and
1186 desktop OpenGL versions before 3.1 without \c GL_ARB_copy_buffer, which
1187 have no \c glCopyBufferSubData. There is no fallback on such systems
1188 because OpenGL ES 2.0 provides no way of reading back the contents of a
1189 buffer either.
1190
1191 \value [since 6.13] PushConstants Indicates that
1192 \l{QRhiCommandBuffer::setPushConstants()}{setPushConstants()} is
1193 functional, meaning shaders can declare a \c{layout(push_constant)} block
1194 and the data for it can be updated between draw calls without involving a
1195 QRhiShaderResourceBindings. The maximum size of the block is reported by
1196 the \l{QRhi::MaxPushConstantsSize}{MaxPushConstantsSize} resource limit.
1197 Vulkan, Metal and Direct3D 12 have a native equivalent. OpenGL and
1198 Direct3D 11 emulate it, with plain uniforms and with a small dynamic
1199 constant buffer, respectively, so there an update costs about as much as
1200 updating a small uniform buffer; what is gained is not having to have a
1201 QRhiShaderResourceBindings per draw call. There is one case where the
1202 feature is reported as supported but does not apply: with Metal, push
1203 constants are not supported with a graphics pipeline that uses
1204 tessellation.
1205
1206 \value [since 6.13] StaticBuffersOnGpuTimeline Indicates that updates of
1207 QRhiBuffer objects with a type of QRhiBuffer::Immutable or
1208 QRhiBuffer::Static are recorded into the command stream, and so are
1209 executed on the GPU timeline, in the order they were recorded in. In
1210 particular this means that
1211 \l{QRhiResourceUpdateBatch::uploadStaticBuffer()}{uploadStaticBuffer()} and
1212 \l{QRhiResourceUpdateBatch::copyBuffer()}{copyBuffer()} targeting the same
1213 buffer within one \l QRhiResourceUpdateBatch take effect in the recorded
1214 order. When this is reported as not supported, uploads are implemented by
1215 writing to host visible memory on an unrelated timeline, and the ordering
1216 between the two kinds of updates is undefined. In practice this is only
1217 relevant with Metal: the feature is not supported there when the Metal
1218 device does not report an Apple GPU, which is the case on Intel-based Macs,
1219 and also in virtual machines where the paravirtualized device does not
1220 advertise an Apple GPU family. Note that this says nothing about when the
1221 contents become visible to the CPU or to subsequent draw calls, which is
1222 always taken care of by QRhi.
1223 */
1224
1225/*!
1226 \enum QRhi::BeginFrameFlag
1227 Flag values for QRhi::beginFrame()
1228 */
1229
1230/*!
1231 \enum QRhi::EndFrameFlag
1232 Flag values for QRhi::endFrame()
1233
1234 \value SkipPresent Specifies that no present command is to be queued or no
1235 swapBuffers call is to be made. This way no image is presented. Generating
1236 multiple frames with all having this flag set is not recommended (except,
1237 for example, for benchmarking purposes - but keep in mind that backends may
1238 behave differently when it comes to waiting for command completion without
1239 presenting so the results are not comparable between them)
1240 */
1241
1242/*!
1243 \enum QRhi::ResourceLimit
1244 Describes the resource limit to query.
1245
1246 \value TextureSizeMin Minimum texture width and height. This is typically
1247 1. The minimum texture size is handled gracefully, meaning attempting to
1248 create a texture with an empty size will instead create a texture with the
1249 minimum size.
1250
1251 \value TextureSizeMax Maximum texture width and height. This depends on the
1252 graphics API and sometimes the platform or implementation as well.
1253 Typically the value is in the range 4096 - 16384. Attempting to create
1254 textures larger than this is expected to fail.
1255
1256 \value MaxColorAttachments The maximum number of color attachments for a
1257 QRhiTextureRenderTarget, in case multiple render targets are supported. When
1258 MRT is not supported, the value is 1. Otherwise this is typically 8, but
1259 watch out for the fact that OpenGL only mandates 4 as the minimum, and that
1260 is what some OpenGL ES implementations provide.
1261
1262 \value FramesInFlight The number of frames the backend may keep "in
1263 flight": with backends like Vulkan or Metal, it is the responsibility of
1264 QRhi to block whenever starting a new frame and finding the CPU is already
1265 \c{N - 1} frames ahead of the GPU (because the command buffer submitted in
1266 frame no. \c{current} - \c{N} has not yet completed). The value N is what
1267 is returned from here, and is typically 2. This can be relevant to
1268 applications that integrate rendering done directly with the graphics API,
1269 as such rendering code may want to perform double (if the value is 2)
1270 buffering for resources, such as, buffers, similarly to the QRhi backends
1271 themselves. The current frame slot index (a value running 0, 1, .., N-1,
1272 then wrapping around) is retrievable from QRhi::currentFrameSlot(). The
1273 value is 1 for backends where the graphics API offers no such low level
1274 control over the command submission process. Note that pipelining may still
1275 happen even when this value is 1 (some backends, such as D3D11, are
1276 designed to attempt to enable this, for instance, by using an update
1277 strategy for uniform buffers that does not stall the pipeline), but that is
1278 then not controlled by QRhi and so not reflected here in the API.
1279
1280 \value MaxAsyncReadbackFrames The number of \l{QRhi::endFrame()}{submitted}
1281 frames (including the one that contains the readback) after which an
1282 asynchronous texture or buffer readback is guaranteed to complete upon
1283 \l{QRhi::beginFrame()}{starting a new frame}.
1284
1285 \value MaxThreadGroupsPerDimension The maximum number of compute
1286 work/thread groups that can be dispatched. Effectively the maximum value
1287 for the arguments of QRhiCommandBuffer::dispatch(). Typically 65535.
1288
1289 \value MaxThreadsPerThreadGroup The maximum number of invocations in a
1290 single local work group, or in other terminology, the maximum number of
1291 threads in a thread group. Effectively the maximum value for the product of
1292 \c local_size_x, \c local_size_y, and \c local_size_z in the compute
1293 shader. Typical values are 128, 256, 512, 1024, or 1536. Watch out that
1294 both OpenGL ES and Vulkan specify only 128 as the minimum required limit
1295 for implementations. While uncommon for Vulkan, some OpenGL ES 3.1
1296 implementations for mobile/embedded devices only support the spec-mandated
1297 minimum value.
1298
1299 \value MaxThreadGroupX The maximum size of a work/thread group in the X
1300 dimension. Effectively the maximum value of \c local_size_x in the compute
1301 shader. Typically 256 or 1024.
1302
1303 \value MaxThreadGroupY The maximum size of a work/thread group in the Y
1304 dimension. Effectively the maximum value of \c local_size_y in the compute
1305 shader. Typically 256 or 1024.
1306
1307 \value MaxThreadGroupZ The maximum size of a work/thread group in the Z
1308 dimension. Effectively the maximum value of \c local_size_z in the compute
1309 shader. Typically 64 or 256.
1310
1311 \value TextureArraySizeMax Maximum texture array size. Typically in range
1312 256 - 2048. Attempting to \l{QRhi::newTextureArray()}{create a texture
1313 array} with more elements will likely fail.
1314
1315 \value MaxUniformBufferRange The number of bytes that can be exposed from a
1316 uniform buffer to the shaders at once. On OpenGL ES 2.0 and 3.0
1317 implementations this may be as low as 3584 bytes (224 four component, 32
1318 bits per component vectors). Elsewhere the value is typically 16384 (1024
1319 vec4s) or 65536 (4096 vec4s).
1320
1321 \value MaxVertexInputs The number of input attributes to the vertex shader.
1322 The location in a QRhiVertexInputAttribute must be in range \c{[0,
1323 MaxVertexInputs-1]}. The value may be as low as 8 with OpenGL ES 2.0.
1324 Elsewhere, typical values are 16, 31, or 32.
1325
1326 \value MaxVertexOutputs The maximum number of outputs (4 component vector
1327 \c out variables) from the vertex shader. The value may be as low as 8 with
1328 OpenGL ES 2.0, and 15 with OpenGL ES 3.0 and some Metal devices. Elsewhere,
1329 a typical value is 32.
1330
1331 \value ShadingRateImageTileSize The tile size for shading rate textures. 0
1332 if the QRhi::VariableRateShadingMapWithTexture feature is not supported.
1333 Otherwise a value such as 16, indicating, for example, a tile size of 16x16.
1334 Each byte in the (R8UI) shading rate texture defines then the shading rate
1335 for a tile of 16x16 pixels. See \l QRhiShadingRateMap for details.
1336
1337 \value [since 6.13] MaxVertexStorageBuffers The maximum number of
1338 storage buffers that can be bound for reading (bufferLoad) in the
1339 vertex stage. Can legitimately be 0: OpenGL ES makes vertex-stage
1340 storage blocks optional even on 3.1 and newer, and many mobile
1341 drivers report 0 while supporting them via Vulkan on the same GPU;
1342 Direct 3D 11 has no vertex-stage storage buffer support at all.
1343 Clients reading storage buffers in the vertex shader must therefore
1344 check this even when QRhi::Compute is supported. Write access can be
1345 more restricted than this value suggests: with Vulkan it additionally
1346 requires the vertexPipelineStoresAndAtomics device feature, and with
1347 Direct 3D 12 unordered access has lower, resource-binding-tier
1348 dependent limits. With Metal the value is the size of the buffer
1349 argument table, which is shared with vertex inputs and uniform
1350 buffers, so the full count is not available in combination with them.
1351
1352 \value [since 6.13] MaxFragmentStorageBuffers The maximum number of
1353 storage buffers that can be bound for reading (bufferLoad) in the
1354 fragment stage. Like the vertex stage, this is optional in OpenGL ES
1355 (only compute-stage storage blocks are mandatory), so 0 is a
1356 legitimate value. The write access and Metal argument table notes
1357 from MaxVertexStorageBuffers apply here as well; with Direct 3D 11
1358 the value reflects the unordered access view slots, which are shared
1359 with render target outputs.
1360
1361 \value [since 6.13] MaxPushConstantsSize The maximum size in bytes of the
1362 push constant block a shader can declare. 0 when the
1363 \l{QRhi::PushConstants}{PushConstants} feature is not supported.
1364 Portable code should stay within 128 bytes: that is what Direct3D 11 and
1365 12 and OpenGL report and what Vulkan guarantees, whereas Metal reports
1366 4096. Note that with Direct3D 12 even 128 is optimistic, because a block
1367 that size takes 32 of the 64 root signature DWORDs, so with a
1368 sufficiently large QRhiShaderResourceBindings the root signature can
1369 still fail to build. With OpenGL the block competes for the uniform
1370 budget with everything else in the shader.
1371 */
1372
1373/*!
1374 \class QRhiInitParams
1375 \inmodule QtGuiPrivate
1376 \inheaderfile rhi/qrhi.h
1377 \since 6.6
1378 \brief Base class for backend-specific initialization parameters.
1379
1380 Contains fields that are relevant to all backends.
1381
1382 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1383 for details.
1384 */
1385
1386/*!
1387 \class QRhiDepthStencilClearValue
1388 \inmodule QtGuiPrivate
1389 \inheaderfile rhi/qrhi.h
1390 \since 6.6
1391 \brief Specifies clear values for a depth or stencil buffer.
1392
1393 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1394 for details.
1395 */
1396
1397/*!
1398 \fn QRhiDepthStencilClearValue::QRhiDepthStencilClearValue() = default
1399
1400 Constructs a depth/stencil clear value with depth clear value 1.0f and
1401 stencil clear value 0.
1402 */
1403
1404/*!
1405 Constructs a depth/stencil clear value with depth clear value \a d and
1406 stencil clear value \a s.
1407 */
1408QRhiDepthStencilClearValue::QRhiDepthStencilClearValue(float d, quint32 s)
1409 : m_d(d),
1410 m_s(s)
1411{
1412}
1413
1414/*!
1415 \fn float QRhiDepthStencilClearValue::depthClearValue() const
1416 \return the depth clear value. In most cases this is 1.0f.
1417 */
1418
1419/*!
1420 \fn void QRhiDepthStencilClearValue::setDepthClearValue(float d)
1421 Sets the depth clear value to \a d.
1422 */
1423
1424/*!
1425 \fn quint32 QRhiDepthStencilClearValue::stencilClearValue() const
1426 \return the stencil clear value. In most cases this is 0.
1427 */
1428
1429/*!
1430 \fn void QRhiDepthStencilClearValue::setStencilClearValue(quint32 s)
1431 Sets the stencil clear value to \a s.
1432 */
1433
1434/*!
1435 \fn bool QRhiDepthStencilClearValue::operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1436
1437 \return \c true if the values in the two QRhiDepthStencilClearValue objects
1438 \a a and \a b are equal.
1439 */
1440
1441/*!
1442 \fn bool QRhiDepthStencilClearValue::operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1443
1444 \return \c false if the values in the two QRhiDepthStencilClearValue
1445 objects \a a and \a b are equal; otherwise returns \c true.
1446
1447*/
1448
1449/*!
1450 \fn size_t QRhiDepthStencilClearValue::qHash(const QRhiDepthStencilClearValue &key, size_t seed)
1451 \qhash{QRhiDepthStencilClearValue}
1452 */
1453
1454#ifndef QT_NO_DEBUG_STREAM
1455QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
1456{
1457 QDebugStateSaver saver(dbg);
1458 dbg.nospace() << "QRhiDepthStencilClearValue(depth-clear=" << v.depthClearValue()
1459 << " stencil-clear=" << v.stencilClearValue()
1460 << ')';
1461 return dbg;
1462}
1463#endif
1464
1465/*!
1466 \class QRhiViewport
1467 \inmodule QtGuiPrivate
1468 \inheaderfile rhi/qrhi.h
1469 \since 6.6
1470 \brief Specifies a viewport rectangle.
1471
1472 Used with QRhiCommandBuffer::setViewport().
1473
1474 QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
1475 bottom-left. Negative width or height are not allowed.
1476
1477 Typical usage is like the following:
1478
1479 \code
1480 const QSize outputSizeInPixels = swapchain->currentPixelSize();
1481 const QRhiViewport viewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height());
1482 cb->beginPass(swapchain->currentFrameRenderTarget(), Qt::black, { 1.0f, 0 });
1483 cb->setGraphicsPipeline(ps);
1484 cb->setViewport(viewport);
1485 // ...
1486 \endcode
1487
1488 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1489 for details.
1490
1491 \sa QRhiCommandBuffer::setViewport(), QRhi::clipSpaceCorrMatrix(), QRhiScissor
1492 */
1493
1494/*!
1495 \fn QRhiViewport::QRhiViewport() = default
1496
1497 Constructs a viewport description with an empty rectangle and a depth range
1498 of 0.0f - 1.0f.
1499
1500 \sa QRhi::clipSpaceCorrMatrix()
1501 */
1502
1503/*!
1504 Constructs a viewport description with the rectangle specified by \a x, \a
1505 y, \a w, \a h and the depth range \a minDepth and \a maxDepth.
1506
1507 \note \a x and \a y are assumed to be the bottom-left position. \a w and \a
1508 h should not be negative, the viewport will be ignored by
1509 QRhiCommandBuffer::setViewport() otherwise.
1510
1511 \sa QRhi::clipSpaceCorrMatrix()
1512 */
1513QRhiViewport::QRhiViewport(float x, float y, float w, float h, float minDepth, float maxDepth)
1514 : m_rect { { x, y, w, h } },
1515 m_minDepth(minDepth),
1516 m_maxDepth(maxDepth)
1517{
1518}
1519
1520/*!
1521 \fn std::array<float, 4> QRhiViewport::viewport() const
1522 \return the viewport x, y, width, and height.
1523 */
1524
1525/*!
1526 \fn void QRhiViewport::setViewport(float x, float y, float w, float h)
1527 Sets the viewport's position and size to \a x, \a y, \a w, and \a h.
1528
1529 \note Viewports are specified in a coordinate system that has its origin in
1530 the bottom-left.
1531 */
1532
1533/*!
1534 \fn float QRhiViewport::minDepth() const
1535 \return the minDepth value of the depth range of the viewport.
1536 */
1537
1538/*!
1539 \fn void QRhiViewport::setMinDepth(float minDepth)
1540 Sets the \a minDepth of the depth range of the viewport.
1541 By default this is set to 0.0f.
1542 */
1543
1544/*!
1545 \fn float QRhiViewport::maxDepth() const
1546 \return the maxDepth value of the depth range of the viewport.
1547 */
1548
1549/*!
1550 \fn void QRhiViewport::setMaxDepth(float maxDepth)
1551 Sets the \a maxDepth of the depth range of the viewport.
1552 By default this is set to 1.0f.
1553 */
1554
1555/*!
1556 \fn bool QRhiViewport::operator==(const QRhiViewport &a, const QRhiViewport &b) noexcept
1557
1558 \return \c true if the values in the two QRhiViewport objects
1559 \a a and \a b are equal.
1560 */
1561
1562/*!
1563 \fn bool QRhiViewport::operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept
1564
1565 \return \c false if the values in the two QRhiViewport
1566 objects \a a and \a b are equal; otherwise returns \c true.
1567*/
1568
1569/*!
1570 \fn size_t QRhiViewport::qHash(const QRhiViewport &key, size_t seed)
1571 \qhash{QRhiViewport}
1572 */
1573
1574#ifndef QT_NO_DEBUG_STREAM
1575QDebug operator<<(QDebug dbg, const QRhiViewport &v)
1576{
1577 QDebugStateSaver saver(dbg);
1578 const std::array<float, 4> r = v.viewport();
1579 dbg.nospace() << "QRhiViewport(bottom-left-x=" << r[0]
1580 << " bottom-left-y=" << r[1]
1581 << " width=" << r[2]
1582 << " height=" << r[3]
1583 << " minDepth=" << v.minDepth()
1584 << " maxDepth=" << v.maxDepth()
1585 << ')';
1586 return dbg;
1587}
1588#endif
1589
1590/*!
1591 \class QRhiScissor
1592 \inmodule QtGuiPrivate
1593 \inheaderfile rhi/qrhi.h
1594 \since 6.6
1595 \brief Specifies a scissor rectangle.
1596
1597 Used with QRhiCommandBuffer::setScissor(). Setting a scissor rectangle is
1598 only possible with a QRhiGraphicsPipeline that has
1599 QRhiGraphicsPipeline::UsesScissor set.
1600
1601 QRhi assumes OpenGL-style scissor coordinates, meaning x and y are
1602 bottom-left. Negative width or height are not allowed. However, apart from
1603 that, the flexible OpenGL semantics apply: negative x and y, partially out
1604 of bounds rectangles, etc. will be handled gracefully, clamping as
1605 appropriate. Therefore, any rendering logic targeting OpenGL can feed
1606 scissor rectangles into QRhiScissor as-is, without any adaptation.
1607
1608 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1609 for details.
1610
1611 \sa QRhiCommandBuffer::setScissor(), QRhiViewport
1612 */
1613
1614/*!
1615 \fn QRhiScissor::QRhiScissor() = default
1616
1617 Constructs an empty scissor.
1618 */
1619
1620/*!
1621 Constructs a scissor with the rectangle specified by \a x, \a y, \a w, and
1622 \a h.
1623
1624 \note \a x and \a y are assumed to be the bottom-left position. Negative \a w
1625 or \a h are not allowed, such scissor rectangles will be ignored by
1626 QRhiCommandBuffer. Other than that, the flexible OpenGL semantics apply:
1627 negative x and y, partially out of bounds rectangles, etc. will be handled
1628 gracefully, clamping as appropriate.
1629 */
1630QRhiScissor::QRhiScissor(int x, int y, int w, int h)
1631 : m_rect { { x, y, w, h } }
1632{
1633}
1634
1635/*!
1636 \fn std::array<int, 4> QRhiScissor::scissor() const
1637 \return the scissor position and size.
1638 */
1639
1640/*!
1641 \fn void QRhiScissor::setScissor(int x, int y, int w, int h)
1642 Sets the scissor position and size to \a x, \a y, \a w, \a h.
1643
1644 \note The position is always expected to be specified in a coordinate
1645 system that has its origin in the bottom-left corner, like OpenGL.
1646 */
1647
1648/*!
1649 \fn bool QRhiScissor::operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept
1650
1651 \return \c true if the values in the two QRhiScissor objects
1652 \a a and \a b are equal.
1653 */
1654
1655/*!
1656 \fn bool QRhiScissor::operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept
1657
1658 \return \c false if the values in the two QRhiScissor
1659 objects \a a and \a b are equal; otherwise returns \c true.
1660*/
1661
1662/*!
1663 \fn size_t QRhiScissor::qHash(const QRhiScissor &key, size_t seed)
1664 \qhash{QRhiScissor}
1665 */
1666
1667#ifndef QT_NO_DEBUG_STREAM
1668QDebug operator<<(QDebug dbg, const QRhiScissor &s)
1669{
1670 QDebugStateSaver saver(dbg);
1671 const std::array<int, 4> r = s.scissor();
1672 dbg.nospace() << "QRhiScissor(bottom-left-x=" << r[0]
1673 << " bottom-left-y=" << r[1]
1674 << " width=" << r[2]
1675 << " height=" << r[3]
1676 << ')';
1677 return dbg;
1678}
1679#endif
1680
1681/*!
1682 \class QRhiVertexInputBinding
1683 \inmodule QtGuiPrivate
1684 \inheaderfile rhi/qrhi.h
1685 \since 6.6
1686 \brief Describes a vertex input binding.
1687
1688 Specifies the stride (in bytes, must be a multiple of 4), the
1689 classification and optionally the instance step rate.
1690
1691 As an example, assume a vertex shader with the following inputs:
1692
1693 \badcode
1694 layout(location = 0) in vec4 position;
1695 layout(location = 1) in vec2 texcoord;
1696 \endcode
1697
1698 Now let's assume also that 3 component vertex positions \c{(x, y, z)} and 2
1699 component texture coordinates \c{(u, v)} are provided in a non-interleaved
1700 format in a buffer (or separate buffers even). Defining two bindings
1701 could then be done like this:
1702
1703 \code
1704 QRhiVertexInputLayout inputLayout;
1705 inputLayout.setBindings({
1706 { 3 * sizeof(float) },
1707 { 2 * sizeof(float) }
1708 });
1709 \endcode
1710
1711 Only the stride is interesting here since instancing is not used. The
1712 binding number is given by the index of the QRhiVertexInputBinding
1713 element in the bindings vector of the QRhiVertexInputLayout.
1714
1715 Once a graphics pipeline with this vertex input layout is bound, the vertex
1716 inputs could be set up like the following for drawing a cube with 36
1717 vertices, assuming we have a single buffer with first the positions and
1718 then the texture coordinates:
1719
1720 \code
1721 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1722 { cubeBuf, 0 },
1723 { cubeBuf, 36 * 3 * sizeof(float) }
1724 };
1725 cb->setVertexInput(0, 2, vbufBindings);
1726 \endcode
1727
1728 Note how the index defined by \c {startBinding + i}, where \c i is the
1729 index in the second argument of
1730 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}, matches the
1731 index of the corresponding entry in the \c bindings vector of the
1732 QRhiVertexInputLayout.
1733
1734 \note the stride must always be a multiple of 4.
1735
1736 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1737 for details.
1738
1739 \sa QRhiCommandBuffer::setVertexInput()
1740 */
1741
1742/*!
1743 \enum QRhiVertexInputBinding::Classification
1744 Describes the input data classification.
1745
1746 \value PerVertex Data is per-vertex
1747 \value PerInstance Data is per-instance
1748 */
1749
1750/*!
1751 \fn QRhiVertexInputBinding::QRhiVertexInputBinding() = default
1752
1753 Constructs a default vertex input binding description.
1754 */
1755
1756/*!
1757 Constructs a vertex input binding description with the specified \a stride,
1758 classification \a cls, and instance step rate \a stepRate.
1759
1760 \note \a stepRate other than 1 is only supported when
1761 QRhi::CustomInstanceStepRate is reported to be supported.
1762 */
1763QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cls, quint32 stepRate)
1764 : m_stride(stride),
1765 m_classification(cls),
1766 m_instanceStepRate(stepRate)
1767{
1768}
1769
1770/*!
1771 \fn quint32 QRhiVertexInputBinding::stride() const
1772 \return the stride in bytes.
1773 */
1774
1775/*!
1776 \fn void QRhiVertexInputBinding::setStride(quint32 s)
1777 Sets the stride to \a s.
1778 */
1779
1780/*!
1781 \fn QRhiVertexInputBinding::Classification QRhiVertexInputBinding::classification() const
1782 \return the input data classification.
1783 */
1784
1785/*!
1786 \fn void QRhiVertexInputBinding::setClassification(Classification c)
1787 Sets the input data classification \a c. By default this is set to PerVertex.
1788 */
1789
1790/*!
1791 \fn quint32 QRhiVertexInputBinding::instanceStepRate() const
1792 \return the instance step rate.
1793 */
1794
1795/*!
1796 \fn void QRhiVertexInputBinding::setInstanceStepRate(quint32 rate)
1797 Sets the instance step \a rate. By default this is set to 1.
1798 */
1799
1800/*!
1801 \fn bool QRhiVertexInputBinding::operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1802
1803 \return \c true if the values in the two QRhiVertexInputBinding objects
1804 \a a and \a b are equal.
1805 */
1806
1807/*!
1808 \fn bool QRhiVertexInputBinding::operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1809
1810 \return \c false if the values in the two QRhiVertexInputBinding
1811 objects \a a and \a b are equal; otherwise returns \c true.
1812*/
1813
1814/*!
1815 \fn size_t QRhiVertexInputBinding::qHash(const QRhiVertexInputBinding &key, size_t seed)
1816 \qhash{QRhiVertexInputBinding}
1817 */
1818
1819#ifndef QT_NO_DEBUG_STREAM
1820QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
1821{
1822 QDebugStateSaver saver(dbg);
1823 dbg.nospace() << "QRhiVertexInputBinding(stride=" << b.stride()
1824 << " cls=" << b.classification()
1825 << " step-rate=" << b.instanceStepRate()
1826 << ')';
1827 return dbg;
1828}
1829#endif
1830
1831/*!
1832 \class QRhiVertexInputAttribute
1833 \inmodule QtGuiPrivate
1834 \inheaderfile rhi/qrhi.h
1835 \since 6.6
1836 \brief Describes a single vertex input element.
1837
1838 The members specify the binding number, location, format, and offset for a
1839 single vertex input element.
1840
1841 \note For HLSL it is assumed that the vertex shader translated from SPIR-V
1842 uses
1843 \c{TEXCOORD<location>} as the semantic for each input. Hence no separate
1844 semantic name and index.
1845
1846 As an example, assume a vertex shader with the following inputs:
1847
1848 \badcode
1849 layout(location = 0) in vec4 position;
1850 layout(location = 1) in vec2 texcoord;
1851 \endcode
1852
1853 Now let's assume that we have 3 component vertex positions \c{(x, y, z)}
1854 and 2 component texture coordinates \c{(u, v)} are provided in a
1855 non-interleaved format in a buffer (or separate buffers even). Once two
1856 bindings are defined, the attributes could be specified as:
1857
1858 \code
1859 QRhiVertexInputLayout inputLayout;
1860 inputLayout.setBindings({
1861 { 3 * sizeof(float) },
1862 { 2 * sizeof(float) }
1863 });
1864 inputLayout.setAttributes({
1865 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1866 { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
1867 });
1868 \endcode
1869
1870 Once a graphics pipeline with this vertex input layout is bound, the vertex
1871 inputs could be set up like the following for drawing a cube with 36
1872 vertices, assuming we have a single buffer with first the positions and
1873 then the texture coordinates:
1874
1875 \code
1876 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1877 { cubeBuf, 0 },
1878 { cubeBuf, 36 * 3 * sizeof(float) }
1879 };
1880 cb->setVertexInput(0, 2, vbufBindings);
1881 \endcode
1882
1883 When working with interleaved data, there will typically be just one
1884 binding, with multiple attributes referring to that same buffer binding
1885 point:
1886
1887 \code
1888 QRhiVertexInputLayout inputLayout;
1889 inputLayout.setBindings({
1890 { 5 * sizeof(float) }
1891 });
1892 inputLayout.setAttributes({
1893 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1894 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
1895 });
1896 \endcode
1897
1898 and then:
1899
1900 \code
1901 const QRhiCommandBuffer::VertexInput vbufBinding(interleavedCubeBuf, 0);
1902 cb->setVertexInput(0, 1, &vbufBinding);
1903 \endcode
1904
1905 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1906 for details.
1907
1908 \sa QRhiCommandBuffer::setVertexInput()
1909 */
1910
1911/*!
1912 \enum QRhiVertexInputAttribute::Format
1913 Specifies the type of the element data.
1914
1915 \value Float4 Four component float vector
1916 \value Float3 Three component float vector
1917 \value Float2 Two component float vector
1918 \value Float Float
1919 \value UNormByte4 Four component normalized unsigned byte vector
1920 \value UNormByte2 Two component normalized unsigned byte vector
1921 \value UNormByte Normalized unsigned byte
1922 \value UInt4 Four component unsigned integer vector
1923 \value UInt3 Three component unsigned integer vector
1924 \value UInt2 Two component unsigned integer vector
1925 \value UInt Unsigned integer
1926 \value SInt4 Four component signed integer vector
1927 \value SInt3 Three component signed integer vector
1928 \value SInt2 Two component signed integer vector
1929 \value SInt Signed integer
1930 \value Half4 Four component half precision (16 bit) float vector
1931 \value Half3 Three component half precision (16 bit) float vector
1932 \value Half2 Two component half precision (16 bit) float vector
1933 \value Half Half precision (16 bit) float
1934 \value UShort4 Four component unsigned short (16 bit) integer vector
1935 \value UShort3 Three component unsigned short (16 bit) integer vector
1936 \value UShort2 Two component unsigned short (16 bit) integer vector
1937 \value UShort Unsigned short (16 bit) integer
1938 \value SShort4 Four component signed short (16 bit) integer vector
1939 \value SShort3 Three component signed short (16 bit) integer vector
1940 \value SShort2 Two component signed short (16 bit) integer vector
1941 \value SShort Signed short (16 bit) integer
1942
1943 \note Support for half precision floating point attributes is indicated at
1944 run time by the QRhi::Feature::HalfAttributes feature flag.
1945
1946 \note Direct3D 11/12 supports 16 bit input attributes, but does not support
1947 the Half3, UShort3 or SShort3 types. The D3D backends pass through Half3 as
1948 Half4, UShort3 as UShort4, and SShort3 as SShort4. To ensure cross platform
1949 compatibility, 16 bit inputs should be padded to 8 bytes.
1950 */
1951
1952/*!
1953 \fn QRhiVertexInputAttribute::QRhiVertexInputAttribute() = default
1954
1955 Constructs a default vertex input attribute description.
1956 */
1957
1958/*!
1959 Constructs a vertex input attribute description with the specified \a
1960 binding number, \a location, \a format, and \a offset.
1961
1962 \a matrixSlice should be -1 except when this attribute corresponds to a row
1963 or column of a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming
1964 4 consecutive vertex input locations), in which case it is the index of the
1965 row or column. \c{location - matrixSlice} must always be equal to the \c
1966 location for the first row or column of the unrolled matrix.
1967 */
1968QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset, int matrixSlice)
1969 : m_binding(binding),
1970 m_location(location),
1971 m_format(format),
1972 m_offset(offset),
1973 m_matrixSlice(matrixSlice)
1974{
1975}
1976
1977/*!
1978 \fn int QRhiVertexInputAttribute::binding() const
1979 \return the binding point index.
1980 */
1981
1982/*!
1983 \fn void QRhiVertexInputAttribute::setBinding(int b)
1984 Sets the binding point index to \a b.
1985 By default this is set to 0.
1986 */
1987
1988/*!
1989 \fn int QRhiVertexInputAttribute::location() const
1990 \return the location of the vertex input element.
1991 */
1992
1993/*!
1994 \fn void QRhiVertexInputAttribute::setLocation(int loc)
1995 Sets the location of the vertex input element to \a loc.
1996 By default this is set to 0.
1997 */
1998
1999/*!
2000 \fn QRhiVertexInputAttribute::Format QRhiVertexInputAttribute::format() const
2001 \return the format of the vertex input element.
2002 */
2003
2004/*!
2005 \fn void QRhiVertexInputAttribute::setFormat(Format f)
2006 Sets the format of the vertex input element to \a f.
2007 By default this is set to Float4.
2008 */
2009
2010/*!
2011 \fn quint32 QRhiVertexInputAttribute::offset() const
2012 \return the byte offset for the input element.
2013 */
2014
2015/*!
2016 \fn void QRhiVertexInputAttribute::setOffset(quint32 ofs)
2017 Sets the byte offset for the input element to \a ofs.
2018 */
2019
2020/*!
2021 \fn int QRhiVertexInputAttribute::matrixSlice() const
2022
2023 \return the matrix slice if the input element corresponds to a row or
2024 column of a matrix, or -1 if not relevant.
2025 */
2026
2027/*!
2028 \fn void QRhiVertexInputAttribute::setMatrixSlice(int slice)
2029
2030 Sets the matrix \a slice. By default this is set to -1, and should be set
2031 to a >= 0 value only when this attribute corresponds to a row or column of
2032 a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming 4
2033 consecutive vertex input locations), in which case it is the index of the
2034 row or column. \c{location - matrixSlice} must always be equal to the \c
2035 location for the first row or column of the unrolled matrix.
2036 */
2037
2038/*!
2039 \fn bool QRhiVertexInputAttribute::operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
2040
2041 \return \c true if the values in the two QRhiVertexInputAttribute objects
2042 \a a and \a b are equal.
2043 */
2044
2045/*!
2046 \fn bool QRhiVertexInputAttribute::operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
2047
2048 \return \c false if the values in the two QRhiVertexInputAttribute
2049 objects \a a and \a b are equal; otherwise returns \c true.
2050*/
2051
2052/*!
2053 \fn size_t QRhiVertexInputAttribute::qHash(const QRhiVertexInputAttribute &key, size_t seed)
2054 \qhash{QRhiVertexInputAttribute}
2055 */
2056
2057#ifndef QT_NO_DEBUG_STREAM
2058QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a)
2059{
2060 QDebugStateSaver saver(dbg);
2061 dbg.nospace() << "QRhiVertexInputAttribute(binding=" << a.binding()
2062 << " location=" << a.location()
2063 << " format=" << a.format()
2064 << " offset=" << a.offset()
2065 << ')';
2066 return dbg;
2067}
2068#endif
2069
2070QRhiVertexInputAttribute::Format QRhiImplementation::shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const
2071{
2072 switch (type) {
2073 case QShaderDescription::Vec4:
2074 return QRhiVertexInputAttribute::Float4;
2075 case QShaderDescription::Vec3:
2076 return QRhiVertexInputAttribute::Float3;
2077 case QShaderDescription::Vec2:
2078 return QRhiVertexInputAttribute::Float2;
2079 case QShaderDescription::Float:
2080 return QRhiVertexInputAttribute::Float;
2081
2082 case QShaderDescription::Int4:
2083 return QRhiVertexInputAttribute::SInt4;
2084 case QShaderDescription::Int3:
2085 return QRhiVertexInputAttribute::SInt3;
2086 case QShaderDescription::Int2:
2087 return QRhiVertexInputAttribute::SInt2;
2088 case QShaderDescription::Int:
2089 return QRhiVertexInputAttribute::SInt;
2090
2091 case QShaderDescription::Uint4:
2092 return QRhiVertexInputAttribute::UInt4;
2093 case QShaderDescription::Uint3:
2094 return QRhiVertexInputAttribute::UInt3;
2095 case QShaderDescription::Uint2:
2096 return QRhiVertexInputAttribute::UInt2;
2097 case QShaderDescription::Uint:
2098 return QRhiVertexInputAttribute::UInt;
2099
2100 case QShaderDescription::Half4:
2101 return QRhiVertexInputAttribute::Half4;
2102 case QShaderDescription::Half3:
2103 return QRhiVertexInputAttribute::Half3;
2104 case QShaderDescription::Half2:
2105 return QRhiVertexInputAttribute::Half2;
2106 case QShaderDescription::Half:
2107 return QRhiVertexInputAttribute::Half;
2108
2109 default:
2110 Q_UNREACHABLE_RETURN(QRhiVertexInputAttribute::Float);
2111 }
2112}
2113
2114quint32 QRhiImplementation::byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const
2115{
2116 switch (format) {
2117 case QRhiVertexInputAttribute::Float4:
2118 return 4 * sizeof(float);
2119 case QRhiVertexInputAttribute::Float3:
2120 return 4 * sizeof(float); // vec3 still takes 16 bytes
2121 case QRhiVertexInputAttribute::Float2:
2122 return 2 * sizeof(float);
2123 case QRhiVertexInputAttribute::Float:
2124 return sizeof(float);
2125
2126 case QRhiVertexInputAttribute::UNormByte4:
2127 return 4 * sizeof(quint8);
2128 case QRhiVertexInputAttribute::UNormByte2:
2129 return 2 * sizeof(quint8);
2130 case QRhiVertexInputAttribute::UNormByte:
2131 return sizeof(quint8);
2132
2133 case QRhiVertexInputAttribute::UInt4:
2134 return 4 * sizeof(quint32);
2135 case QRhiVertexInputAttribute::UInt3:
2136 return 4 * sizeof(quint32); // ivec3 still takes 16 bytes
2137 case QRhiVertexInputAttribute::UInt2:
2138 return 2 * sizeof(quint32);
2139 case QRhiVertexInputAttribute::UInt:
2140 return sizeof(quint32);
2141
2142 case QRhiVertexInputAttribute::SInt4:
2143 return 4 * sizeof(qint32);
2144 case QRhiVertexInputAttribute::SInt3:
2145 return 4 * sizeof(qint32); // uvec3 still takes 16 bytes
2146 case QRhiVertexInputAttribute::SInt2:
2147 return 2 * sizeof(qint32);
2148 case QRhiVertexInputAttribute::SInt:
2149 return sizeof(qint32);
2150
2151 case QRhiVertexInputAttribute::Half4:
2152 return 4 * sizeof(qfloat16);
2153 case QRhiVertexInputAttribute::Half3:
2154 return 4 * sizeof(qfloat16); // half3 still takes 8 bytes
2155 case QRhiVertexInputAttribute::Half2:
2156 return 2 * sizeof(qfloat16);
2157 case QRhiVertexInputAttribute::Half:
2158 return sizeof(qfloat16);
2159
2160 case QRhiVertexInputAttribute::UShort4:
2161 return 4 * sizeof(quint16);
2162 case QRhiVertexInputAttribute::UShort3:
2163 return 4 * sizeof(quint16); // ivec3 still takes 8 bytes
2164 case QRhiVertexInputAttribute::UShort2:
2165 return 2 * sizeof(quint16);
2166 case QRhiVertexInputAttribute::UShort:
2167 return sizeof(quint16);
2168
2169 case QRhiVertexInputAttribute::SShort4:
2170 return 4 * sizeof(qint16);
2171 case QRhiVertexInputAttribute::SShort3:
2172 return 4 * sizeof(qint16); // uvec3 still takes 8 bytes
2173 case QRhiVertexInputAttribute::SShort2:
2174 return 2 * sizeof(qint16);
2175 case QRhiVertexInputAttribute::SShort:
2176 return sizeof(qint16);
2177
2178 default:
2179 Q_UNREACHABLE_RETURN(1);
2180 }
2181}
2182
2183/*!
2184 \class QRhiVertexInputLayout
2185 \inmodule QtGuiPrivate
2186 \inheaderfile rhi/qrhi.h
2187 \since 6.6
2188 \brief Describes the layout of vertex inputs consumed by a vertex shader.
2189
2190 The vertex input layout is defined by the collections of
2191 QRhiVertexInputBinding and QRhiVertexInputAttribute.
2192
2193 As an example, let's assume that we have a single buffer with 3 component
2194 vertex positions and 2 component UV coordinates interleaved (\c x, \c y, \c
2195 z, \c u, \c v), that the position and UV are expected at input locations 0
2196 and 1 by the vertex shader, and that the vertex buffer will be bound at
2197 binding point 0 using
2198 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()} later on:
2199
2200 \code
2201 QRhiVertexInputLayout inputLayout;
2202 inputLayout.setBindings({
2203 { 5 * sizeof(float) }
2204 });
2205 inputLayout.setAttributes({
2206 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
2207 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
2208 });
2209 \endcode
2210
2211 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2212 for details.
2213 */
2214
2215/*!
2216 \fn QRhiVertexInputLayout::QRhiVertexInputLayout() = default
2217
2218 Constructs an empty vertex input layout description.
2219 */
2220
2221/*!
2222 \fn void QRhiVertexInputLayout::setBindings(std::initializer_list<QRhiVertexInputBinding> list)
2223 Sets the bindings from the specified \a list.
2224 */
2225
2226/*!
2227 \fn template<typename InputIterator> void QRhiVertexInputLayout::setBindings(InputIterator first, InputIterator last)
2228 Sets the bindings using the iterators \a first and \a last.
2229 */
2230
2231/*!
2232 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cbeginBindings() const
2233 \return a const iterator pointing to the first item in the binding list.
2234 */
2235
2236/*!
2237 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cendBindings() const
2238 \return a const iterator pointing just after the last item in the binding list.
2239 */
2240
2241/*!
2242 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::bindingAt(qsizetype index) const
2243 \return the binding at the given \a index.
2244 */
2245
2246/*!
2247 \fn qsizetype QRhiVertexInputLayout::bindingCount() const
2248 \return the number of bindings.
2249 */
2250
2251/*!
2252 \fn void QRhiVertexInputLayout::setAttributes(std::initializer_list<QRhiVertexInputAttribute> list)
2253 Sets the attributes from the specified \a list.
2254 */
2255
2256/*!
2257 \fn template<typename InputIterator> void QRhiVertexInputLayout::setAttributes(InputIterator first, InputIterator last)
2258 Sets the attributes using the iterators \a first and \a last.
2259 */
2260
2261/*!
2262 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cbeginAttributes() const
2263 \return a const iterator pointing to the first item in the attribute list.
2264 */
2265
2266/*!
2267 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cendAttributes() const
2268 \return a const iterator pointing just after the last item in the attribute list.
2269 */
2270
2271/*!
2272 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::attributeAt(qsizetype index) const
2273 \return the attribute at the given \a index.
2274 */
2275
2276/*!
2277 \fn qsizetype QRhiVertexInputLayout::attributeCount() const
2278 \return the number of attributes.
2279 */
2280
2281/*!
2282 \fn bool QRhiVertexInputLayout::operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2283
2284 \return \c true if the values in the two QRhiVertexInputLayout objects
2285 \a a and \a b are equal.
2286 */
2287
2288/*!
2289 \fn bool QRhiVertexInputLayout::operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2290
2291 \return \c false if the values in the two QRhiVertexInputLayout
2292 objects \a a and \a b are equal; otherwise returns \c true.
2293*/
2294
2295/*!
2296 \fn size_t QRhiVertexInputLayout::qHash(const QRhiVertexInputLayout &key, size_t seed)
2297 \qhash{QRhiVertexInputLayout}
2298 */
2299
2300#ifndef QT_NO_DEBUG_STREAM
2301QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
2302{
2303 QDebugStateSaver saver(dbg);
2304 dbg.nospace() << "QRhiVertexInputLayout(bindings=" << v.m_bindings
2305 << " attributes=" << v.m_attributes
2306 << ')';
2307 return dbg;
2308}
2309#endif
2310
2311/*!
2312 \class QRhiShaderStage
2313 \inmodule QtGuiPrivate
2314 \inheaderfile rhi/qrhi.h
2315 \since 6.6
2316 \brief Specifies the type and the shader code for a shader stage in the pipeline.
2317
2318 When setting up a QRhiGraphicsPipeline, a collection of shader stages are
2319 specified. The QRhiShaderStage contains a QShader and some associated
2320 metadata, such as the graphics pipeline stage, and the
2321 \l{QShader::Variant}{shader variant} to select. There is no need to specify
2322 the shader language or version because the QRhi backend in use at runtime
2323 will take care of choosing the appropriate shader version from the
2324 collection within the QShader.
2325
2326 The typical usage is in combination with
2327 QRhiGraphicsPipeline::setShaderStages(), shown here with a simple approach
2328 to load the QShader from \c{.qsb} files generated offline or at build time:
2329
2330 \code
2331 QShader getShader(const QString &name)
2332 {
2333 QFile f(name);
2334 return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
2335 }
2336
2337 QShader vs = getShader("material.vert.qsb");
2338 QShader fs = getShader("material.frag.qsb");
2339 pipeline->setShaderStages({
2340 { QRhiShaderStage::Vertex, vs },
2341 { QRhiShaderStage::Fragment, fs }
2342 });
2343 \endcode
2344
2345 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2346 for details.
2347 */
2348
2349/*!
2350 \enum QRhiShaderStage::Type
2351 Specifies the type of the shader stage.
2352
2353 \value Vertex Vertex stage
2354
2355 \value TessellationControl Tessellation control (hull shader) stage. Must
2356 be used only when the QRhi::Tessellation feature is supported.
2357
2358 \value TessellationEvaluation Tessellation evaluation (domain shader)
2359 stage. Must be used only when the QRhi::Tessellation feature is supported.
2360
2361 \value Fragment Fragment (pixel shader) stage
2362
2363 \value Compute Compute stage. Must be used only when the QRhi::Compute
2364 feature is supported.
2365
2366 \value Geometry Geometry stage. Must be used only when the
2367 QRhi::GeometryShader feature is supported.
2368 */
2369
2370/*!
2371 \fn QRhiShaderStage::QRhiShaderStage() = default
2372
2373 Constructs a shader stage description for the vertex stage with an empty
2374 QShader.
2375 */
2376
2377/*!
2378 \fn QRhiShaderStage::Type QRhiShaderStage::type() const
2379 \return the type of the stage.
2380 */
2381
2382/*!
2383 \fn void QRhiShaderStage::setType(Type t)
2384
2385 Sets the type of the stage to \a t. Setters should rarely be needed in
2386 pratice. Most applications will likely use the QRhiShaderStage constructor
2387 in most cases.
2388 */
2389
2390/*!
2391 \fn QShader QRhiShaderStage::shader() const
2392 \return the QShader to be used for this stage in the graphics pipeline.
2393 */
2394
2395/*!
2396 \fn void QRhiShaderStage::setShader(const QShader &s)
2397 Sets the shader collection \a s.
2398 */
2399
2400/*!
2401 \fn QShader::Variant QRhiShaderStage::shaderVariant() const
2402 \return the requested shader variant.
2403 */
2404
2405/*!
2406 \fn void QRhiShaderStage::setShaderVariant(QShader::Variant v)
2407 Sets the requested shader variant \a v.
2408 */
2409
2410/*!
2411 Constructs a shader stage description with the \a type of the stage and the
2412 \a shader.
2413
2414 The shader variant \a v defaults to QShader::StandardShader. A
2415 QShader contains multiple source and binary versions of a shader.
2416 In addition, it can also contain variants of the shader with slightly
2417 modified code. \a v can then be used to select the desired variant.
2418 */
2419QRhiShaderStage::QRhiShaderStage(Type type, const QShader &shader, QShader::Variant v)
2420 : m_type(type),
2421 m_shader(shader),
2422 m_shaderVariant(v)
2423{
2424}
2425
2426/*!
2427 \fn bool QRhiShaderStage::operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2428
2429 \return \c true if the values in the two QRhiShaderStage objects
2430 \a a and \a b are equal.
2431 */
2432
2433/*!
2434 \fn bool QRhiShaderStage::operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2435
2436 \return \c false if the values in the two QRhiShaderStage
2437 objects \a a and \a b are equal; otherwise returns \c true.
2438*/
2439
2440/*!
2441 \fn size_t QRhiShaderStage::qHash(const QRhiShaderStage &key, size_t seed)
2442 \qhash{QRhiShaderStage}
2443 */
2444
2445#ifndef QT_NO_DEBUG_STREAM
2446QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
2447{
2448 QDebugStateSaver saver(dbg);
2449 dbg.nospace() << "QRhiShaderStage(type=" << s.type()
2450 << " shader=" << s.shader()
2451 << " variant=" << s.shaderVariant()
2452 << ')';
2453 return dbg;
2454}
2455#endif
2456
2457/*!
2458 \class QRhiColorAttachment
2459 \inmodule QtGuiPrivate
2460 \inheaderfile rhi/qrhi.h
2461 \since 6.6
2462 \brief Describes the a single color attachment of a render target.
2463
2464 A color attachment is either a QRhiTexture or a QRhiRenderBuffer. The
2465 former, i.e. when texture() is set, is used in most cases.
2466 QRhiColorAttachment is commonly used in combination with
2467 QRhiTextureRenderTargetDescription.
2468
2469 \note texture() and renderBuffer() cannot be both set (be non-null at the
2470 same time).
2471
2472 Setting renderBuffer instead is recommended only when multisampling is
2473 needed. Relying on QRhi::MultisampleRenderBuffer is a better choice than
2474 QRhi::MultisampleTexture in practice since the former is available in more
2475 run time configurations (e.g. when running on OpenGL ES 3.0 which has no
2476 support for multisample textures, but does support multisample
2477 renderbuffers).
2478
2479 When targeting a non-multisample texture, the layer() and level() indicate
2480 the targeted layer (face index \c{0-5} for cubemaps) and mip level. For 3D
2481 textures layer() specifies the slice (one 2D image within the 3D texture)
2482 to render to. For texture arrays layer() is the array index.
2483
2484 When texture() or renderBuffer() is multisample, resolveTexture() can be
2485 set optionally. When set, samples are resolved automatically into that
2486 (non-multisample) texture at the end of the render pass. When rendering
2487 into a multisample renderbuffers, this is the only way to get resolved,
2488 non-multisample content out of them. Multisample textures allow sampling in
2489 shaders so for them this is just one option.
2490
2491 \note when resolving is enabled, the multisample data may not be written
2492 out at all. This means that the multisample texture() must not be used
2493 afterwards with shaders for sampling when resolveTexture() is set.
2494
2495 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2496 for details.
2497
2498 \sa QRhiTextureRenderTargetDescription
2499 */
2500
2501/*!
2502 \fn QRhiColorAttachment::QRhiColorAttachment() = default
2503
2504 Constructs an empty color attachment description.
2505 */
2506
2507/*!
2508 Constructs a color attachment description that specifies \a texture as the
2509 associated color buffer.
2510 */
2511QRhiColorAttachment::QRhiColorAttachment(QRhiTexture *texture)
2512 : m_texture(texture)
2513{
2514}
2515
2516/*!
2517 Constructs a color attachment description that specifies \a renderBuffer as
2518 the associated color buffer.
2519 */
2520QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
2521 : m_renderBuffer(renderBuffer)
2522{
2523}
2524
2525/*!
2526 \fn QRhiTexture *QRhiColorAttachment::texture() const
2527
2528 \return the texture this attachment description references, or \nullptr if
2529 there is none.
2530 */
2531
2532/*!
2533 \fn void QRhiColorAttachment::setTexture(QRhiTexture *tex)
2534
2535 Sets the texture \a tex.
2536
2537 \note texture() and renderBuffer() cannot be both set (be non-null at the
2538 same time).
2539 */
2540
2541/*!
2542 \fn QRhiRenderBuffer *QRhiColorAttachment::renderBuffer() const
2543
2544 \return the renderbuffer this attachment description references, or
2545 \nullptr if there is none.
2546
2547 In practice associating a QRhiRenderBuffer with a QRhiColorAttachment makes
2548 the most sense when setting up multisample rendering via a multisample
2549 \l{QRhiRenderBuffer::Type}{color} renderbuffer that is then resolved into a
2550 non-multisample texture at the end of the render pass.
2551 */
2552
2553/*!
2554 \fn void QRhiColorAttachment::setRenderBuffer(QRhiRenderBuffer *rb)
2555
2556 Sets the renderbuffer \a rb.
2557
2558 \note texture() and renderBuffer() cannot be both set (be non-null at the
2559 same time).
2560 */
2561
2562/*!
2563 \fn int QRhiColorAttachment::layer() const
2564 \return the layer index (cubemap face or array layer). 0 by default.
2565 */
2566
2567/*!
2568 \fn void QRhiColorAttachment::setLayer(int layer)
2569 Sets the \a layer index.
2570 */
2571
2572/*!
2573 \fn int QRhiColorAttachment::level() const
2574 \return the mip level. 0 by default.
2575 */
2576
2577/*!
2578 \fn void QRhiColorAttachment::setLevel(int level)
2579 Sets the mip \a level.
2580 */
2581
2582/*!
2583 \fn QRhiTexture *QRhiColorAttachment::resolveTexture() const
2584
2585 \return the resolve texture this attachment description references, or
2586 \nullptr if there is none.
2587
2588 Setting a non-null resolve texture is applicable when the attachment
2589 references a multisample texture or renderbuffer. The QRhiTexture in the
2590 resolveTexture() is then a non-multisample 2D texture (or texture array)
2591 with the same size (but a sample count of 1). The multisample content is
2592 automatically resolved into this texture at the end of each render pass.
2593 */
2594
2595/*!
2596 \fn void QRhiColorAttachment::setResolveTexture(QRhiTexture *tex)
2597
2598 Sets the resolve texture \a tex.
2599
2600 \a tex is expected to be a 2D texture or a 2D texture array. In either
2601 case, resolving targets a single mip level of a single layer (array
2602 element) of \a tex. The mip level and array layer are specified by
2603 resolveLevel() and resolveLayer().
2604
2605 An exception is \l{setMultiViewCount()}{multiview}: when the color
2606 attachment is associated with a texture array and multiview is enabled, the
2607 resolve texture must also be a texture array with sufficient elements for
2608 all views. In this case all elements that correspond to views are resolved
2609 automatically; the behavior is similar to the following pseudo-code:
2610 \badcode
2611 for (i = 0; i < multiViewCount(); ++i)
2612 resolve texture's layer() + i into resolveTexture's resolveLayer() + i
2613 \endcode
2614
2615 Setting a non-multisample texture to resolve a multisample texture or
2616 renderbuffer automatically at the end of the render pass is often
2617 preferable to working with multisample textures (and not setting a resolve
2618 texture), because it avoids the need for writing dedicated fragment shaders
2619 that work exclusively with multisample textures (\c sampler2DMS, \c
2620 texelFetch, etc.), and rather allows using the same shader as one would if
2621 the attachment's texture was not multisampled to begin with. This comes at
2622 the expense of an additional resource (the non-multisample \a tex).
2623 */
2624
2625/*!
2626 \fn int QRhiColorAttachment::resolveLayer() const
2627 \return the currently set resolve texture layer. Defaults to 0.
2628 */
2629
2630/*!
2631 \fn void QRhiColorAttachment::setResolveLayer(int layer)
2632 Sets the resolve texture \a layer to use.
2633 */
2634
2635/*!
2636 \fn int QRhiColorAttachment::resolveLevel() const
2637 \return the currently set resolve texture mip level. Defaults to 0.
2638 */
2639
2640/*!
2641 \fn void QRhiColorAttachment::setResolveLevel(int level)
2642 Sets the resolve texture mip \a level to use.
2643 */
2644
2645/*!
2646 \fn int QRhiColorAttachment::multiViewCount() const
2647
2648 \return the currently set number of views. Defaults to 0 which indicates
2649 the render target with this color attachment is not going to be used with
2650 multiview rendering.
2651
2652 \since 6.7
2653 */
2654
2655/*!
2656 \fn void QRhiColorAttachment::setMultiViewCount(int count)
2657
2658 Sets the view \a count. Setting a value larger than 1 indicates that the
2659 render target with this color attachment is going to be used with multiview
2660 rendering. The default value is 0. Values smaller than 2 indicate no
2661 multiview rendering.
2662
2663 When \a count is set to \c 2 or greater, the color attachment must be
2664 associated with a 2D texture array. layer() and multiViewCount() together
2665 define the range of texture array elements that are targeted during
2666 multiview rendering.
2667
2668 For example, if \c layer is \c 0 and \c multiViewCount is \c 2, the texture
2669 array must have 2 (or more) elements, and the multiview rendering will
2670 target elements 0 and 1. The \c{gl_ViewIndex} variable in the shaders has a
2671 value of \c 0 or \c 1 then, where view \c 0 corresponds to the texture array
2672 element \c 0, and view \c 1 to the array element \c 1.
2673
2674 \note Setting a \a count larger than 1, using a texture array as texture(),
2675 and calling \l{QRhiCommandBuffer::beginPass()}{beginPass()} on a
2676 QRhiTextureRenderTarget with this color attachment implies multiview
2677 rendering for the entire render pass. multiViewCount() should not be set
2678 unless multiview rendering is wanted. Multiview cannot be used with texture
2679 types other than 2D texture arrays. (although 3D textures may work,
2680 depending on the graphics API and backend; applications are nonetheless
2681 advised not to rely on that and only use 2D texture arrays as the render
2682 targets of multiview rendering)
2683
2684 See
2685 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2686 for more details regarding multiview rendering. Do note that Qt requires
2687 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview2.txt}{GL_OVR_multiview2}
2688 as well, when running on OpenGL (ES).
2689
2690 Multiview rendering is available only when the
2691 \l{QRhi::MultiView}{MultiView} feature is reported as supported from
2692 \l{QRhi::isFeatureSupported()}{isFeatureSupported()}.
2693
2694 \note For portability, be aware of limitations that exist for multiview
2695 rendering with some of the graphics APIs. It is recommended that multiview
2696 render passes do not rely on any of the features that
2697 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2698 declares as unsupported. The one exception is shader stage outputs other
2699 than \c{gl_Position} depending on \c{gl_ViewIndex}: that can be relied on
2700 (even with OpenGL) because QRhi never reports multiview as supported without
2701 \c{GL_OVR_multiview2} also being present.
2702
2703 \note Multiview rendering is not supported in combination with tessellation
2704 or geometry shaders, even though some implementations of some graphics APIs
2705 may allow this.
2706
2707 \since 6.7
2708 */
2709
2710/*!
2711 \class QRhiTextureRenderTargetDescription
2712 \inmodule QtGuiPrivate
2713 \inheaderfile rhi/qrhi.h
2714 \since 6.6
2715 \brief Describes the color and depth or depth/stencil attachments of a render target.
2716
2717 A texture render target has zero or more textures as color attachments,
2718 zero or one renderbuffer as combined depth/stencil buffer or zero or one
2719 texture as depth buffer.
2720
2721 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2722 non-null at the same time).
2723
2724 Let's look at some example usages in combination with
2725 QRhiTextureRenderTarget.
2726
2727 Due to the constructors, the targeting a texture (and no depth/stencil
2728 buffer) is simple:
2729
2730 \code
2731 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256), 1, QRhiTexture::RenderTarget);
2732 texture->create();
2733 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture }));
2734 \endcode
2735
2736 The following creates a texture render target that is set up to target mip
2737 level #2 of a texture:
2738
2739 \code
2740 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget | QRhiTexture::MipMapped);
2741 texture->create();
2742 QRhiColorAttachment colorAtt(texture);
2743 colorAtt.setLevel(2);
2744 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt });
2745 \endcode
2746
2747 Another example, this time to render into a depth texture:
2748
2749 \code
2750 QRhiTexture *shadowMap = rhi->newTexture(QRhiTexture::D32F, QSize(1024, 1024), 1, QRhiTexture::RenderTarget);
2751 shadowMap->create();
2752 QRhiTextureRenderTargetDescription rtDesc;
2753 rtDesc.setDepthTexture(shadowMap);
2754 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2755 \endcode
2756
2757 A very common case, having a texture as the color attachment and a
2758 renderbuffer as depth/stencil to enable depth testing:
2759
2760 \code
2761 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2762 texture->create();
2763 QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512));
2764 depthStencil->create();
2765 QRhiTextureRenderTargetDescription rtDesc({ texture }, depthStencil);
2766 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2767 \endcode
2768
2769 Finally, to enable multisample rendering in a portable manner (so also
2770 supporting OpenGL ES 3.0), using a QRhiRenderBuffer as the (multisample)
2771 color buffer and then resolving into a regular (non-multisample) 2D
2772 texture. To enable depth testing, a depth-stencil buffer, which also must
2773 use the same sample count, is used as well:
2774
2775 \code
2776 QRhiRenderBuffer *colorBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4); // 4x MSAA
2777 colorBuffer->create();
2778 QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512), 4);
2779 depthStencil->create();
2780 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2781 texture->create();
2782 QRhiColorAttachment colorAtt(colorBuffer);
2783 colorAtt.setResolveTexture(texture);
2784 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt, depthStencil });
2785 \endcode
2786
2787 \note when multisample resolving is enabled, the multisample data may not be
2788 written out at all. This means that the multisample texture in a color
2789 attachment must not be used afterwards with shaders for sampling (or other
2790 purposes) whenever a resolve texture is set, since the multisample color
2791 buffer is merely an intermediate storage then that gets no data written back
2792 on some GPU architectures at all. See
2793 \l{QRhiTextureRenderTarget::Flag}{PreserveColorContents} for more details.
2794
2795 \note When using setDepthTexture(), not setDepthStencilBuffer(), and the
2796 depth (stencil) data is not of interest afterwards, set the
2797 DoNotStoreDepthStencilContents flag on the QRhiTextureRenderTarget. This
2798 allows indicating to the underlying 3D API that the depth/stencil data can
2799 be discarded, leading potentially to better performance with tiled GPU
2800 architectures. When the depth-stencil buffer is a QRhiRenderBuffer (and also
2801 for the multisample color texture, see previous note) this is implicit, but
2802 with a depth (stencil) QRhiTexture the intention needs to be declared
2803 explicitly. By default QRhi assumes that the data is of interest (e.g., the
2804 depth texture is sampled in a shader afterwards).
2805
2806 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2807 for details.
2808
2809 \sa QRhiColorAttachment, QRhiTextureRenderTarget
2810 */
2811
2812/*!
2813 \fn QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription() = default
2814
2815 Constructs an empty texture render target description.
2816 */
2817
2818/*!
2819 Constructs a texture render target description with one attachment
2820 described by \a colorAttachment.
2821 */
2822QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment)
2823{
2824 m_colorAttachments.append(colorAttachment);
2825}
2826
2827/*!
2828 Constructs a texture render target description with two attachments, a
2829 color attachment described by \a colorAttachment, and a depth/stencil
2830 attachment with \a depthStencilBuffer.
2831 */
2832QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2833 QRhiRenderBuffer *depthStencilBuffer)
2834 : m_depthStencilBuffer(depthStencilBuffer)
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 attachment
2842 with \a depthTexture.
2843
2844 \note \a depthTexture must have a suitable format, such as QRhiTexture::D16
2845 or QRhiTexture::D32F.
2846 */
2847QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2848 QRhiTexture *depthTexture)
2849 : m_depthTexture(depthTexture)
2850{
2851 m_colorAttachments.append(colorAttachment);
2852}
2853
2854/*!
2855 \fn void QRhiTextureRenderTargetDescription::setColorAttachments(std::initializer_list<QRhiColorAttachment> list)
2856 Sets the \a list of color attachments.
2857 */
2858
2859/*!
2860 \fn template<typename InputIterator> void QRhiTextureRenderTargetDescription::setColorAttachments(InputIterator first, InputIterator last)
2861 Sets the list of color attachments via the iterators \a first and \a last.
2862 */
2863
2864/*!
2865 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cbeginColorAttachments() const
2866 \return a const iterator pointing to the first item in the attachment list.
2867 */
2868
2869/*!
2870 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cendColorAttachments() const
2871 \return a const iterator pointing just after the last item in the attachment list.
2872 */
2873
2874/*!
2875 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::colorAttachmentAt(qsizetype index) const
2876 \return the color attachment at the specified \a index.
2877 */
2878
2879/*!
2880 \fn qsizetype QRhiTextureRenderTargetDescription::colorAttachmentCount() const
2881 \return the number of currently set color attachments.
2882 */
2883
2884/*!
2885 \fn QRhiRenderBuffer *QRhiTextureRenderTargetDescription::depthStencilBuffer() const
2886 \return the renderbuffer used as depth-stencil buffer, or \nullptr if none was set.
2887 */
2888
2889/*!
2890 \fn void QRhiTextureRenderTargetDescription::setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer)
2891
2892 Sets the \a renderBuffer for depth-stencil. Not mandatory, e.g. when no
2893 depth test/write or stencil-related features are used within any graphics
2894 pipelines in any of the render passes for this render target, it can be
2895 left set to \nullptr.
2896
2897 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2898 non-null at the same time).
2899
2900 Using a QRhiRenderBuffer over a 2D QRhiTexture as the depth or
2901 depth/stencil buffer is very common, and is the recommended approach for
2902 applications. Using a QRhiTexture, and so setDepthTexture() becomes
2903 relevant if the depth data is meant to be accessed (e.g. sampled in a
2904 shader) afterwards, or when
2905 \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering} is
2906 involved (because then the depth texture must be a texture array).
2907
2908 \sa setDepthTexture()
2909 */
2910
2911/*!
2912 \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthTexture() const
2913 \return the currently referenced depth texture, or \nullptr if none was set.
2914 */
2915
2916/*!
2917 \fn void QRhiTextureRenderTargetDescription::setDepthTexture(QRhiTexture *texture)
2918
2919 Sets the \a texture for depth-stencil. This is an alternative to
2920 setDepthStencilBuffer(), where instead of a QRhiRenderBuffer a QRhiTexture
2921 with a suitable type (e.g., QRhiTexture::D32F) is provided.
2922
2923 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2924 non-null at the same time).
2925
2926 \a texture can either be a 2D texture or a 2D texture array (when texture
2927 arrays are supported). Specifying a texture array is relevant in particular
2928 with
2929 \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering}.
2930
2931 \note If \a texture is a format with a stencil component, such as
2932 \l QRhiTexture::D24S8, it will serve as the stencil buffer as well.
2933
2934 \sa setDepthStencilBuffer()
2935 */
2936
2937/*!
2938 \fn int QRhiTextureRenderTargetDescription::depthLayer() const
2939 \return the array slice index to be used for the depth/stencil attachment,
2940 or -1 by default.
2941
2942 \since 6.12
2943 \sa setDepthLayer(), setDepthTexture()
2944 */
2945
2946/*!
2947 \fn void QRhiTextureRenderTargetDescription::setDepthLayer(int depthLayer)
2948
2949 Sets the array slice index to be used for the depth/stencil attachment.
2950
2951 Pass -1 (the default) to not target a particular layer. When set to a
2952 non-negative value, the render target attaches a view that targets exactly
2953 that layer (slice) of the depth texture. This is only effective when a 2D
2954 array depth texture is provided via setDepthTexture(); otherwise the value
2955 is ignored.
2956
2957 The value must be within the array size of the depth texture; passing an
2958 out-of-range index leads to undefined behavior. The index is absolute
2959 with respect to the underlying texture, regardless of any array range
2960 that may have been specified when creating the texture.
2961
2962 Specifying a \a depthLayer disables layered/multiview rendering for the
2963 depth attachment.
2964
2965 \since 6.12
2966 \sa depthLayer(), setDepthTexture()
2967 */
2968
2969/*!
2970 \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthResolveTexture() const
2971
2972 \return the texture to which a multisample depth (or depth-stencil) texture
2973 (or texture array) is resolved to. \nullptr if there is none, which is the
2974 most common case.
2975
2976 \since 6.8
2977 \sa QRhiColorAttachment::resolveTexture(), depthTexture()
2978 */
2979
2980/*!
2981 \fn void QRhiTextureRenderTargetDescription::setDepthResolveTexture(QRhiTexture *tex)
2982
2983 Sets the depth (or depth-stencil) resolve texture \a tex.
2984
2985 \a tex is expected to be a 2D texture or a 2D texture array with a format
2986 matching the texture set via setDepthTexture().
2987
2988 \note Resolving depth (or depth-stencil) data is only functional when the
2989 \l QRhi::ResolveDepthStencil feature is reported as supported at run time.
2990 Support for depth-stencil resolve is not universally available among the
2991 graphics APIs. Designs assuming unconditional availability of depth-stencil
2992 resolve are therefore non-portable, and should be avoided.
2993
2994 \note As an additional limitation for OpenGL ES in particular, setting a
2995 depth resolve texture may only be functional in combination with
2996 setDepthTexture(), not with setDepthStencilBuffer().
2997
2998 \since 6.8
2999 \sa QRhiColorAttachment::setResolveTexture(), setDepthTexture()
3000 */
3001
3002/*!
3003 \fn QRhiShadingRateMap *QRhiTextureRenderTargetDescription::shadingRateMap() const
3004 \return the currently set QRhiShadingRateMap. By default this is \nullptr.
3005 \since 6.9
3006 */
3007
3008/*!
3009 \fn void QRhiTextureRenderTargetDescription::setShadingRateMap(QRhiShadingRateMap *map)
3010
3011 Associates with the specified QRhiShadingRateMap \a map. This is functional
3012 only when the \l QRhi::VariableRateShadingMap feature is reported as
3013 supported.
3014
3015 When QRhiCommandBuffer::setShadingRate() is also called, the higher of the
3016 two shading rates is used for each tile. There is currently no control
3017 offered over the combiner behavior.
3018
3019 \note When the render target had already been built (create() was called
3020 successfully), setting a shading rate map implies that a different, new
3021 QRhiRenderPassDescriptor is needed and thus a rebuild is needed. Call
3022 setRenderPassDescriptor() again (outside of a render pass) and then rebuild
3023 by calling create(). This has other rolling consequences as well, for
3024 example for graphics pipelines: those also need to be associated with the
3025 new QRhiRenderPassDescriptor and then rebuilt. See \l
3026 QRhiRenderPassDescriptor::serializedFormat() for some suggestions on how to
3027 deal with this. Remember to set the QRhiGraphicsPipeline::UsesShadingRate
3028 flag as well.
3029
3030 \since 6.9
3031 */
3032
3033/*!
3034 \class QRhiTextureSubresourceUploadDescription
3035 \inmodule QtGuiPrivate
3036 \inheaderfile rhi/qrhi.h
3037 \since 6.6
3038 \brief Describes the source for one mip level in a layer in a texture upload operation.
3039
3040 The source content is specified either as a QImage or as a raw blob. The
3041 former is only allowed for uncompressed textures with a format that can be
3042 mapped to QImage, while the latter is supported for all formats, including
3043 floating point and compressed.
3044
3045 \note image() and data() cannot be both set at the same time.
3046
3047 destinationTopLeft() specifies the top-left corner of the target
3048 rectangle. Defaults to (0, 0).
3049
3050 An empty sourceSize() (the default) indicates that size is assumed to be
3051 the size of the subresource. With QImage-based uploads this implies that
3052 the size of the source image() must match the subresource. When providing
3053 raw data instead, sufficient number of bytes must be provided in data().
3054
3055 sourceTopLeft() is supported only for QImage-based uploads, and specifies
3056 the top-left corner of the source rectangle.
3057
3058 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3059 internally, depending on the format and the backend.
3060
3061 When providing raw data, and the stride is not specified via
3062 setDataStride(), the stride (row pitch, row length in bytes) of the
3063 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
3064 the number of bytes used for one pixel, and there must be no additional
3065 padding between rows. There is no row start alignment requirement.
3066
3067 When there is unused data at the end of each row in the input raw data,
3068 call setDataStride() with the total number of bytes per row. The stride
3069 must always be a multiple of the number of bytes for one pixel. The row
3070 stride is only applicable to image data for textures with an uncompressed
3071 format.
3072
3073 \note The format of the source data must be compatible with the texture
3074 format. With many graphics APIs the data is copied as-is into a staging
3075 buffer, there is no intermediate format conversion provided by QRhi. This
3076 applies to floating point formats as well, with, for example, RGBA16F
3077 requiring half floats in the source data.
3078
3079 \note Setting the stride via setDataStride() is only functional when
3080 QRhi::ImageDataStride is reported as
3081 \l{QRhi::isFeatureSupported()}{supported}. In practice this can be expected
3082 to be supported everywhere except for OpenGL ES 2.0.
3083
3084 \note When a QImage is given, the stride returned from
3085 QImage::bytesPerLine() is taken into account automatically.
3086
3087 \warning When a QImage is given and the QImage does not own the underlying
3088 pixel data, it is up to the caller to ensure that the associated data stays
3089 valid until the end of the frame. (just submitting the resource update batch
3090 is not sufficient, the data must stay valid until QRhi::endFrame() is called
3091 in order to be portable across all backends) If this cannot be ensured, the
3092 caller is strongly encouraged to call QImage::detach() on the image before
3093 passing it to uploadTexture().
3094
3095 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3096 for details.
3097
3098 \sa QRhiTextureUploadDescription
3099 */
3100
3101/*!
3102 \fn QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription() = default
3103
3104 Constructs an empty subresource description.
3105
3106 \note an empty QRhiTextureSubresourceUploadDescription is not useful on its
3107 own and should not be submitted to a QRhiTextureUploadEntry. At minimum
3108 image or data must be set first.
3109 */
3110
3111/*!
3112 Constructs a mip level description with a \a image.
3113
3114 The \l{QImage::size()}{size} of \a image must match the size of the mip
3115 level. For level 0 that is the \l{QRhiTexture::pixelSize()}{texture size}.
3116
3117 The bit depth of \a image must be compatible with the
3118 \l{QRhiTexture::Format}{texture format}.
3119
3120 To describe a partial upload, call setSourceSize(), setSourceTopLeft(), or
3121 setDestinationTopLeft() afterwards.
3122 */
3123QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QImage &image)
3124 : m_image(image)
3125{
3126}
3127
3128/*!
3129 Constructs a mip level description with the image data is specified by \a
3130 data and \a size. This is suitable for floating point and compressed
3131 formats as well.
3132
3133 \a data can safely be destroyed or changed once this function returns.
3134 */
3135QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const void *data, quint32 size)
3136 : m_data(reinterpret_cast<const char *>(data), size)
3137{
3138}
3139
3140/*!
3141 Constructs a mip level description with the image data specified by \a
3142 data. This is suitable for floating point and compressed formats as well.
3143 */
3144QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QByteArray &data)
3145 : m_data(data)
3146{
3147}
3148
3149/*!
3150 \fn QImage QRhiTextureSubresourceUploadDescription::image() const
3151 \return the currently set QImage.
3152 */
3153
3154/*!
3155 \fn void QRhiTextureSubresourceUploadDescription::setImage(const QImage &image)
3156
3157 Sets \a image.
3158 Upon textures loading, the image data will be read as is, with no formats conversions.
3159
3160 \note image() and data() cannot be both set at the same time.
3161 */
3162
3163/*!
3164 \fn QByteArray QRhiTextureSubresourceUploadDescription::data() const
3165 \return the currently set raw pixel data.
3166 */
3167
3168/*!
3169 \fn void QRhiTextureSubresourceUploadDescription::setData(const QByteArray &data)
3170
3171 Sets \a data.
3172
3173 \note image() and data() cannot be both set at the same time.
3174 */
3175
3176/*!
3177 \fn quint32 QRhiTextureSubresourceUploadDescription::dataStride() const
3178 \return the currently set data stride.
3179 */
3180
3181/*!
3182 \fn void QRhiTextureSubresourceUploadDescription::setDataStride(quint32 stride)
3183
3184 Sets the data \a stride in bytes. By default this is 0 and not always
3185 relevant. When providing raw data(), and the stride is not specified via
3186 setDataStride(), the stride (row pitch, row length in bytes) of the
3187 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
3188 the number of bytes used for one pixel, and there must be no additional
3189 padding between rows. Otherwise, if there is additional space between the
3190 lines, set a non-zero \a stride. All this is applicable only when raw image
3191 data is provided, and is not necessary when working QImage since that has
3192 its own \l{QImage::bytesPerLine()}{stride} value.
3193
3194 \note When a non-zero \a stride is set, make sure the data contains the
3195 trailing padding for the last row as well, i.e. at least \c{stride * height}
3196 bytes in total. While providing the data without the last row's padding
3197 (i.e., interpreting stride as not applicable to the last row) could be safe,
3198 and is in fact safe with Vulkan, OpenGL, and D3D12, this cannot be
3199 guaranteed for all backends, so the safe approach is to avoid this and treat
3200 the last line like all others.
3201
3202 \note Setting the stride via setDataStride() is only functional when
3203 QRhi::ImageDataStride is reported as
3204 \l{QRhi::isFeatureSupported()}{supported}.
3205
3206 \note When a QImage is given, the stride returned from
3207 QImage::bytesPerLine() is taken into account automatically and therefore
3208 there is no need to set the data stride manually.
3209 */
3210
3211/*!
3212 \fn QPoint QRhiTextureSubresourceUploadDescription::destinationTopLeft() const
3213 \return the currently set destination top-left position. Defaults to (0, 0).
3214 */
3215
3216/*!
3217 \fn void QRhiTextureSubresourceUploadDescription::setDestinationTopLeft(const QPoint &p)
3218 Sets the destination top-left position \a p.
3219
3220 \note In the most common case of sourcing the image data from a QImage, Qt
3221 performs clamping of invalid texture upload sizes when the destination
3222 position + the source size exceeds the size of the targeted texture
3223 subresource (i.e, the size at the given mip level). There is also a
3224 qWarning() message printed on the debug output in this case. This is done in
3225 order to avoid confusion when the underlying 3D APIs crash and lead to GPU
3226 device removals at a later point when submitting the commands. Regardless,
3227 developers are encouraged to always validate applications by running with the
3228 Vulkan, D3D12, or Metal validation/debug layers enabled, since those offer a
3229 much wider range of checks on API usage.
3230 */
3231
3232/*!
3233 \fn QSize QRhiTextureSubresourceUploadDescription::sourceSize() const
3234
3235 \return the source size in pixels. Defaults to a default-constructed QSize,
3236 which indicates the entire subresource.
3237 */
3238
3239/*!
3240 \fn void QRhiTextureSubresourceUploadDescription::setSourceSize(const QSize &size)
3241
3242 Sets the source \a size in pixels.
3243
3244 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3245 internally, depending on the format and the backend.
3246 */
3247
3248/*!
3249 \fn QPoint QRhiTextureSubresourceUploadDescription::sourceTopLeft() const
3250 \return the currently set source top-left position. Defaults to (0, 0).
3251 */
3252
3253/*!
3254 \fn void QRhiTextureSubresourceUploadDescription::setSourceTopLeft(const QPoint &p)
3255
3256 Sets the source top-left position \a p.
3257
3258 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3259 internally, depending on the format and the backend.
3260 */
3261
3262/*!
3263 \class QRhiTextureUploadEntry
3264 \inmodule QtGuiPrivate
3265 \inheaderfile rhi/qrhi.h
3266 \since 6.6
3267
3268 \brief Describes one layer (face for cubemaps, slice for 3D textures,
3269 element for texture arrays) in a texture upload operation.
3270
3271 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3272 for details.
3273 */
3274
3275/*!
3276 \fn QRhiTextureUploadEntry::QRhiTextureUploadEntry()
3277
3278 Constructs an empty QRhiTextureUploadEntry targeting layer 0 and level 0.
3279
3280 \note an empty QRhiTextureUploadEntry should not be submitted without
3281 setting a QRhiTextureSubresourceUploadDescription via setDescription()
3282 first.
3283 */
3284
3285/*!
3286 Constructs a QRhiTextureUploadEntry targeting the given \a layer and mip
3287 \a level, with the subresource contents described by \a desc.
3288 */
3289QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
3290 const QRhiTextureSubresourceUploadDescription &desc)
3291 : m_layer(layer),
3292 m_level(level),
3293 m_desc(desc)
3294{
3295}
3296
3297/*!
3298 \fn int QRhiTextureUploadEntry::layer() const
3299 \return the currently set layer index (cubemap face, array layer). Defaults to 0.
3300 */
3301
3302/*!
3303 \fn void QRhiTextureUploadEntry::setLayer(int layer)
3304 Sets the \a layer.
3305 */
3306
3307/*!
3308 \fn int QRhiTextureUploadEntry::level() const
3309 \return the currently set mip level. Defaults to 0.
3310 */
3311
3312/*!
3313 \fn void QRhiTextureUploadEntry::setLevel(int level)
3314 Sets the mip \a level.
3315 */
3316
3317/*!
3318 \fn QRhiTextureSubresourceUploadDescription QRhiTextureUploadEntry::description() const
3319 \return the currently set subresource description.
3320 */
3321
3322/*!
3323 \fn void QRhiTextureUploadEntry::setDescription(const QRhiTextureSubresourceUploadDescription &desc)
3324 Sets the subresource description \a desc.
3325 */
3326
3327/*!
3328 \class QRhiTextureUploadDescription
3329 \inmodule QtGuiPrivate
3330 \inheaderfile rhi/qrhi.h
3331 \since 6.6
3332 \brief Describes a texture upload operation.
3333
3334 Used with QRhiResourceUpdateBatch::uploadTexture(). That function has two
3335 variants: one taking a QImage and one taking a
3336 QRhiTextureUploadDescription. The former is a convenience version,
3337 internally creating a QRhiTextureUploadDescription with a single image
3338 targeting level 0 for layer 0.
3339
3340 An example of the common, simple case of wanting to upload the contents
3341 of a QImage to a QRhiTexture with a matching pixel size:
3342
3343 \code
3344 QImage image(256, 256, QImage::Format_RGBA8888);
3345 image.fill(Qt::green); // or could use a QPainter targeting image
3346 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256));
3347 texture->create();
3348 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
3349 u->uploadTexture(texture, image);
3350 \endcode
3351
3352 When cubemaps, pre-generated mip images, compressed textures, or partial
3353 uploads are involved, applications will have to use this class instead.
3354
3355 QRhiTextureUploadDescription also enables specifying batched uploads, which
3356 are useful for example when generating an atlas or glyph cache texture:
3357 multiple, partial uploads for the same subresource (meaning the same layer
3358 and level) are supported, and can be, depending on the backend and the
3359 underlying graphics API, more efficient when batched into the same
3360 QRhiTextureUploadDescription as opposed to issuing individual
3361 \l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} commands for
3362 each of them.
3363
3364 \note Cubemaps have one layer for each of the six faces in the order +X,
3365 -X, +Y, -Y, +Z, -Z.
3366
3367 For example, specifying the faces of a cubemap could look like the following:
3368
3369 \code
3370 QImage faces[6];
3371 // ...
3372 QVarLengthArray<QRhiTextureUploadEntry, 6> entries;
3373 for (int i = 0; i < 6; ++i)
3374 entries.append(QRhiTextureUploadEntry(i, 0, faces[i]));
3375 QRhiTextureUploadDescription desc;
3376 desc.setEntries(entries.cbegin(), entries.cend());
3377 resourceUpdates->uploadTexture(texture, desc);
3378 \endcode
3379
3380 Another example that specifies mip images for a compressed texture:
3381
3382 \code
3383 QList<QRhiTextureUploadEntry> entries;
3384 const int mipCount = rhi->mipLevelsForSize(compressedTexture->pixelSize());
3385 for (int level = 0; level < mipCount; ++level) {
3386 const QByteArray compressedDataForLevel = ..
3387 entries.append(QRhiTextureUploadEntry(0, level, compressedDataForLevel));
3388 }
3389 QRhiTextureUploadDescription desc;
3390 desc.setEntries(entries.cbegin(), entries.cend());
3391 resourceUpdates->uploadTexture(compressedTexture, desc);
3392 \endcode
3393
3394 With partial uploads targeting the same subresource, it is recommended to
3395 batch them into a single upload request, whenever possible:
3396
3397 \code
3398 QRhiTextureSubresourceUploadDescription subresDesc(image);
3399 subresDesc.setSourceSize(QSize(10, 10));
3400 subResDesc.setDestinationTopLeft(QPoint(50, 40));
3401 QRhiTextureUploadEntry entry(0, 0, subresDesc); // layer 0, level 0
3402
3403 QRhiTextureSubresourceUploadDescription subresDesc2(image);
3404 subresDesc2.setSourceSize(QSize(30, 40));
3405 subResDesc2.setDestinationTopLeft(QPoint(100, 200));
3406 QRhiTextureUploadEntry entry2(0, 0, subresDesc2); // layer 0, level 0, i.e. same subresource
3407
3408 QRhiTextureUploadDescription desc({ entry, entry2});
3409 resourceUpdates->uploadTexture(texture, desc);
3410 \endcode
3411
3412 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3413 for details.
3414
3415 \sa QRhiResourceUpdateBatch
3416 */
3417
3418/*!
3419 \fn QRhiTextureUploadDescription::QRhiTextureUploadDescription()
3420
3421 Constructs an empty texture upload description.
3422 */
3423
3424/*!
3425 Constructs a texture upload description with a single subresource upload
3426 described by \a entry.
3427 */
3428QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry)
3429{
3430 m_entries.append(entry);
3431}
3432
3433/*!
3434 Constructs a texture upload description with the specified \a list of entries.
3435
3436 \note \a list can also contain multiple QRhiTextureUploadEntry elements
3437 with the same layer and level. This makes sense when those uploads are
3438 partial, meaning their subresource description has a source size or image
3439 smaller than the subresource dimensions, and can be more efficient than
3440 issuing separate uploadTexture()'s.
3441 */
3442QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list)
3443 : m_entries(list)
3444{
3445}
3446
3447/*!
3448 \fn void QRhiTextureUploadDescription::setEntries(std::initializer_list<QRhiTextureUploadEntry> list)
3449 Sets the \a list of entries.
3450 */
3451
3452/*!
3453 \fn template<typename InputIterator> void QRhiTextureUploadDescription::setEntries(InputIterator first, InputIterator last)
3454 Sets the list of entries using the iterators \a first and \a last.
3455 */
3456
3457/*!
3458 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cbeginEntries() const
3459 \return a const iterator pointing to the first item in the entry list.
3460 */
3461
3462/*!
3463 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cendEntries() const
3464 \return a const iterator pointing just after the last item in the entry list.
3465 */
3466
3467/*!
3468 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::entryAt(qsizetype index) const
3469 \return the entry at \a index.
3470 */
3471
3472/*!
3473 \fn qsizetype QRhiTextureUploadDescription::entryCount() const
3474 \return the number of entries.
3475 */
3476
3477/*!
3478 \class QRhiBufferCopyDescription
3479 \inmodule QtGuiPrivate
3480 \inheaderfile rhi/qrhi.h
3481 \since 6.13
3482 \brief Describes a buffer-to-buffer copy operation.
3483
3484 A size() of 0 indicates that the entire source buffer is to be copied. A
3485 default constructed copy description therefore leads to copying the whole
3486 of the source buffer to the beginning of the destination buffer.
3487
3488 \note The copied region must fit both the source and the destination
3489 buffer. When it does not, QRhiResourceUpdateBatch::copyBuffer() prints a
3490 warning and drops the operation.
3491
3492 \note size(), sourceOffset(), and destinationOffset() should all be
3493 multiples of 4. This is a requirement of the blit encoder in Metal, and it
3494 applies on macOS on Intel-based devices. Other platforms and 3D APIs,
3495 including Metal on Apple Silicon and on iOS, have no such restriction, but
3496 portable code has to assume the strictest of these. Note that a size() of 0
3497 implies the full size of the source buffer, which is not necessarily a
3498 multiple of 4 either.
3499
3500 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3501 for details.
3502
3503 \sa QRhiResourceUpdateBatch::copyBuffer()
3504 */
3505
3506/*!
3507 \fn QRhiBufferCopyDescription::QRhiBufferCopyDescription()
3508
3509 Constructs an empty buffer copy description.
3510 */
3511
3512/*!
3513 \fn quint32 QRhiBufferCopyDescription::size() const
3514 \return the number of bytes to copy.
3515
3516 \note A size() of 0 indicates that the entire source buffer is to be
3517 copied.
3518 */
3519
3520/*!
3521 \fn void QRhiBufferCopyDescription::setSize(quint32 sz)
3522 Sets the number of bytes to copy to \a sz.
3523 */
3524
3525/*!
3526 \fn quint32 QRhiBufferCopyDescription::sourceOffset() const
3527 \return the offset in bytes into the source buffer. Defaults to 0.
3528 */
3529
3530/*!
3531 \fn void QRhiBufferCopyDescription::setSourceOffset(quint32 offset)
3532 Sets the source \a offset in bytes.
3533 */
3534
3535/*!
3536 \fn quint32 QRhiBufferCopyDescription::destinationOffset() const
3537 \return the offset in bytes into the destination buffer. Defaults to 0.
3538 */
3539
3540/*!
3541 \fn void QRhiBufferCopyDescription::setDestinationOffset(quint32 offset)
3542 Sets the destination \a offset in bytes.
3543 */
3544
3545/*!
3546 \class QRhiTextureCopyDescription
3547 \inmodule QtGuiPrivate
3548 \inheaderfile rhi/qrhi.h
3549 \since 6.6
3550 \brief Describes a texture-to-texture copy operation.
3551
3552 An empty pixelSize() indicates that the entire subresource is to be copied.
3553 A default constructed copy description therefore leads to copying the
3554 entire subresource at level 0 of layer 0.
3555
3556 \note The source texture must be created with
3557 QRhiTexture::UsedAsTransferSource.
3558
3559 \note The source and destination rectangles defined by pixelSize(),
3560 sourceTopLeft(), and destinationTopLeft() must fit the source and
3561 destination textures, respectively. The behavior is undefined otherwise.
3562
3563 With cubemaps, 3D textures, and texture arrays one face or slice can be
3564 copied at a time. The face or slice is specified by the source and
3565 destination layer indices. With mipmapped textures one mip level can be
3566 copied at a time. The source and destination layer and mip level indices can
3567 differ, but the size and position must be carefully controlled to avoid out
3568 of bounds copies, in which case the behavior is undefined.
3569
3570 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3571 for details.
3572 */
3573
3574/*!
3575 \fn QRhiTextureCopyDescription::QRhiTextureCopyDescription()
3576
3577 Constructs an empty texture copy description.
3578 */
3579
3580/*!
3581 \fn QSize QRhiTextureCopyDescription::pixelSize() const
3582 \return the size of the region to copy.
3583
3584 \note An empty pixelSize() indicates that the entire subresource is to be
3585 copied. A default constructed copy description therefore leads to copying
3586 the entire subresource at level 0 of layer 0.
3587 */
3588
3589/*!
3590 \fn void QRhiTextureCopyDescription::setPixelSize(const QSize &sz)
3591 Sets the size of the region to copy to \a sz.
3592 */
3593
3594/*!
3595 \fn int QRhiTextureCopyDescription::sourceLayer() const
3596 \return the source array layer (cubemap face or array layer index). Defaults to 0.
3597 */
3598
3599/*!
3600 \fn void QRhiTextureCopyDescription::setSourceLayer(int layer)
3601 Sets the source array \a layer.
3602 */
3603
3604/*!
3605 \fn int QRhiTextureCopyDescription::sourceLevel() const
3606 \return the source mip level. Defaults to 0.
3607 */
3608
3609/*!
3610 \fn void QRhiTextureCopyDescription::setSourceLevel(int level)
3611 Sets the source mip \a level.
3612 */
3613
3614/*!
3615 \fn QPoint QRhiTextureCopyDescription::sourceTopLeft() const
3616 \return the source top-left position (in pixels). Defaults to (0, 0).
3617 */
3618
3619/*!
3620 \fn void QRhiTextureCopyDescription::setSourceTopLeft(const QPoint &p)
3621 Sets the source top-left position to \a p.
3622 */
3623
3624/*!
3625 \fn int QRhiTextureCopyDescription::destinationLayer() const
3626 \return the destination array layer (cubemap face or array layer index). Default to 0.
3627 */
3628
3629/*!
3630 \fn void QRhiTextureCopyDescription::setDestinationLayer(int layer)
3631 Sets the destination array \a layer.
3632 */
3633
3634/*!
3635 \fn int QRhiTextureCopyDescription::destinationLevel() const
3636 \return the destionation mip level. Defaults to 0.
3637 */
3638
3639/*!
3640 \fn void QRhiTextureCopyDescription::setDestinationLevel(int level)
3641 Sets the destination mip \a level.
3642 */
3643
3644/*!
3645 \fn QPoint QRhiTextureCopyDescription::destinationTopLeft() const
3646 \return the destionation top-left position in pixels. Defaults to (0, 0).
3647 */
3648
3649/*!
3650 \fn void QRhiTextureCopyDescription::setDestinationTopLeft(const QPoint &p)
3651 Sets the destination top-left position \a p.
3652 */
3653
3654/*!
3655 \class QRhiReadbackDescription
3656 \inmodule QtGuiPrivate
3657 \inheaderfile rhi/qrhi.h
3658 \since 6.6
3659 \brief Describes a readback (reading back texture contents from possibly GPU-only memory) operation.
3660
3661 The source of the readback operation is either a QRhiTexture or the
3662 current backbuffer of the currently targeted QRhiSwapChain. When
3663 texture() is not set, the swapchain is used. Otherwise the specified
3664 QRhiTexture is treated as the source.
3665
3666 \note Textures used in readbacks must be created with
3667 QRhiTexture::UsedAsTransferSource.
3668
3669 \note Swapchains used in readbacks must be created with
3670 QRhiSwapChain::UsedAsTransferSource.
3671
3672 layer() and level() are only applicable when the source is a QRhiTexture.
3673
3674 \note Multisample textures cannot be read back. Readbacks are supported for
3675 multisample swapchain buffers however.
3676
3677 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3678 for details.
3679 */
3680
3681/*!
3682 \fn QRhiReadbackDescription::QRhiReadbackDescription() = default
3683
3684 Constructs an empty texture readback description.
3685
3686 \note The source texture is set to null by default, which is still a valid
3687 readback: it specifies that the backbuffer of the current swapchain is to
3688 be read back. (current meaning the frame's target swapchain at the time of
3689 committing the QRhiResourceUpdateBatch with the
3690 \l{QRhiResourceUpdateBatch::readBackTexture()}{texture readback} on it)
3691 */
3692
3693/*!
3694 Constructs an texture readback description that specifies that level 0 of
3695 layer 0 of \a texture is to be read back.
3696
3697 \note \a texture can also be null in which case this constructor is
3698 identical to the argumentless variant.
3699 */
3700QRhiReadbackDescription::QRhiReadbackDescription(QRhiTexture *texture)
3701 : m_texture(texture)
3702{
3703}
3704
3705/*!
3706 \fn QRhiTexture *QRhiReadbackDescription::texture() const
3707
3708 \return the QRhiTexture that is read back. Can be left set to \nullptr
3709 which indicates that the backbuffer of the current swapchain is to be used
3710 instead.
3711 */
3712
3713/*!
3714 \fn void QRhiReadbackDescription::setTexture(QRhiTexture *tex)
3715
3716 Sets the texture \a tex as the source of the readback operation.
3717
3718 Setting \nullptr is valid too, in which case the current swapchain's
3719 current backbuffer is used. (but then the readback cannot be issued in a
3720 non-swapchain-based frame)
3721
3722 \note Multisample textures cannot be read back. Readbacks are supported for
3723 multisample swapchain buffers however.
3724
3725 \note Textures used in readbacks must be created with
3726 QRhiTexture::UsedAsTransferSource.
3727
3728 \note Swapchains used in readbacks must be created with
3729 QRhiSwapChain::UsedAsTransferSource.
3730 */
3731
3732/*!
3733 \fn int QRhiReadbackDescription::layer() const
3734
3735 \return the currently set array layer (cubemap face, array index). Defaults to 0.
3736
3737 Applicable only when the source of the readback is a QRhiTexture.
3738 */
3739
3740/*!
3741 \fn void QRhiReadbackDescription::setLayer(int layer)
3742 Sets the array \a layer to read back.
3743 */
3744
3745/*!
3746 \fn int QRhiReadbackDescription::level() const
3747
3748 \return the currently set mip level. Defaults to 0.
3749
3750 Applicable only when the source of the readback is a QRhiTexture.
3751 */
3752
3753/*!
3754 \fn void QRhiReadbackDescription::setLevel(int level)
3755 Sets the mip \a level to read back.
3756 */
3757
3758/*!
3759 \fn const QRect &QRhiReadbackDescription::rect() const
3760 \since 6.10
3761
3762 \return the rectangle to read back. Defaults to an invalid rectangle.
3763
3764 If invalid, the entire texture or swapchain backbuffer is read back.
3765 */
3766
3767/*!
3768 \fn void QRhiReadbackDescription::setRect(const QRect &rectangle)
3769 \since 6.10
3770
3771 Sets the \a rectangle to read back.
3772 */
3773
3774/*!
3775 \class QRhiReadbackResult
3776 \inmodule QtGuiPrivate
3777 \inheaderfile rhi/qrhi.h
3778 \since 6.6
3779 \brief Describes the results of a potentially asynchronous buffer or texture readback operation.
3780
3781 When \l completed is set, the function is invoked when the \l data is
3782 available. \l format and \l pixelSize are set upon completion together with
3783 \l data.
3784
3785 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3786 for details.
3787 */
3788
3789/*!
3790 \variable QRhiReadbackResult::completed
3791
3792 Callback that is invoked upon completion, on the thread the QRhi operates
3793 on. Can be left set to \nullptr, in which case no callback is invoked.
3794 */
3795
3796/*!
3797 \variable QRhiReadbackResult::format
3798
3799 Valid only for textures, the texture format.
3800 */
3801
3802/*!
3803 \variable QRhiReadbackResult::pixelSize
3804
3805 Valid only for textures, the size in pixels.
3806 */
3807
3808/*!
3809 \variable QRhiReadbackResult::data
3810
3811 The buffer or image data.
3812
3813 \sa QRhiResourceUpdateBatch::readBackTexture(), QRhiResourceUpdateBatch::readBackBuffer()
3814 */
3815
3816
3817/*!
3818 \class QRhiNativeHandles
3819 \inmodule QtGuiPrivate
3820 \inheaderfile rhi/qrhi.h
3821 \since 6.6
3822 \brief Base class for classes exposing backend-specific collections of native resource objects.
3823
3824 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3825 for details.
3826 */
3827
3828/*!
3829 \class QRhiResource
3830 \inmodule QtGuiPrivate
3831 \inheaderfile rhi/qrhi.h
3832 \since 6.6
3833 \brief Base class for classes encapsulating native resource objects.
3834
3835 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3836 for details.
3837 */
3838
3839/*!
3840 \enum QRhiResource::Type
3841 Specifies type of the resource.
3842
3843 \value Buffer
3844 \value Texture
3845 \value Sampler
3846 \value RenderBuffer
3847 \value RenderPassDescriptor
3848 \value SwapChainRenderTarget
3849 \value TextureRenderTarget
3850 \value ShaderResourceBindings
3851 \value GraphicsPipeline
3852 \value SwapChain
3853 \value ComputePipeline
3854 \value CommandBuffer
3855 \value ShadingRateMap
3856 \value [since 6.13] IndirectCommandBuffer
3857 */
3858
3859/*!
3860 \fn virtual QRhiResource::Type QRhiResource::resourceType() const = 0
3861
3862 \return the type of the resource.
3863 */
3864
3865/*!
3866 \internal
3867 */
3868QRhiResource::QRhiResource(QRhiImplementation *rhi)
3869 : m_rhi(rhi)
3870{
3871 m_id = QRhiGlobalObjectIdGenerator::newId();
3872}
3873
3874/*!
3875 Destructor.
3876
3877 Releases (or requests deferred releasing of) the underlying native graphics
3878 resources, if there are any.
3879
3880 \note Resources referenced by commands for the current frame should not be
3881 released until the frame is submitted by QRhi::endFrame().
3882
3883 \sa destroy()
3884 */
3885QRhiResource::~QRhiResource()
3886{
3887 // destroy() cannot be called here, due to virtuals; it is up to the
3888 // subclasses to do that.
3889}
3890
3891/*!
3892 \fn virtual void QRhiResource::destroy() = 0
3893
3894 Releases (or requests deferred releasing of) the underlying native graphics
3895 resources. Safe to call multiple times, subsequent invocations will be a
3896 no-op then.
3897
3898 Once destroy() is called, the QRhiResource instance can be reused, by
3899 calling \c create() again. That will then result in creating new native
3900 graphics resources underneath.
3901
3902 \note Resources referenced by commands for the current frame should not be
3903 released until the frame is submitted by QRhi::endFrame().
3904
3905 The QRhiResource destructor also performs the same task, so calling this
3906 function is not necessary before deleting a QRhiResource.
3907
3908 \sa deleteLater()
3909 */
3910
3911/*!
3912 When called without a frame being recorded, this function is equivalent to
3913 deleting the object. Between a QRhi::beginFrame() and QRhi::endFrame()
3914 however the behavior is different: the QRhiResource will not be destroyed
3915 until the frame is submitted via QRhi::endFrame(), thus satisfying the QRhi
3916 requirement of not altering QRhiResource objects that are referenced by the
3917 frame being recorded.
3918
3919 If the QRhi that created this object is already destroyed, the object is
3920 deleted immediately.
3921
3922 Using deleteLater() can be a useful convenience in many cases, and it
3923 complements the low-level guarantee (that the underlying native graphics
3924 objects are never destroyed until it is safe to do so and it is known for
3925 sure that they are not used by the GPU in an still in-flight frame), by
3926 offering a way to make sure the C++ object instances (of QRhiBuffer,
3927 QRhiTexture, etc.) themselves also stay valid until the end of the current
3928 frame.
3929
3930 The following example shows a convenient way of creating a throwaway buffer
3931 that is only used in one frame and gets automatically released in
3932 endFrame(). (when it comes to the underlying native buffer(s), the usual
3933 guarantee applies: the QRhi backend defers the releasing of those until it
3934 is guaranteed that the frame in which the buffer is accessed by the GPU has
3935 completed)
3936
3937 \code
3938 rhi->beginFrame(swapchain);
3939 QRhiBuffer *buf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, 256);
3940 buf->deleteLater(); // !
3941 u = rhi->nextResourceUpdateBatch();
3942 u->uploadStaticBuffer(buf, data);
3943 // ... draw with buf
3944 rhi->endFrame();
3945 \endcode
3946
3947 \sa destroy()
3948 */
3949void QRhiResource::deleteLater()
3950{
3951 if (m_rhi)
3952 m_rhi->addDeleteLater(this);
3953 else
3954 delete this;
3955}
3956
3957/*!
3958 \return the currently set object name. By default the name is empty.
3959 */
3960QByteArray QRhiResource::name() const
3961{
3962 return m_objectName;
3963}
3964
3965/*!
3966 Sets a \a name for the object.
3967
3968 This allows getting descriptive names for the native graphics
3969 resources visible in graphics debugging tools, such as
3970 \l{https://renderdoc.org/}{RenderDoc} and
3971 \l{https://developer.apple.com/xcode/}{XCode}.
3972
3973 When it comes to naming native objects by relaying the name via the
3974 appropriate graphics API, note that the name is ignored when
3975 QRhi::DebugMarkers are not supported, and may, depending on the backend,
3976 also be ignored when QRhi::EnableDebugMarkers is not set.
3977
3978 \note The name may be ignored for objects other than buffers,
3979 renderbuffers, and textures, depending on the backend.
3980
3981 \note The name may be modified. For slotted resources, such as a QRhiBuffer
3982 backed by multiple native buffers, QRhi will append a suffix to make the
3983 underlying native buffers easily distinguishable from each other.
3984 */
3985void QRhiResource::setName(const QByteArray &name)
3986{
3987 m_objectName = name;
3988}
3989
3990/*!
3991 \return the global, unique identifier of this QRhiResource.
3992
3993 User code rarely needs to deal with the value directly. It is used
3994 internally for tracking and bookkeeping purposes.
3995 */
3996quint64 QRhiResource::globalResourceId() const
3997{
3998 return m_id;
3999}
4000
4001/*!
4002 \return the QRhi that created this resource.
4003
4004 If the QRhi that created this object is already destroyed, the result is
4005 \nullptr.
4006 */
4007QRhi *QRhiResource::rhi() const
4008{
4009 return m_rhi ? m_rhi->q : nullptr;
4010}
4011
4012/*!
4013 \class QRhiBuffer
4014 \inmodule QtGuiPrivate
4015 \inheaderfile rhi/qrhi.h
4016 \since 6.6
4017 \brief Vertex, index, or uniform (constant) buffer resource.
4018
4019 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4020 for details.
4021
4022 A QRhiBuffer encapsulates zero, one, or more native buffer objects (such as
4023 a \c VkBuffer or \c MTLBuffer). With some graphics APIs and backends
4024 certain types of buffers may not use a native buffer object at all (e.g.
4025 OpenGL if uniform buffer objects are not used), but this is transparent to
4026 the user of the QRhiBuffer API. Similarly, the fact that some types of
4027 buffers may use two or three native buffers underneath, in order to allow
4028 efficient per-frame content update without stalling the GPU pipeline, is
4029 mostly invisible to the applications and libraries.
4030
4031 A QRhiBuffer instance is always created by calling
4032 \l{QRhi::newBuffer()}{the QRhi's newBuffer() function}. This creates no
4033 native graphics resources. To do that, call create() after setting the
4034 appropriate options, such as the type, usage flags, size, although in most cases these
4035 are already set based on the arguments passed to
4036 \l{QRhi::newBuffer()}{newBuffer()}.
4037
4038 \section2 Example usage
4039
4040 To create a uniform buffer for a shader where the GLSL uniform block
4041 contains a single \c mat4 member, and update the contents:
4042
4043 \code
4044 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64);
4045 if (!ubuf->create()) { error(); }
4046 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4047 QMatrix4x4 mvp;
4048 // ... set up the modelview-projection matrix
4049 batch->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
4050 // ...
4051 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4052 \endcode
4053
4054 An example of creating a buffer with vertex data:
4055
4056 \code
4057 const float vertices[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f };
4058 QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices));
4059 if (!vbuf->create()) { error(); }
4060 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4061 batch->uploadStaticBuffer(vbuf, vertices);
4062 // ...
4063 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4064 \endcode
4065
4066 An index buffer:
4067
4068 \code
4069 static const quint16 indices[] = { 0, 1, 2 };
4070 QRhiBuffer *ibuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices));
4071 if (!ibuf->create()) { error(); }
4072 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4073 batch->uploadStaticBuffer(ibuf, indices);
4074 // ...
4075 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4076 \endcode
4077
4078 \section2 Common patterns
4079
4080 A call to create() destroys any existing native resources if create() was
4081 successfully called before. If those native resources are still in use by
4082 an in-flight frame (i.e., there's a chance they are still read by the GPU),
4083 the destroying of those resources is deferred automatically. Thus a very
4084 common and convenient pattern to safely increase the size of an already
4085 initialized buffer is the following. In practice this drops and creates a
4086 whole new set of native resources underneath, so it is not necessarily a
4087 cheap operation, but is more convenient and still faster than the
4088 alternatives, because by not destroying the \c buf object itself, all
4089 references to it stay valid in other data structures (e.g., in any
4090 QRhiShaderResourceBinding the QRhiBuffer is referenced from).
4091
4092 \code
4093 if (buf->size() < newSize) {
4094 buf->setSize(newSize);
4095 if (!buf->create()) { error(); }
4096 }
4097 // continue using buf, fill it with new data
4098 \endcode
4099
4100 When working with uniform buffers, it will sometimes be necessary to
4101 combine data for multiple draw calls into a single buffer for efficiency
4102 reasons. Be aware of the aligment requirements: with some graphics APIs
4103 offsets for a uniform buffer must be aligned to 256 bytes. This applies
4104 both to QRhiShaderResourceBinding and to the dynamic offsets passed to
4105 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}. Use the
4106 \l{QRhi::ubufAlignment()}{ubufAlignment()} and
4107 \l{QRhi::ubufAligned()}{ubufAligned()} functions to create portable code.
4108 As an example, the following is an outline for issuing multiple (\c N) draw
4109 calls with the same pipeline and geometry, but with a different data in the
4110 uniform buffers exposed at binding point 0. This assumes the buffer is
4111 exposed via
4112 \l{QRhiShaderResourceBinding::uniformBufferWithDynamicOffset()}{uniformBufferWithDynamicOffset()}
4113 which allows passing a QRhiCommandBuffer::DynamicOffset list to
4114 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}.
4115
4116 \code
4117 const int N = 2;
4118 const int UB_SIZE = 64 + 4; // assuming a uniform block with { mat4 matrix; float opacity; }
4119 const int ONE_UBUF_SIZE = rhi->ubufAligned(UB_SIZE);
4120 const int TOTAL_UBUF_SIZE = N * ONE_UBUF_SIZE;
4121 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, TOTAL_UBUF_SIZE);
4122 if (!ubuf->create()) { error(); }
4123 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4124 for (int i = 0; i < N; ++i) {
4125 batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE, 64, matrix.constData());
4126 batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE + 64, 4, &opacity);
4127 }
4128 // ...
4129 // beginPass(), set pipeline, etc., and then:
4130 for (int i = 0; i < N; ++i) {
4131 QRhiCommandBuffer::DynamicOffset dynOfs[] = { { 0, i * ONE_UBUF_SIZE } };
4132 cb->setShaderResources(srb, 1, dynOfs);
4133 cb->draw(36);
4134 }
4135 \endcode
4136
4137 \sa QRhiResourceUpdateBatch, QRhi, QRhiCommandBuffer
4138 */
4139
4140/*!
4141 \enum QRhiBuffer::Type
4142 Specifies storage type of buffer resource.
4143
4144 \value Immutable Indicates that the data is not expected to change ever
4145 after the initial upload. Under the hood such buffer resources are
4146 typically placed in device local (GPU) memory (on systems where
4147 applicable). Uploading new data is possible, but may be expensive. The
4148 upload typically happens by copying to a separate, host visible staging
4149 buffer from which a GPU buffer-to-buffer copy is issued into the actual
4150 GPU-only buffer.
4151
4152 \value Static Indicates that the data is expected to change only
4153 infrequently. Typically placed in device local (GPU) memory, where
4154 applicable. On backends where host visible staging buffers are used for
4155 uploading, the staging buffers are kept around for this type, unlike with
4156 Immutable, so subsequent uploads do not suffer in performance. Frequent
4157 updates, especially updates in consecutive frames, should be avoided.
4158
4159 \value Dynamic Indicates that the data is expected to change frequently.
4160 Not recommended for large buffers. Typically backed by host visible memory
4161 in 2 copies in order to allow for changing without stalling the graphics
4162 pipeline. The double buffering is managed transparently to the applications
4163 and is not exposed in the API here in any form. This is the recommended,
4164 and, with some backends, the only possible, type for buffers with
4165 UniformBuffer usage.
4166 */
4167
4168/*!
4169 \enum QRhiBuffer::UsageFlag
4170 Flag values to specify how the buffer is going to be used.
4171
4172 \value VertexBuffer Vertex buffer. This allows the QRhiBuffer to be used in
4173 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
4174
4175 \value IndexBuffer Index buffer. This allows the QRhiBuffer to be used in
4176 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
4177
4178 \value UniformBuffer Uniform buffer (also called constant buffer). This
4179 allows the QRhiBuffer to be used in combination with
4180 \l{QRhiShaderResourceBinding::UniformBuffer}{UniformBuffer}. When
4181 \l{QRhi::NonDynamicUniformBuffers}{NonDynamicUniformBuffers} is reported as
4182 not supported, this usage can only be combined with the type Dynamic.
4183
4184 \value StorageBuffer Storage buffer. This allows the QRhiBuffer to be used
4185 in combination with \l{QRhiShaderResourceBinding::BufferLoad}{BufferLoad},
4186 \l{QRhiShaderResourceBinding::BufferStore}{BufferStore}, or
4187 \l{QRhiShaderResourceBinding::BufferLoadStore}{BufferLoadStore}. This usage
4188 can only be combined with the types Immutable or Static, and is only
4189 available when the \l{QRhi::Compute}{Compute feature} is reported as
4190 supported.
4191
4192 \value [since 6.12] IndirectBuffer Indirect draw or dispatch buffer. This
4193 allows the QRhiBuffer to be used in
4194 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()},
4195 \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}, and
4196 \l{QRhiCommandBuffer::dispatchIndirect()}{dispatchIndirect()}.
4197 This usage can be combined with types Immutable or Static. Combining it with
4198 Dynamic is unsupported with D3D11, where create() will fail. This usage may
4199 also be combined with StorageBuffer on backends that support
4200 \l{QRhi::Compute}{compute shaders}, allowing indirect draw or dispatch
4201 commands to be generated by compute shaders and consumed by indirect
4202 draw/dispatch calls.
4203 */
4204
4205/*!
4206 \class QRhiBuffer::NativeBuffer
4207 \inmodule QtGuiPrivate
4208 \inheaderfile rhi/qrhi.h
4209 \brief Contains information about the underlying native resources of a buffer.
4210 */
4211
4212/*!
4213 \variable QRhiBuffer::NativeBuffer::objects
4214 \brief an array with pointers to the native object handles.
4215
4216 With OpenGL, the native handle is a GLuint value, so the elements in the \c
4217 objects array are pointers to a GLuint. With Vulkan, the native handle is a
4218 VkBuffer, so the elements of the array are pointers to a VkBuffer. With
4219 Direct3D 11 and Metal the elements are pointers to a ID3D11Buffer or
4220 MTLBuffer pointer, respectively. With Direct3D 12, the elements are
4221 pointers to a ID3D12Resource.
4222
4223 \note Pay attention to the fact that the elements are always pointers to
4224 the native buffer handle type, even if the native type itself is a pointer.
4225 (so the elements are \c{VkBuffer *} on Vulkan, even though VkBuffer itself
4226 is a pointer on 64-bit architectures).
4227 */
4228
4229/*!
4230 \variable QRhiBuffer::NativeBuffer::slotCount
4231 \brief Specifies the number of valid elements in the objects array.
4232
4233 The value can be 0, 1, 2, or 3 in practice. 0 indicates that the QRhiBuffer
4234 is not backed by any native buffer objects. This can happen with
4235 QRhiBuffers with the usage UniformBuffer when the underlying API does not
4236 support (or the backend chooses not to use) native uniform buffers. 1 is
4237 commonly used for Immutable and Static types (but some backends may
4238 differ). 2 or 3 is typical when the type is Dynamic (but some backends may
4239 differ).
4240
4241 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4242 */
4243
4244/*!
4245 \internal
4246 */
4247QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, quint32 size_)
4248 : QRhiResource(rhi),
4249 m_type(type_), m_usage(usage_), m_size(size_)
4250{
4251}
4252
4253/*!
4254 \return the resource type.
4255 */
4256QRhiResource::Type QRhiBuffer::resourceType() const
4257{
4258 return Buffer;
4259}
4260
4261/*!
4262 \fn virtual bool QRhiBuffer::create() = 0
4263
4264 Creates the corresponding native graphics resources. If there are already
4265 resources present due to an earlier create() with no corresponding
4266 destroy(), then destroy() is called implicitly first.
4267
4268 \return \c true when successful, \c false when a graphics operation failed.
4269 Regardless of the return value, calling destroy() is always safe.
4270 */
4271
4272/*!
4273 \fn QRhiBuffer::Type QRhiBuffer::type() const
4274 \return the buffer type.
4275 */
4276
4277/*!
4278 \fn void QRhiBuffer::setType(Type t)
4279 Sets the buffer's type to \a t.
4280 */
4281
4282/*!
4283 \fn QRhiBuffer::UsageFlags QRhiBuffer::usage() const
4284 \return the buffer's usage flags.
4285 */
4286
4287/*!
4288 \fn void QRhiBuffer::setUsage(UsageFlags u)
4289 Sets the buffer's usage flags to \a u.
4290 */
4291
4292/*!
4293 \fn quint32 QRhiBuffer::size() const
4294
4295 \return the buffer's size in bytes.
4296
4297 This is always the value that was passed to setSize() or QRhi::newBuffer().
4298 Internally, the native buffers may be bigger if that is required by the
4299 underlying graphics API.
4300 */
4301
4302/*!
4303 \fn void QRhiBuffer::setSize(quint32 sz)
4304
4305 Sets the size of the buffer in bytes. The size is normally specified in
4306 QRhi::newBuffer() so this function is only used when the size has to be
4307 changed. As with other setters, the size only takes effect when calling
4308 create(), and for already created buffers this involves releasing the previous
4309 native resource and creating new ones under the hood.
4310
4311 Backends may choose to allocate buffers bigger than \a sz in order to
4312 fulfill alignment requirements. This is hidden from the applications and
4313 size() will always report the size requested in \a sz.
4314 */
4315
4316/*!
4317 \return the underlying native resources for this buffer. The returned value
4318 will be empty if exposing the underlying native resources is not supported by
4319 the backend.
4320
4321 A QRhiBuffer may be backed by multiple native buffer objects, depending on
4322 the type() and the QRhi backend in use. When this is the case, all of them
4323 are returned in the objects array in the returned struct, with slotCount
4324 specifying the number of native buffer objects. While
4325 \l{QRhi::beginFrame()}{recording a frame}, QRhi::currentFrameSlot() can be
4326 used to determine which of the native buffers QRhi is using for operations
4327 that read or write from this QRhiBuffer within the frame being recorded.
4328
4329 In some cases a QRhiBuffer will not be backed by a native buffer object at
4330 all. In this case slotCount will be set to 0 and no valid native objects
4331 are returned. This is not an error, and is perfectly valid when a given
4332 backend does not use native buffers for QRhiBuffers with certain types or
4333 usages.
4334
4335 \note Be aware that QRhi backends may employ various buffer update
4336 strategies. Unlike textures, where uploading image data always means
4337 recording a buffer-to-image (or similar) copy command on the command
4338 buffer, buffers, in particular Dynamic and UniformBuffer ones, can operate
4339 in many different ways. For example, a QRhiBuffer with usage type
4340 UniformBuffer may not even be backed by a native buffer object at all if
4341 uniform buffers are not used or supported by a given backend and graphics
4342 API. There are also differences to how data is written to the buffer and
4343 the type of backing memory used. For buffers backed by host visible memory,
4344 calling this function guarantees that pending host writes are executed for
4345 all the returned native buffers.
4346
4347 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4348 */
4349QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
4350{
4351 return { {}, 0 };
4352}
4353
4354/*!
4355 \return a pointer to a memory block with the host visible buffer data.
4356
4357 This is a shortcut for medium-to-large dynamic uniform buffers that have
4358 their \b entire contents (or at least all regions that are read by the
4359 shaders in the current frame) changed \b{in every frame} and the
4360 QRhiResourceUpdateBatch-based update mechanism is seen too heavy due to the
4361 amount of data copying involved.
4362
4363 The call to this function must be eventually followed by a call to
4364 endFullDynamicUniformBufferUpdateForCurrentFrame(), before recording any
4365 render or compute pass that relies on this buffer.
4366
4367 \warning Updating data via this method is not compatible with
4368 QRhiResourceUpdateBatch-based updates and readbacks. Unexpected behavior
4369 may occur when attempting to combine the two update models for the same
4370 buffer. Similarly, the data updated this direct way may not be visible to
4371 \l{QRhiResourceUpdateBatch::readBackBuffer()}{readBackBuffer operations},
4372 depending on the backend.
4373
4374 \warning When updating buffer data via this method, the update must be done
4375 in every frame, otherwise backends that perform double or triple buffering
4376 of resources may end up in unexpected behavior.
4377
4378 \warning Partial updates are not possible with this approach since some
4379 backends may choose a strategy where the previous contents of the buffer is
4380 lost upon calling this function. Data must be written to all regions that
4381 are read by shaders in the frame currently being prepared.
4382
4383 \warning This function can only be called when recording a frame, so
4384 between QRhi::beginFrame() and QRhi::endFrame().
4385
4386 \warning This function can only be called on Dynamic buffers.
4387 */
4388char *QRhiBuffer::beginFullDynamicBufferUpdateForCurrentFrame()
4389{
4390 return nullptr;
4391}
4392
4393/*!
4394 To be called when the entire contents of the buffer data has been updated
4395 in the memory block returned from
4396 beginFullDynamicBufferUpdateForCurrentFrame().
4397 */
4398void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
4399{
4400}
4401
4402/*!
4403 \internal
4404 */
4405void QRhiBuffer::fullDynamicBufferUpdateForCurrentFrame(const void *data, quint32 size)
4406{
4407 char *p = beginFullDynamicBufferUpdateForCurrentFrame();
4408 if (p) {
4409 memcpy(p, data, size > 0 ? size : m_size);
4410 endFullDynamicBufferUpdateForCurrentFrame();
4411 }
4412}
4413
4414/*!
4415 \class QRhiRenderBuffer
4416 \inmodule QtGuiPrivate
4417 \inheaderfile rhi/qrhi.h
4418 \since 6.6
4419 \brief Renderbuffer resource.
4420
4421 Renderbuffers cannot be sampled or read but have some benefits over
4422 textures in some cases:
4423
4424 A \l DepthStencil renderbuffer may be lazily allocated and be backed by
4425 transient memory with some APIs. On some platforms this may mean the
4426 depth/stencil buffer uses no physical backing at all.
4427
4428 That transient nature has a consequence: the contents of a \l DepthStencil
4429 renderbuffer are not guaranteed to survive if a backend has to interrupt and
4430 restart a render pass internally. With Metal this happens when a draw call
4431 is implemented via indirect command buffers, which is the case for
4432 \l{QRhiCommandBuffer::drawIndirectCount()}{drawIndirectCount()} and its
4433 indexed variant, for a high draw count
4434 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()} or
4435 \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}, and
4436 also when tessellation is used. Draws recorded after such a call then
4437 depth-test against a depth buffer that lost its contents. When this matters,
4438 set the \l NoTransientBacking flag, which makes the contents preservable at
4439 the cost of the memory and bandwidth that the transient backing was saving.
4440 Alternatively, where a QRhiTextureRenderTarget is used anyway, attach a depth
4441 or depth-stencil QRhiTexture with
4442 \l{QRhiTextureRenderTargetDescription::setDepthTexture()}{setDepthTexture()}
4443 instead of a renderbuffer: that is preserved across an interruption, unless
4444 QRhiTextureRenderTarget::DoNotStoreDepthStencilContents is set.
4445
4446 Note that the indirect drawing cases above are avoidable. A
4447 QRhiIndirectCommandBuffer executed with
4448 \l{QRhiCommandBuffer::executeIndirect()}{executeIndirect()} is prepared
4449 before the render pass begins, so it never interrupts the pass however many
4450 commands it holds, and none of this applies to it. Only tessellation then
4451 remains as a reason to consider \l NoTransientBacking.
4452
4453 \l Color renderbuffers are useful since QRhi::MultisampleRenderBuffer may be
4454 supported even when QRhi::MultisampleTexture is not.
4455
4456 How the renderbuffer is implemented by a backend is not exposed to the
4457 applications. In some cases it may be backed by ordinary textures, while in
4458 others there may be a different kind of native resource used.
4459
4460 Renderbuffers that are used as (and are only used as) depth-stencil buffers
4461 in combination with a QRhiSwapChain's color buffers should have the
4462 UsedWithSwapChainOnly flag set. This serves a double purpose: such buffers,
4463 depending on the backend and the underlying APIs, be more efficient, and
4464 QRhi provides automatic sizing behavior to match the color buffers, which
4465 means calling setPixelSize() and create() are not necessary for such
4466 renderbuffers.
4467
4468 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4469 for details.
4470 */
4471
4472/*!
4473 \enum QRhiRenderBuffer::Type
4474 Specifies the type of the renderbuffer
4475
4476 \value DepthStencil Combined depth/stencil
4477 \value Color Color
4478 */
4479
4480/*!
4481 \struct QRhiRenderBuffer::NativeRenderBuffer
4482 \inmodule QtGuiPrivate
4483 \inheaderfile rhi/qrhi.h
4484 \brief Wraps a native renderbuffer object.
4485 */
4486
4487/*!
4488 \variable QRhiRenderBuffer::NativeRenderBuffer::object
4489 \brief 64-bit integer containing the native object handle.
4490
4491 Used with QRhiRenderBuffer::createFrom().
4492
4493 With OpenGL the native handle is a GLuint value. \c object is expected to
4494 be a valid OpenGL renderbuffer object ID.
4495 */
4496
4497/*!
4498 \enum QRhiRenderBuffer::Flag
4499 Flag values for flags() and setFlags()
4500
4501 \value UsedWithSwapChainOnly For DepthStencil renderbuffers this indicates
4502 that the renderbuffer is only used in combination with a QRhiSwapChain, and
4503 never in any other way. This provides automatic sizing and resource
4504 rebuilding, so calling setPixelSize() or create() is not needed whenever
4505 this flag is set. This flag value may also trigger backend-specific
4506 behavior, for example with OpenGL, where a separate windowing system
4507 interface API is in use (EGL, GLX, etc.), the flag is especially important
4508 as it avoids creating any actual renderbuffer resource as there is already
4509 a windowing system provided depth/stencil buffer as requested by
4510 QSurfaceFormat.
4511
4512 \value [since 6.13] NoTransientBacking Requests that the renderbuffer is not
4513 backed by transient, lazily allocated memory. Only relevant for
4514 \l DepthStencil renderbuffers, and only with backends that would otherwise
4515 choose such storage, which in practice means Metal on Apple GPUs. Set this
4516 when the contents have to survive a render pass being interrupted and
4517 continued internally by a backend, as described in the
4518 \l{QRhiRenderBuffer}{class documentation}. It costs actual memory and
4519 bandwidth for the depth/stencil buffer, so do not set it when not needed.
4520 In particular it is not needed on account of
4521 \l{QRhiCommandBuffer::executeIndirect()}{executeIndirect()}, which never
4522 interrupts the pass.
4523 */
4524
4525/*!
4526 \internal
4527 */
4528QRhiRenderBuffer::QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
4529 int sampleCount_, Flags flags_,
4530 QRhiTexture::Format backingFormatHint_)
4531 : QRhiResource(rhi),
4532 m_type(type_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_),
4533 m_backingFormatHint(backingFormatHint_)
4534{
4535}
4536
4537/*!
4538 \return the resource type.
4539 */
4540QRhiResource::Type QRhiRenderBuffer::resourceType() const
4541{
4542 return RenderBuffer;
4543}
4544
4545/*!
4546 \fn virtual bool QRhiRenderBuffer::create() = 0
4547
4548 Creates the corresponding native graphics resources. If there are already
4549 resources present due to an earlier create() with no corresponding
4550 destroy(), then destroy() is called implicitly first.
4551
4552 \return \c true when successful, \c false when a graphics operation failed.
4553 Regardless of the return value, calling destroy() is always safe.
4554 */
4555
4556/*!
4557 Similar to create() except that no new native renderbuffer objects are
4558 created. Instead, the native renderbuffer object specified by \a src is
4559 used.
4560
4561 This allows importing an existing renderbuffer object (which must belong to
4562 the same device or sharing context, depending on the graphics API) from an
4563 external graphics engine.
4564
4565 \note This is currently applicable to OpenGL only. This function exists
4566 solely to allow importing a renderbuffer object that is bound to some
4567 special, external object, such as an EGLImageKHR. Once the application
4568 performed the glEGLImageTargetRenderbufferStorageOES call, the renderbuffer
4569 object can be passed to this function to create a wrapping
4570 QRhiRenderBuffer, which in turn can be passed in as a color attachment to
4571 a QRhiTextureRenderTarget to enable rendering to the EGLImage.
4572
4573 \note pixelSize(), sampleCount(), and flags() must still be set correctly.
4574 Passing incorrect sizes and other values to QRhi::newRenderBuffer() and
4575 then following it with a createFrom() expecting that the native
4576 renderbuffer object alone is sufficient to deduce such values is \b wrong
4577 and will lead to problems.
4578
4579 \note QRhiRenderBuffer does not take ownership of the native object, and
4580 destroy() will not release that object.
4581
4582 \note This function is only implemented when the QRhi::RenderBufferImport
4583 feature is reported as \l{QRhi::isFeatureSupported()}{supported}. Otherwise,
4584 the function does nothing and the return value is \c false.
4585
4586 \return \c true when successful, \c false when not supported.
4587 */
4588bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
4589{
4590 Q_UNUSED(src);
4591 return false;
4592}
4593
4594/*!
4595 \fn QRhiRenderBuffer::Type QRhiRenderBuffer::type() const
4596 \return the renderbuffer type.
4597 */
4598
4599/*!
4600 \fn void QRhiRenderBuffer::setType(Type t)
4601 Sets the type to \a t.
4602 */
4603
4604/*!
4605 \fn QSize QRhiRenderBuffer::pixelSize() const
4606 \return the pixel size.
4607 */
4608
4609/*!
4610 \fn void QRhiRenderBuffer::setPixelSize(const QSize &sz)
4611 Sets the size (in pixels) to \a sz.
4612 */
4613
4614/*!
4615 \fn int QRhiRenderBuffer::sampleCount() const
4616 \return the sample count. 1 means no multisample antialiasing.
4617 */
4618
4619/*!
4620 \fn void QRhiRenderBuffer::setSampleCount(int s)
4621 Sets the sample count to \a s.
4622 */
4623
4624/*!
4625 \fn QRhiRenderBuffer::Flags QRhiRenderBuffer::flags() const
4626 \return the flags.
4627 */
4628
4629/*!
4630 \fn void QRhiRenderBuffer::setFlags(Flags f)
4631 Sets the flags to \a f.
4632 */
4633
4634/*!
4635 \fn virtual QRhiTexture::Format QRhiRenderBuffer::backingFormat() const = 0
4636
4637 \internal
4638 */
4639
4640/*!
4641 \class QRhiTexture
4642 \inmodule QtGuiPrivate
4643 \inheaderfile rhi/qrhi.h
4644 \since 6.6
4645 \brief Texture resource.
4646
4647 A QRhiTexture encapsulates a native texture object, such as a \c VkImage or
4648 \c MTLTexture.
4649
4650 A QRhiTexture instance is always created by calling
4651 \l{QRhi::newTexture()}{the QRhi's newTexture() function}. This creates no
4652 native graphics resources. To do that, call create() after setting the
4653 appropriate options, such as the format and size, although in most cases
4654 these are already set based on the arguments passed to
4655 \l{QRhi::newTexture()}{newTexture()}.
4656
4657 Setting the \l{QRhiTexture::Flags}{flags} correctly is essential, otherwise
4658 various errors can occur depending on the underlying QRhi backend and
4659 graphics API. For example, when a texture will be rendered into from a
4660 render pass via QRhiTextureRenderTarget, the texture must be created with
4661 the \l RenderTarget flag set. Similarly, when the texture is going to be
4662 \l{QRhiResourceUpdateBatch::readBackTexture()}{read back}, the \l
4663 UsedAsTransferSource flag must be set upfront. Mipmapped textures must have
4664 the MipMapped flag set. And so on. It is not possible to change the flags
4665 once create() has succeeded. To release the existing and create a new
4666 native texture object with the changed settings, call the setters and call
4667 create() again. This then might be a potentially expensive operation.
4668
4669 \section2 Example usage
4670
4671 To create a 2D texture with a size of 512x512 pixels and set its contents to all green:
4672
4673 \code
4674 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512));
4675 if (!texture->create()) { error(); }
4676 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4677 QImage image(512, 512, QImage::Format_RGBA8888);
4678 image.fill(Qt::green);
4679 batch->uploadTexture(texture, image);
4680 // ...
4681 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4682 \endcode
4683
4684 \section2 Common patterns
4685
4686 A call to create() destroys any existing native resources if create() was
4687 successfully called before. If those native resources are still in use by
4688 an in-flight frame (i.e., there's a chance they are still read by the GPU),
4689 the destroying of those resources is deferred automatically. Thus a very
4690 common and convenient pattern to safely change the size of an already
4691 existing texture is the following. In practice this drops and creates a
4692 whole new native texture resource underneath, so it is not necessarily a
4693 cheap operation, but is more convenient and still faster than the
4694 alternatives, because by not destroying the \c texture object itself, all
4695 references to it stay valid in other data structures (e.g., in any
4696 QShaderResourceBinding the QRhiTexture is referenced from).
4697
4698 \code
4699 // determine newSize, e.g. based on the swapchain's output size or other factors
4700 if (texture->pixelSize() != newSize) {
4701 texture->setPixelSize(newSize);
4702 if (!texture->create()) { error(); }
4703 }
4704 // continue using texture, fill it with new data
4705 \endcode
4706
4707 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4708 for details.
4709
4710 \sa QRhiResourceUpdateBatch, QRhi, QRhiTextureRenderTarget
4711 */
4712
4713/*!
4714 \enum QRhiTexture::Flag
4715
4716 Flag values to specify how the texture is going to be used. Not honoring
4717 the flags set before create() and attempting to use the texture in ways that
4718 was not declared upfront can lead to unspecified behavior or decreased
4719 performance depending on the backend and the underlying graphics API.
4720
4721 \value RenderTarget The texture going to be used in combination with
4722 QRhiTextureRenderTarget.
4723
4724 \value CubeMap The texture is a cubemap. Such textures have 6 layers, one
4725 for each face in the order of +X, -X, +Y, -Y, +Z, -Z. Cubemap textures
4726 cannot be multisample.
4727
4728 \value MipMapped The texture has mipmaps. The appropriate mip count is
4729 calculated automatically and can also be retrieved via
4730 QRhi::mipLevelsForSize(). The images for the mip levels have to be
4731 provided in the texture uploaded or generated via
4732 QRhiResourceUpdateBatch::generateMips(). Multisample textures cannot have
4733 mipmaps.
4734
4735 \value sRGB Use an sRGB format.
4736
4737 \value UsedAsTransferSource The texture is used as the source of a texture
4738 copy or readback, meaning the texture is given as the source in
4739 QRhiResourceUpdateBatch::copyTexture() or
4740 QRhiResourceUpdateBatch::readBackTexture().
4741
4742 \value UsedWithGenerateMips The texture is going to be used with
4743 QRhiResourceUpdateBatch::generateMips().
4744
4745 \value UsedWithLoadStore The texture is going to be used with image
4746 load/store operations, for example, in a compute shader.
4747
4748 \value UsedAsCompressedAtlas The texture has a compressed format and the
4749 dimensions of subresource uploads may not match the texture size.
4750
4751 \value ExternalOES The texture should use the GL_TEXTURE_EXTERNAL_OES
4752 target with OpenGL. This flag is ignored with other graphics APIs.
4753
4754 \value ThreeDimensional The texture is a 3D texture. Such textures should
4755 be created with the QRhi::newTexture() overload taking a depth in addition
4756 to width and height. A 3D texture can have mipmaps but cannot be
4757 multisample. When rendering into, or uploading data to a 3D texture, the \c
4758 layer specified in the render target's color attachment or the upload
4759 description refers to a single slice in range [0..depth-1]. The underlying
4760 graphics API may not support 3D textures at run time. Support is indicated
4761 by the QRhi::ThreeDimensionalTextures feature.
4762
4763 \value TextureRectangleGL The texture should use the GL_TEXTURE_RECTANGLE
4764 target with OpenGL. This flag is ignored with other graphics APIs. Just
4765 like ExternalOES, this flag is useful when working with platform APIs where
4766 native OpenGL texture objects received from the platform are wrapped in a
4767 QRhiTexture, and the platform can only provide textures for a non-2D
4768 texture target.
4769
4770 \value TextureArray The texture is a texture array, i.e. a single texture
4771 object that is a homogeneous array of 2D textures. Texture arrays are
4772 created with QRhi::newTextureArray(). The underlying graphics API may not
4773 support texture array objects at run time. Support is indicated by the
4774 QRhi::TextureArrays feature. When rendering into, or uploading data to a
4775 texture array, the \c layer specified in the render target's color
4776 attachment or the upload description selects a single element in the array.
4777
4778 \value OneDimensional The texture is a 1D texture. Such textures can be
4779 created by passing a 0 height and depth to QRhi::newTexture(). Note that
4780 there can be limitations on one dimensional textures depending on the
4781 underlying graphics API. For example, rendering to them or using them with
4782 mipmap-based filtering may be unsupported. This is indicated by the
4783 QRhi::OneDimensionalTextures and QRhi::OneDimensionalTextureMipmaps
4784 feature flags.
4785
4786 \value UsedAsShadingRateMap
4787 */
4788
4789/*!
4790 \enum QRhiTexture::Format
4791
4792 Specifies the texture format. See also QRhi::isTextureFormatSupported() and
4793 note that flags() can modify the format when QRhiTexture::sRGB is set.
4794
4795 \value UnknownFormat Not a valid format. This cannot be passed to setFormat().
4796
4797 \value RGBA8 Four components, unsigned normalized 8-bit per component. Always supported. (32 bits total)
4798
4799 \value BGRA8 Four components, unsigned normalized 8-bit per component. (32 bits total)
4800
4801 \value R8 One component, unsigned normalized 8-bit. (8 bits total)
4802
4803 \value RG8 Two components, unsigned normalized 8-bit. (16 bits total)
4804
4805 \value R16 One component, unsigned normalized 16-bit. (16 bits total)
4806
4807 \value RG16 Two components, unsigned normalized 16-bit. (32 bits total)
4808
4809 \value RED_OR_ALPHA8 Either same as R8, or is a similar format with the component swizzled to alpha,
4810 depending on \l{QRhi::RedOrAlpha8IsRed}{RedOrAlpha8IsRed}. (8 bits total)
4811
4812 \value RGBA16F Four components, 16-bit float. (64 bits total)
4813
4814 \value RGBA32F Four components, 32-bit float. (128 bits total)
4815
4816 \value R16F One component, 16-bit float. (16 bits total)
4817
4818 \value R32F One component, 32-bit float. (32 bits total)
4819
4820 \value RGB10A2 Four components, unsigned normalized 10 bit R, G, and B,
4821 2-bit alpha. This is a packed format so native endianness applies. Note
4822 that there is no BGR10A2. This is because RGB10A2 maps to
4823 DXGI_FORMAT_R10G10B10A2_UNORM with D3D, MTLPixelFormatRGB10A2Unorm with
4824 Metal, VK_FORMAT_A2B10G10R10_UNORM_PACK32 with Vulkan, and
4825 GL_RGB10_A2/GL_RGB/GL_UNSIGNED_INT_2_10_10_10_REV on OpenGL (ES). This is
4826 the only universally supported RGB30 option. The corresponding QImage
4827 formats are QImage::Format_BGR30 and QImage::Format_A2BGR30_Premultiplied.
4828 (32 bits total)
4829
4830 \value D16 16-bit depth (normalized unsigned integer)
4831
4832 \value D24 24-bit depth (normalized unsigned integer)
4833
4834 \value D24S8 24-bit depth (normalized unsigned integer), 8 bit stencil
4835
4836 \value D32F 32-bit depth (32-bit float)
4837
4838 \value [since 6.9] D32FS8 32-bit depth (32-bit float), 8 bits of stencil, 24 bits unused
4839 (64 bits total)
4840
4841 \value BC1
4842 \value BC2
4843 \value BC3
4844 \value BC4
4845 \value BC5
4846 \value BC6H
4847 \value BC7
4848
4849 \value ETC2_RGB8
4850 \value ETC2_RGB8A1
4851 \value ETC2_RGBA8
4852
4853 \value ASTC_4x4
4854 \value ASTC_5x4
4855 \value ASTC_5x5
4856 \value ASTC_6x5
4857 \value ASTC_6x6
4858 \value ASTC_8x5
4859 \value ASTC_8x6
4860 \value ASTC_8x8
4861 \value ASTC_10x5
4862 \value ASTC_10x6
4863 \value ASTC_10x8
4864 \value ASTC_10x10
4865 \value ASTC_12x10
4866 \value ASTC_12x12
4867
4868 \value [since 6.9] R8UI One component, unsigned 8-bit. (8 bits total)
4869 \value [since 6.9] R32UI One component, unsigned 32-bit. (32 bits total)
4870 \value [since 6.9] RG32UI Two components, unsigned 32-bit. (64 bits total)
4871 \value [since 6.9] RGBA32UI Four components, unsigned 32-bit. (128 bits total)
4872
4873 \value [since 6.10] R8SI One component, signed 8-bit. (8 bits total)
4874 \value [since 6.10] R32SI One component, signed 32-bit. (32 bits total)
4875 \value [since 6.10] RG32SI Two components, signed 32-bit. (64 bits total)
4876 \value [since 6.10] RGBA32SI Four components, signed 32-bit. (128 bits total)
4877 */
4878
4879// When adding new texture formats, update void tst_QRhi::textureFormats_data().
4880
4881/*!
4882 \struct QRhiTexture::NativeTexture
4883 \inmodule QtGuiPrivate
4884 \inheaderfile rhi/qrhi.h
4885 \brief Contains information about the underlying native resources of a texture.
4886 */
4887
4888/*!
4889 \variable QRhiTexture::NativeTexture::object
4890 \brief 64-bit integer containing the native object handle.
4891
4892 With OpenGL, the native handle is a GLuint value, so \c object can then be
4893 cast to a GLuint. With Vulkan, the native handle is a VkImage, so \c object
4894 can be cast to a VkImage. With Direct3D 11 and Metal \c object contains a
4895 ID3D11Texture2D or MTLTexture pointer, respectively. With Direct3D 12
4896 \c object contains a ID3D12Resource pointer.
4897 */
4898
4899/*!
4900 \variable QRhiTexture::NativeTexture::layout
4901 \brief Specifies the current image layout for APIs like Vulkan.
4902
4903 For Vulkan, \c layout contains a \c VkImageLayout value.
4904 */
4905
4906/*!
4907 \internal
4908 */
4909QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
4910 int arraySize_, int sampleCount_, Flags flags_)
4911 : QRhiResource(rhi),
4912 m_format(format_), m_pixelSize(pixelSize_), m_depth(depth_),
4913 m_arraySize(arraySize_), m_sampleCount(sampleCount_), m_flags(flags_)
4914{
4915}
4916
4917/*!
4918 \return the resource type.
4919 */
4920QRhiResource::Type QRhiTexture::resourceType() const
4921{
4922 return Texture;
4923}
4924
4925/*!
4926 \fn virtual bool QRhiTexture::create() = 0
4927
4928 Creates the corresponding native graphics resources. If there are already
4929 resources present due to an earlier create() with no corresponding
4930 destroy(), then destroy() is called implicitly first.
4931
4932 \return \c true when successful, \c false when a graphics operation failed.
4933 Regardless of the return value, calling destroy() is always safe.
4934 */
4935
4936/*!
4937 \return the underlying native resources for this texture. The returned value
4938 will be empty if exposing the underlying native resources is not supported by
4939 the backend.
4940
4941 \sa createFrom()
4942 */
4943QRhiTexture::NativeTexture QRhiTexture::nativeTexture()
4944{
4945 return {};
4946}
4947
4948/*!
4949 Similar to create(), except that no new native textures are created.
4950 Instead, the native texture resources specified by \a src is used.
4951
4952 This allows importing an existing native texture object (which must belong
4953 to the same device or sharing context, depending on the graphics API) from
4954 an external graphics engine.
4955
4956 \return true if the specified existing native texture object has been
4957 successfully wrapped as a non-owning QRhiTexture.
4958
4959 \note format(), pixelSize(), sampleCount(), and flags() must still be set
4960 correctly. Passing incorrect sizes and other values to QRhi::newTexture()
4961 and then following it with a createFrom() expecting that the native texture
4962 object alone is sufficient to deduce such values is \b wrong and will lead
4963 to problems.
4964
4965 \note QRhiTexture does not take ownership of the texture object. destroy()
4966 does not free the object or any associated memory.
4967
4968 The opposite of this operation, exposing a QRhiTexture-created native
4969 texture object to a foreign engine, is possible via nativeTexture().
4970
4971 \note When importing a 3D texture, or a texture array object, or, with
4972 OpenGL ES, an external texture, it is then especially important to set the
4973 corresponding flags (ThreeDimensional, TextureArray, ExternalOES) via
4974 setFlags() before calling this function.
4975*/
4976bool QRhiTexture::createFrom(QRhiTexture::NativeTexture src)
4977{
4978 Q_UNUSED(src);
4979 return false;
4980}
4981
4982/*!
4983 With some graphics APIs, such as Vulkan, integrating custom rendering code
4984 that uses the graphics API directly needs special care when it comes to
4985 image layouts. This function allows communicating the expected \a layout the
4986 image backing the QRhiTexture is in after the native rendering commands.
4987
4988 For example, consider rendering into a QRhiTexture's VkImage directly with
4989 Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and
4990 QRhiCommandBuffer::endExternal(), followed by using the image for texture
4991 sampling in a QRhi-based render pass. To avoid potentially incorrect image
4992 layout transitions, this function can be used to indicate what the image
4993 layout will be once the commands recorded in said code block complete.
4994
4995 Calling this function makes sense only after
4996 QRhiCommandBuffer::endExternal() and before a subsequent
4997 QRhiCommandBuffer::beginPass().
4998
4999 This function has no effect with QRhi backends where the underlying
5000 graphics API does not expose a concept of image layouts.
5001
5002 \note With Vulkan \a layout is a \c VkImageLayout. With Direct 3D 12 \a
5003 layout is a value composed of the bits from \c D3D12_RESOURCE_STATES.
5004 */
5005void QRhiTexture::setNativeLayout(int layout)
5006{
5007 Q_UNUSED(layout);
5008}
5009
5010/*!
5011 \fn QRhiTexture::Format QRhiTexture::format() const
5012 \return the texture format.
5013 */
5014
5015/*!
5016 \fn void QRhiTexture::setFormat(QRhiTexture::Format fmt)
5017
5018 Sets the requested texture format to \a fmt.
5019
5020 \note The value set is only taken into account upon the next call to
5021 create(), i.e. when the underlying graphics resource are (re)created.
5022 Setting a new value is futile otherwise and must be avoided since it can
5023 lead to inconsistent state.
5024 */
5025
5026/*!
5027 \fn QSize QRhiTexture::pixelSize() const
5028 \return the size in pixels.
5029 */
5030
5031/*!
5032 \fn void QRhiTexture::setPixelSize(const QSize &sz)
5033
5034 Sets the texture size, specified in pixels, to \a sz.
5035
5036 \note The value set is only taken into account upon the next call to
5037 create(), i.e. when the underlying graphics resource are (re)created.
5038 Setting a new value is futile otherwise and must be avoided since it can
5039 lead to inconsistent state. The same applies to all other setters as well.
5040 */
5041
5042/*!
5043 \fn int QRhiTexture::depth() const
5044 \return the depth for 3D textures.
5045 */
5046
5047/*!
5048 \fn void QRhiTexture::setDepth(int depth)
5049 Sets the \a depth for a 3D texture.
5050 */
5051
5052/*!
5053 \fn int QRhiTexture::arraySize() const
5054 \return the texture array size.
5055 */
5056
5057/*!
5058 \fn void QRhiTexture::setArraySize(int arraySize)
5059 Sets the texture \a arraySize.
5060 */
5061
5062/*!
5063 \fn int QRhiTexture::arrayRangeStart() const
5064
5065 \return the first array layer when setArrayRange() was called.
5066
5067 \sa setArrayRange()
5068 */
5069
5070/*!
5071 \fn int QRhiTexture::arrayRangeLength() const
5072
5073 \return the exposed array range size when setArrayRange() was called.
5074
5075 \sa setArrayRange()
5076*/
5077
5078/*!
5079 \fn void QRhiTexture::setArrayRange(int startIndex, int count)
5080
5081 Normally all array layers are exposed and it is up to the shader to select
5082 the layer via the third coordinate passed to the \c{texture()} GLSL
5083 function when sampling the \c sampler2DArray. When QRhi::TextureArrayRange
5084 is reported as supported, calling setArrayRange() before create() or
5085 createFrom() requests selecting only the specified range, \a count elements
5086 starting from \a startIndex. The shader logic can then be written with this
5087 in mind.
5088
5089 \sa QRhi::TextureArrayRange
5090 */
5091
5092/*!
5093 \fn Flags QRhiTexture::flags() const
5094 \return the texture flags.
5095 */
5096
5097/*!
5098 \fn void QRhiTexture::setFlags(Flags f)
5099 Sets the texture flags to \a f.
5100 */
5101
5102/*!
5103 \fn int QRhiTexture::sampleCount() const
5104 \return the sample count. 1 means no multisample antialiasing.
5105 */
5106
5107/*!
5108 \fn void QRhiTexture::setSampleCount(int s)
5109 Sets the sample count to \a s.
5110 */
5111
5112/*!
5113 \struct QRhiTexture::ViewFormat
5114 \inmodule QtGuiPrivate
5115 \inheaderfile rhi/qrhi.h
5116 \since 6.8
5117 \brief Specifies the view format for reading or writing from or to the texture.
5118
5119 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5120 for details.
5121 */
5122
5123/*!
5124 \variable QRhiTexture::ViewFormat::format
5125 */
5126
5127/*!
5128 \variable QRhiTexture::ViewFormat::srgb
5129 */
5130
5131/*!
5132 \fn QRhiTexture::ViewFormat QRhiTexture::readViewFormat() const
5133 \since 6.8
5134 \return the view format used when sampling the texture. When not called, the view
5135 format is assumed to be the same as format().
5136 */
5137
5138/*!
5139 \fn void QRhiTexture::setReadViewFormat(const ViewFormat &fmt)
5140 \since 6.8
5141
5142 Sets the shader resource view format (or the format of the view used for
5143 sampling the texture) to \a fmt. By default the same format (and sRGB-ness)
5144 is used as the texture itself, and in most cases this function does not need
5145 to be called.
5146
5147 This setting is only taken into account when the \l QRhi::TextureViewFormat
5148 feature is reported as supported.
5149
5150 \note This functionality is provided to allow "casting" between
5151 non-sRGB and sRGB in order to get the shader reads perform, or not perform,
5152 the implicit sRGB conversions. Other types of casting may or may not be
5153 functional.
5154 */
5155
5156/*!
5157 \fn QRhiTexture::ViewFormat QRhiTexture::writeViewFormat() const
5158 \since 6.8
5159 \return the view format used when writing to the texture and when using it
5160 with image load/store. When not called, the view format is assumed to be the
5161 same as format().
5162 */
5163
5164/*!
5165 \fn void QRhiTexture::setWriteViewFormat(const ViewFormat &fmt)
5166 \since 6.8
5167
5168 Sets the render target view format to \a fmt. By default the same format
5169 (and sRGB-ness) is used as the texture itself, and in most cases this
5170 function does not need to be called.
5171
5172 One common use case for providing a write view format is working with
5173 externally provided textures that, outside of our control, use an sRGB
5174 format with 3D APIs such as Vulkan or Direct 3D, but the rendering engine is
5175 already prepared to handle linearization and conversion to sRGB at the end
5176 of its shading pipeline. In this case what is wanted when rendering into
5177 such a texture is a render target view (e.g. VkImageView) that has the same,
5178 but non-sRGB format. (if e.g. from an OpenXR implementation one gets a
5179 VK_FORMAT_R8G8B8A8_SRGB texture, it is likely that rendering into it should
5180 be done using a VK_FORMAT_R8G8B8A8_UNORM view, if that is what the rendering
5181 engine's pipeline requires; in this example one would call this function
5182 with a ViewFormat that has a format of QRhiTexture::RGBA8 and \c srgb set to
5183 \c false).
5184
5185 This setting is only taken into account when the \l QRhi::TextureViewFormat
5186 feature is reported as supported.
5187
5188 \note This functionality is provided to allow "casting" between
5189 non-sRGB and sRGB in order to get the shader write not perform, or perform,
5190 the implicit sRGB conversions. Other types of casting may or may not be
5191 functional.
5192 */
5193
5194/*!
5195 \class QRhiSampler
5196 \inmodule QtGuiPrivate
5197 \inheaderfile rhi/qrhi.h
5198 \since 6.6
5199 \brief Sampler resource.
5200
5201 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5202 for details.
5203 */
5204
5205/*!
5206 \enum QRhiSampler::Filter
5207 Specifies the minification, magnification, or mipmap filtering
5208
5209 \value None Applicable only for mipmapMode(), indicates no mipmaps to be used
5210 \value Nearest
5211 \value Linear
5212 */
5213
5214/*!
5215 \enum QRhiSampler::AddressMode
5216 Specifies the addressing mode
5217
5218 \value Repeat
5219 \value ClampToEdge
5220 \value Mirror
5221 */
5222
5223/*!
5224 \enum QRhiSampler::CompareOp
5225 Specifies the texture comparison function.
5226
5227 \value Never (default)
5228 \value Less
5229 \value Equal
5230 \value LessOrEqual
5231 \value Greater
5232 \value NotEqual
5233 \value GreaterOrEqual
5234 \value Always
5235 */
5236
5237/*!
5238 \internal
5239 */
5240QRhiSampler::QRhiSampler(QRhiImplementation *rhi,
5241 Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
5242 AddressMode u_, AddressMode v_, AddressMode w_)
5243 : QRhiResource(rhi),
5244 m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_),
5245 m_addressU(u_), m_addressV(v_), m_addressW(w_),
5246 m_compareOp(QRhiSampler::Never)
5247{
5248}
5249
5250/*!
5251 \return the resource type.
5252 */
5253QRhiResource::Type QRhiSampler::resourceType() const
5254{
5255 return Sampler;
5256}
5257
5258/*!
5259 \fn QRhiSampler::Filter QRhiSampler::magFilter() const
5260 \return the magnification filter mode.
5261 */
5262
5263/*!
5264 \fn void QRhiSampler::setMagFilter(Filter f)
5265 Sets the magnification filter mode to \a f.
5266 */
5267
5268/*!
5269 \fn QRhiSampler::Filter QRhiSampler::minFilter() const
5270 \return the minification filter mode.
5271 */
5272
5273/*!
5274 \fn void QRhiSampler::setMinFilter(Filter f)
5275 Sets the minification filter mode to \a f.
5276 */
5277
5278/*!
5279 \fn QRhiSampler::Filter QRhiSampler::mipmapMode() const
5280 \return the mipmap filter mode.
5281 */
5282
5283/*!
5284 \fn void QRhiSampler::setMipmapMode(Filter f)
5285
5286 Sets the mipmap filter mode to \a f.
5287
5288 Leave this set to None when the texture has no mip levels, or when the mip
5289 levels are not to be taken into account.
5290 */
5291
5292/*!
5293 \fn QRhiSampler::AddressMode QRhiSampler::addressU() const
5294 \return the horizontal wrap mode.
5295 */
5296
5297/*!
5298 \fn void QRhiSampler::setAddressU(AddressMode mode)
5299 Sets the horizontal wrap \a mode.
5300 */
5301
5302/*!
5303 \fn QRhiSampler::AddressMode QRhiSampler::addressV() const
5304 \return the vertical wrap mode.
5305 */
5306
5307/*!
5308 \fn void QRhiSampler::setAddressV(AddressMode mode)
5309 Sets the vertical wrap \a mode.
5310 */
5311
5312/*!
5313 \fn QRhiSampler::AddressMode QRhiSampler::addressW() const
5314 \return the depth wrap mode.
5315 */
5316
5317/*!
5318 \fn void QRhiSampler::setAddressW(AddressMode mode)
5319 Sets the depth wrap \a mode.
5320 */
5321
5322/*!
5323 \fn QRhiSampler::CompareOp QRhiSampler::textureCompareOp() const
5324 \return the texture comparison function.
5325 */
5326
5327/*!
5328 \fn void QRhiSampler::setTextureCompareOp(CompareOp op)
5329 Sets the texture comparison function \a op.
5330 */
5331
5332/*!
5333 \class QRhiShadingRateMap
5334 \inmodule QtGuiPrivate
5335 \inheaderfile rhi/qrhi.h
5336 \since 6.9
5337 \brief An object that wraps a texture or another kind of native 3D API object.
5338
5339 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5340 for details.
5341
5342 For an introduction to Variable Rate Shading (VRS), see
5343 \l{https://learn.microsoft.com/en-us/windows/win32/direct3d12/vrs}. Qt
5344 supports a subset of the VRS features offered by Direct 3D 12 and Vulkan. In
5345 addition, Metal's somewhat different mechanism is supported by making it
5346 possible to set up a QRhiShadingRateMap with an existing
5347 MTLRasterizationRateMap object.
5348 */
5349
5350/*!
5351 \struct QRhiShadingRateMap::NativeShadingRateMap
5352 \inmodule QtGuiPrivate
5353 \inheaderfile rhi/qrhi.h
5354 \since 6.9
5355 \brief Wraps a native shading rate map.
5356
5357 An example is MTLRasterizationRateMap with Metal. Other 3D APIs that use
5358 textures for image-based VRS do not use this struct since those can function
5359 via the QRhiTexture-based overload of QRhiShadingRateMap::createFrom().
5360 */
5361
5362/*!
5363 \variable QRhiShadingRateMap::NativeShadingRateMap::object
5364 \brief 64-bit integer containing the native object handle.
5365
5366 Used with QRhiShadingRateMap::createFrom(). For example, with Metal,
5367 \c object is expected to be an id<MTLRasterizationRateMap>.
5368 */
5369
5370/*!
5371 \internal
5372 */
5373QRhiShadingRateMap::QRhiShadingRateMap(QRhiImplementation *rhi)
5374 : QRhiResource(rhi)
5375{
5376}
5377
5378/*!
5379 \return the resource type.
5380 */
5381QRhiResource::Type QRhiShadingRateMap::resourceType() const
5382{
5383 return ShadingRateMap;
5384}
5385
5386/*!
5387 Sets up the shading rate map to use a native 3D API shading rate object
5388 \a src.
5389
5390 \return \c true when successful, \c false when not supported.
5391
5392 \note This is functional only when the QRhi::VariableRateShadingMap feature
5393 is reported as supported, while QRhi::VariableRateShadingMapWithTexture
5394 feature is not. Currently this is true for Metal, assuming variable rate
5395 shading is supported by the GPU.
5396
5397 \note With Metal, the \c object field of \a src is expected to contain an
5398 id<MTLRasterizationRateMap>. Qt passes the MTLRasterizationRateMap on to the
5399 MTLRenderPassDescriptor, and, because Metal then interprets viewports and
5400 scissor rectangles in the map's screen space coordinate system, sizes the
5401 default scissor and converts viewports and scissors specified via
5402 QRhiCommandBuffer accordingly. The size of that coordinate system is
5403 reported by logicalSize(). Anything else, such as scaling when sampling
5404 the rendered result, is up to the application (or the XR compositor).
5405 */
5406bool QRhiShadingRateMap::createFrom(NativeShadingRateMap src)
5407{
5408 Q_UNUSED(src);
5409 return false;
5410}
5411
5412/*!
5413 Sets up the shading rate map to use the texture \a src as the
5414 image containing the per-tile shading rates.
5415
5416 \return \c true when successful, \c false when not supported.
5417
5418 The QRhiShadingRateMap does not take ownership of \a src.
5419
5420 \note This is functional only when the
5421 QRhi::VariableRateShadingMapWithTexture feature is reported as supported. In
5422 practice may be supported on Vulkan and Direct 3D 12 when using modern
5423 graphics cards. It will never be supported on OpenGL or Metal, for example.
5424
5425 \note \a src must have a format of QRhiTexture::R8UI.
5426
5427 \note \a src must have a width of \c{ceil(render_target_pixel_width /
5428 (float)tile_width)} and a height of \c{ceil(render_target_pixel_height /
5429 (float)tile_height)}. It is up to the application to ensure the size of the
5430 texture is as expected, using the above formula, at all times. The tile size
5431 can be queried via \l QRhi::resourceLimit() and
5432 QRhi::ShadingRateImageTileSize.
5433
5434 Each byte (texel) in the texture corresponds to the shading rate value for
5435 one tile. 0 indicates 1x1, while a value of 10 indicates 4x4. See
5436 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shading_rate}{D3D12_SHADING_RATE}
5437 for other possible values.
5438 */
5439bool QRhiShadingRateMap::createFrom(QRhiTexture *src)
5440{
5441 Q_UNUSED(src);
5442 return false;
5443}
5444
5445/*!
5446 \since 6.13
5447
5448 \return the size of the logical coordinate space the shading rate map
5449 defines, or an invalid QSize when the map does not define one.
5450
5451 Some implementations, Metal in particular, describe a shading rate map in
5452 terms of a logical (screen space) size that is mapped onto the physical
5453 pixels of the render target. When such a map is attached to a render
5454 target, viewports and scissor rectangles are interpreted in the logical
5455 coordinate system, and the logical size is typically larger than
5456 QRhiRenderTarget::pixelSize(). Applications that derive viewports,
5457 scissors, or projection setup from the render target size should use this
5458 size instead whenever it is valid.
5459
5460 For implementations where the shading rate map is a tile image covering
5461 the render target, such as Vulkan and Direct 3D 12, there is no separate
5462 logical coordinate space, and an invalid QSize is returned. The render
5463 target's pixel size applies as usual in that case.
5464
5465 \sa QRhiRenderTarget::pixelSize()
5466 */
5467QSize QRhiShadingRateMap::logicalSize() const
5468{
5469 return QSize();
5470}
5471
5472/*!
5473 \class QRhiRenderPassDescriptor
5474 \inmodule QtGuiPrivate
5475 \inheaderfile rhi/qrhi.h
5476 \since 6.6
5477 \brief Render pass resource.
5478
5479 A render pass, if such a concept exists in the underlying graphics API, is
5480 a collection of attachments (color, depth, stencil) and describes how those
5481 attachments are used.
5482
5483 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5484 for details.
5485 */
5486
5487/*!
5488 \internal
5489 */
5490QRhiRenderPassDescriptor::QRhiRenderPassDescriptor(QRhiImplementation *rhi)
5491 : QRhiResource(rhi)
5492{
5493}
5494
5495/*!
5496 \return the resource type.
5497 */
5498QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
5499{
5500 return RenderPassDescriptor;
5501}
5502
5503/*!
5504 \fn virtual bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const = 0
5505
5506 \return true if the \a other QRhiRenderPassDescriptor is compatible with
5507 this one, meaning \c this and \a other can be used interchangeably in
5508 QRhiGraphicsPipeline::setRenderPassDescriptor().
5509
5510 The concept of the compatibility of renderpass descriptors is similar to
5511 the \l{QRhiShaderResourceBindings::isLayoutCompatible}{layout
5512 compatibility} of QRhiShaderResourceBindings instances. They allow better
5513 reuse of QRhiGraphicsPipeline instances: for example, a
5514 QRhiGraphicsPipeline instance cache is expected to use these functions to
5515 look for a matching pipeline, instead of just comparing pointers, thus
5516 allowing a different QRhiRenderPassDescriptor and
5517 QRhiShaderResourceBindings to be used in combination with the pipeline, as
5518 long as they are compatible.
5519
5520 The exact details of compatibility depend on the underlying graphics API.
5521 Two renderpass descriptors
5522 \l{QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()}{created}
5523 from the same QRhiTextureRenderTarget are always compatible.
5524
5525 Similarly to QRhiShaderResourceBindings, compatibility can also be tested
5526 without having two existing objects available. Extracting the opaque blob by
5527 calling serializedFormat() allows testing for compatibility by comparing the
5528 returned vector to another QRhiRenderPassDescriptor's
5529 serializedFormat(). This has benefits in certain situations, because it
5530 allows testing the compatibility of a QRhiRenderPassDescriptor with a
5531 QRhiGraphicsPipeline even when the QRhiRenderPassDescriptor the pipeline was
5532 originally built with is no longer available (but the data returned from its
5533 serializedFormat() still is).
5534
5535 \sa newCompatibleRenderPassDescriptor(), serializedFormat()
5536 */
5537
5538/*!
5539 \fn virtual QRhiRenderPassDescriptor *QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor() const = 0
5540
5541 \return a new QRhiRenderPassDescriptor that is
5542 \l{isCompatible()}{compatible} with this one.
5543
5544 This function allows cloning a QRhiRenderPassDescriptor. The returned
5545 object is ready to be used, and the ownership is transferred to the caller.
5546 Cloning a QRhiRenderPassDescriptor object can become useful in situations
5547 where the object is stored in data structures related to graphics pipelines
5548 (in order to allow creating new pipelines which in turn requires a
5549 renderpass descriptor object), and the lifetime of the renderpass
5550 descriptor created from a render target may be shorter than the pipelines.
5551 (for example, because the engine manages and destroys renderpasses together
5552 with the textures and render targets it was created from) In such a
5553 situation, it can be beneficial to store a cloned version in the data
5554 structures, and thus transferring ownership as well.
5555
5556 \sa isCompatible()
5557 */
5558
5559/*!
5560 \fn virtual QVector<quint32> QRhiRenderPassDescriptor::serializedFormat() const = 0
5561
5562 \return a vector of integers containing an opaque blob describing the data
5563 relevant for \l{isCompatible()}{compatibility}.
5564
5565 Given two QRhiRenderPassDescriptor objects \c rp1 and \c rp2, if the data
5566 returned from this function is identical, then \c{rp1->isCompatible(rp2)},
5567 and vice versa hold true as well.
5568
5569 \note The returned data is meant to be used for storing in memory and
5570 comparisons during the lifetime of the QRhi the object belongs to. It is not
5571 meant for storing on disk, reusing between processes, or using with multiple
5572 QRhi instances with potentially different backends.
5573
5574 \note Calling this function is expected to be a cheap operation since the
5575 backends are not supposed to calculate the data in this function, but rather
5576 return an already calculated series of data.
5577
5578 When creating reusable components as part of a library, where graphics
5579 pipelines are created and maintained while targeting a QRhiRenderTarget (be
5580 it a swapchain or a texture) managed by the client of the library, the
5581 components must be able to deal with a changing QRhiRenderPassDescriptor.
5582 For example, because the render target changes and so invalidates the
5583 previously QRhiRenderPassDescriptor (with regards to the new render target
5584 at least) due to having a potentially different color format and attachments
5585 now. Or because \l{QRhiShadingRateMap}{variable rate shading} is taken into
5586 use dynamically. A simple pattern that helps dealing with this is performing
5587 the following check on every frame, to recognize the case when the pipeline
5588 needs to be associated with a new QRhiRenderPassDescriptor, because
5589 something is different about the render target now, compared to earlier
5590 frames:
5591
5592 \code
5593 QRhiRenderPassDescriptor *rp = m_renderTarget->renderPassDescriptor();
5594 if (m_pipeline && rp->serializedFormat() != m_renderPassFormat) {
5595 m_pipeline->setRenderPassDescriptor(rp);
5596 m_renderPassFormat = rp->serializedFormat();
5597 m_pipeline->create();
5598 }
5599 // remember to store m_renderPassFormat also when creating m_pipeline the first time
5600 \endcode
5601
5602 \sa isCompatible()
5603 */
5604
5605/*!
5606 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
5607 QRhiVulkanRenderPassNativeHandles. The returned value is \nullptr when exposing
5608 the underlying native resources is not supported by the backend.
5609
5610 \sa QRhiVulkanRenderPassNativeHandles
5611 */
5612const QRhiNativeHandles *QRhiRenderPassDescriptor::nativeHandles()
5613{
5614 return nullptr;
5615}
5616
5617/*!
5618 \class QRhiRenderTarget
5619 \inmodule QtGuiPrivate
5620 \inheaderfile rhi/qrhi.h
5621 \since 6.6
5622 \brief Represents an onscreen (swapchain) or offscreen (texture) render target.
5623
5624 Applications do not create an instance of this class directly. Rather, it
5625 is the subclass QRhiTextureRenderTarget that is instantiable by clients of
5626 the API via \l{QRhi::newTextureRenderTarget()}{newTextureRenderTarget()}.
5627 The other subclass is QRhiSwapChainRenderTarget, which is the type
5628 QRhiSwapChain returns when calling
5629 \l{QRhiSwapChain::currentFrameRenderTarget()}{currentFrameRenderTarget()}.
5630
5631 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5632 for details.
5633
5634 \sa QRhiSwapChainRenderTarget, QRhiTextureRenderTarget
5635 */
5636
5637/*!
5638 \internal
5639 */
5640QRhiRenderTarget::QRhiRenderTarget(QRhiImplementation *rhi)
5641 : QRhiResource(rhi)
5642{
5643}
5644
5645/*!
5646 \fn virtual QSize QRhiRenderTarget::pixelSize() const = 0
5647
5648 \return the size in pixels.
5649
5650 Valid only after create() has been called successfully. Until then the
5651 result is a default-constructed QSize.
5652
5653 With QRhiTextureRenderTarget the returned size is the size of the
5654 associated attachments at the time of create(), in practice the size of the
5655 first color attachment, or the depth/stencil buffer if there are no color
5656 attachments. If the associated textures or renderbuffers are resized and
5657 rebuilt afterwards, then pixelSize() performs an implicit call to create()
5658 in order to rebuild the underlying data structures. This implicit check is
5659 similar to what QRhiCommandBuffer::beginPass() does, and ensures that the
5660 returned size is always up-to-date.
5661 */
5662
5663/*!
5664 \fn virtual float QRhiRenderTarget::devicePixelRatio() const = 0
5665
5666 \return the device pixel ratio. For QRhiTextureRenderTarget this is always
5667 1. For targets retrieved from a QRhiSwapChain the value reflects the
5668 \l{QWindow::devicePixelRatio()}{device pixel ratio} of the targeted
5669 QWindow.
5670 */
5671
5672/*!
5673 \fn virtual int QRhiRenderTarget::sampleCount() const = 0
5674
5675 \return the sample count or 1 if multisample antialiasing is not relevant for
5676 this render target.
5677 */
5678
5679/*!
5680 \fn QRhiRenderPassDescriptor *QRhiRenderTarget::renderPassDescriptor() const
5681
5682 \return the associated QRhiRenderPassDescriptor.
5683 */
5684
5685/*!
5686 \fn void QRhiRenderTarget::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
5687
5688 Sets the QRhiRenderPassDescriptor \a desc for use with this render target.
5689 */
5690
5691/*!
5692 \internal
5693 */
5694QRhiSwapChainRenderTarget::QRhiSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain_)
5695 : QRhiRenderTarget(rhi),
5696 m_swapchain(swapchain_)
5697{
5698}
5699
5700/*!
5701 \class QRhiSwapChainRenderTarget
5702 \inmodule QtGuiPrivate
5703 \inheaderfile rhi/qrhi.h
5704 \since 6.6
5705 \brief Swapchain render target resource.
5706
5707 When targeting the color buffers of a swapchain, active render target is a
5708 QRhiSwapChainRenderTarget. This is what
5709 QRhiSwapChain::currentFrameRenderTarget() returns.
5710
5711 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5712 for details.
5713
5714 \sa QRhiSwapChain
5715 */
5716
5717/*!
5718 \return the resource type.
5719 */
5720QRhiResource::Type QRhiSwapChainRenderTarget::resourceType() const
5721{
5722 return SwapChainRenderTarget;
5723}
5724
5725/*!
5726 \fn QRhiSwapChain *QRhiSwapChainRenderTarget::swapChain() const
5727
5728 \return the swapchain object.
5729 */
5730
5731/*!
5732 \class QRhiTextureRenderTarget
5733 \inmodule QtGuiPrivate
5734 \inheaderfile rhi/qrhi.h
5735 \since 6.6
5736 \brief Texture render target resource.
5737
5738 A texture render target allows rendering into one or more textures,
5739 optionally with a depth texture or depth/stencil renderbuffer.
5740
5741 For multisample rendering the common approach is to use a renderbuffer as
5742 the color attachment and set the non-multisample destination texture as the
5743 \c{resolve texture}. For more information, read the detailed description of
5744 the \l QRhiColorAttachment class.
5745
5746 \note Textures used in combination with QRhiTextureRenderTarget must be
5747 created with the QRhiTexture::RenderTarget flag.
5748
5749 The simplest example of creating a render target with a texture as its
5750 single color attachment:
5751
5752 \code
5753 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
5754 texture->create();
5755 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture });
5756 rp = rt->newCompatibleRenderPassDescriptor();
5757 rt->setRenderPassDescriptor(rp);
5758 rt->create();
5759 // rt can now be used with beginPass()
5760 \endcode
5761
5762 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5763 for details.
5764 */
5765
5766/*!
5767 \enum QRhiTextureRenderTarget::Flag
5768
5769 Flag values describing the load/store behavior for the render target. The
5770 load/store behavior may be baked into native resources under the hood,
5771 depending on the backend, and therefore it needs to be known upfront and
5772 cannot be changed without rebuilding (and so releasing and creating new
5773 native resources).
5774
5775 \value PreserveColorContents Indicates that the contents of the color
5776 attachments is to be loaded when starting a render pass, instead of
5777 clearing. This is potentially more expensive, especially on mobile (tiled)
5778 GPUs, but allows preserving the existing contents between passes. When doing
5779 multisample rendering with a resolve texture set, setting this flag also
5780 requests the multisample color data to be stored (written out) to the
5781 multisample texture or render buffer. (for non-multisample rendering the
5782 color data is always stored, but for MSAA storing the multisample data
5783 decreases efficiency for certain GPU architectures, hence defaulting to not
5784 writing it out) Note however that this is non-portable: in some cases there
5785 is no intermediate multisample texture on the graphics API level, e.g. when
5786 using OpenGL ES's \c{GL_EXT_multisampled_render_to_texture} as it is all
5787 implicit, handled by the OpenGL ES implementation. In that case,
5788 PreserveColorContents will likely have no effect. Therefore, avoid relying
5789 on this flag when using multisample rendering and the color attachment is
5790 using a multisample QRhiTexture (not QRhiRenderBuffer).
5791
5792 \value PreserveDepthStencilContents Indicates that the contents of the
5793 depth texture is to be loaded when starting a render pass, instead
5794 clearing. Only applicable when a texture is used as the depth buffer
5795 (QRhiTextureRenderTargetDescription::depthTexture() is set) because
5796 depth/stencil renderbuffers may not have any physical backing and data may
5797 not be written out in the first place.
5798
5799 \value DoNotStoreDepthStencilContents Indicates that the contents of the
5800 depth texture does not need to be written out. Relevant only when a
5801 QRhiTexture, not QRhiRenderBuffer, is used as the depth-stencil buffer,
5802 because for QRhiRenderBuffer this is implicit. When a depthResolveTexture is
5803 set, the flag is not relevant, because the behavior is then as if the flag
5804 was set. This enum value is introduced in Qt 6.8.
5805 */
5806
5807/*!
5808 \internal
5809 */
5810QRhiTextureRenderTarget::QRhiTextureRenderTarget(QRhiImplementation *rhi,
5811 const QRhiTextureRenderTargetDescription &desc_,
5812 Flags flags_)
5813 : QRhiRenderTarget(rhi),
5814 m_desc(desc_),
5815 m_flags(flags_)
5816{
5817}
5818
5819/*!
5820 \return the resource type.
5821 */
5822QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
5823{
5824 return TextureRenderTarget;
5825}
5826
5827/*!
5828 \fn virtual QRhiRenderPassDescriptor *QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() = 0
5829
5830 \return a new QRhiRenderPassDescriptor that is compatible with this render
5831 target.
5832
5833 The returned value is used in two ways: it can be passed to
5834 setRenderPassDescriptor() and
5835 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
5836 describes the attachments (color, depth/stencil) and the load/store
5837 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
5838 be used in combination with a render target that has a
5839 \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
5840 QRhiRenderPassDescriptor set.
5841
5842 Two QRhiTextureRenderTarget instances can share the same render pass
5843 descriptor as long as they have the same number and type of attachments.
5844 The associated QRhiTexture or QRhiRenderBuffer instances are not part of
5845 the render pass descriptor so those can differ in the two
5846 QRhiTextureRenderTarget instances.
5847
5848 \note resources, such as QRhiTexture instances, referenced in description()
5849 must already have create() called on them.
5850
5851 \sa create()
5852 */
5853
5854/*!
5855 \fn virtual bool QRhiTextureRenderTarget::create() = 0
5856
5857 Creates the corresponding native graphics resources. If there are already
5858 resources present due to an earlier create() with no corresponding
5859 destroy(), then destroy() is called implicitly first.
5860
5861 \note renderPassDescriptor() must be set before calling create(). To obtain
5862 a QRhiRenderPassDescriptor compatible with the render target, call
5863 newCompatibleRenderPassDescriptor() before create() but after setting all
5864 other parameters, such as description() and flags(). To save resources,
5865 reuse the same QRhiRenderPassDescriptor with multiple
5866 QRhiTextureRenderTarget instances, whenever possible. Sharing the same
5867 render pass descriptor is only possible when the render targets have the
5868 same number and type of attachments (the actual textures can differ) and
5869 the same flags.
5870
5871 \note resources, such as QRhiTexture instances, referenced in description()
5872 must already have create() called on them.
5873
5874 \return \c true when successful, \c false when a graphics operation failed.
5875 Regardless of the return value, calling destroy() is always safe.
5876 */
5877
5878/*!
5879 \fn QRhiTextureRenderTargetDescription QRhiTextureRenderTarget::description() const
5880 \return the render target description.
5881 */
5882
5883/*!
5884 \fn void QRhiTextureRenderTarget::setDescription(const QRhiTextureRenderTargetDescription &desc)
5885 Sets the render target description \a desc.
5886 */
5887
5888/*!
5889 \fn QRhiTextureRenderTarget::Flags QRhiTextureRenderTarget::flags() const
5890 \return the currently set flags.
5891 */
5892
5893/*!
5894 \fn void QRhiTextureRenderTarget::setFlags(Flags f)
5895 Sets the flags to \a f.
5896 */
5897
5898/*!
5899 \class QRhiShaderResourceBindings
5900 \inmodule QtGuiPrivate
5901 \inheaderfile rhi/qrhi.h
5902 \since 6.6
5903 \brief Encapsulates resources for making buffer, texture, sampler resources visible to shaders.
5904
5905 A QRhiShaderResourceBindings is a collection of QRhiShaderResourceBinding
5906 objects, each of which describe a single binding.
5907
5908 Take a fragment shader with the following interface:
5909
5910 \badcode
5911 layout(std140, binding = 0) uniform buf {
5912 mat4 mvp;
5913 int flip;
5914 } ubuf;
5915
5916 layout(binding = 1) uniform sampler2D tex;
5917 \endcode
5918
5919 To make resources visible to the shader, the following
5920 QRhiShaderResourceBindings could be created and then passed to
5921 QRhiGraphicsPipeline::setShaderResourceBindings():
5922
5923 \code
5924 QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings();
5925 srb->setBindings({
5926 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf),
5927 QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler)
5928 });
5929 srb->create();
5930 // ...
5931 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
5932 // ...
5933 ps->setShaderResourceBindings(srb);
5934 ps->create();
5935 // ...
5936 cb->setGraphicsPipeline(ps);
5937 cb->setShaderResources(); // binds srb
5938 \endcode
5939
5940 This assumes that \c ubuf is a QRhiBuffer, \c texture is a QRhiTexture,
5941 while \a sampler is a QRhiSampler. The example also assumes that the
5942 uniform block is present in the vertex shader as well so the same buffer is
5943 made visible to the vertex stage too.
5944
5945 \section3 Advanced usage
5946
5947 Building on the above example, let's assume that a pass now needs to use
5948 the exact same pipeline and shaders with a different texture. Creating a
5949 whole separate QRhiGraphicsPipeline just for this would be an overkill.
5950 This is why QRhiCommandBuffer::setShaderResources() allows specifying a \a
5951 srb argument. As long as the layouts (so the number of bindings and the
5952 binding points) match between two QRhiShaderResourceBindings, they can both
5953 be used with the same pipeline, assuming the pipeline was created with one of
5954 them in the first place. See isLayoutCompatible() for more details.
5955
5956 \code
5957 QRhiShaderResourceBindings *srb2 = rhi->newShaderResourceBindings();
5958 // ...
5959 cb->setGraphicsPipeline(ps);
5960 cb->setShaderResources(srb2); // binds srb2
5961 \endcode
5962
5963 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5964 for details.
5965 */
5966
5967/*!
5968 \typedef QRhiShaderResourceBindingSet
5969 \relates QRhi
5970 \since 6.7
5971
5972 Synonym for QRhiShaderResourceBindings.
5973*/
5974
5975/*!
5976 \internal
5977 */
5978QRhiShaderResourceBindings::QRhiShaderResourceBindings(QRhiImplementation *rhi)
5979 : QRhiResource(rhi)
5980{
5981 m_layoutDesc.reserve(BINDING_PREALLOC * QRhiShaderResourceBinding::LAYOUT_DESC_ENTRIES_PER_BINDING);
5982}
5983
5984/*!
5985 \return the resource type.
5986 */
5987QRhiResource::Type QRhiShaderResourceBindings::resourceType() const
5988{
5989 return ShaderResourceBindings;
5990}
5991
5992/*!
5993 \return \c true if the layout is compatible with \a other. The layout does
5994 not include the actual resource (such as, buffer or texture) and related
5995 parameters (such as, offset or size). It does include the binding point,
5996 pipeline stage, and resource type, however. The number and order of the
5997 bindings must also match in order to be compatible.
5998
5999 When there is a QRhiGraphicsPipeline created with this
6000 QRhiShaderResourceBindings, and the function returns \c true, \a other can
6001 then safely be passed to QRhiCommandBuffer::setShaderResources(), and so
6002 be used with the pipeline in place of this QRhiShaderResourceBindings.
6003
6004 \note This function must only be called after a successful create(), because
6005 it relies on data generated during the baking of the underlying data
6006 structures. This way the function can implement a comparison approach that
6007 is more efficient than iterating through two binding lists and calling
6008 QRhiShaderResourceBinding::isLayoutCompatible() on each pair. This becomes
6009 relevant especially when this function is called at a high frequency.
6010
6011 \sa serializedLayoutDescription()
6012 */
6013bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBindings *other) const
6014{
6015 if (other == this)
6016 return true;
6017
6018 if (!other)
6019 return false;
6020
6021 // This can become a hot code path. Therefore we do not iterate and call
6022 // isLayoutCompatible() on m_bindings, but rather check a pre-calculated
6023 // hash code and then, if the hash matched, do a uint array comparison
6024 // (that's still more cache friendly).
6025
6026 return m_layoutDescHash == other->m_layoutDescHash
6027 && m_layoutDesc == other->m_layoutDesc;
6028}
6029
6030/*!
6031 \fn QVector<quint32> QRhiShaderResourceBindings::serializedLayoutDescription() const
6032
6033 \return a vector of integers containing an opaque blob describing the layout
6034 of the binding list, i.e. the data relevant for
6035 \l{isLayoutCompatible()}{layout compatibility tests}.
6036
6037 Given two objects \c srb1 and \c srb2, if the data returned from this
6038 function is identical, then \c{srb1->isLayoutCompatible(srb2)}, and vice
6039 versa hold true as well.
6040
6041 \note The returned data is meant to be used for storing in memory and
6042 comparisons during the lifetime of the QRhi the object belongs to. It is not
6043 meant for storing on disk, reusing between processes, or using with multiple
6044 QRhi instances with potentially different backends.
6045
6046 \sa isLayoutCompatible()
6047 */
6048
6049void QRhiImplementation::updateLayoutDesc(QRhiShaderResourceBindings *srb)
6050{
6051 srb->m_layoutDescHash = 0;
6052 srb->m_layoutDesc.clear();
6053 auto layoutDescAppender = std::back_inserter(srb->m_layoutDesc);
6054 for (const QRhiShaderResourceBinding &b : std::as_const(srb->m_bindings)) {
6055 const QRhiShaderResourceBinding::Data *d = &b.d;
6056 srb->m_layoutDescHash ^= uint(d->binding) ^ uint(d->stage) ^ uint(d->type)
6057 ^ uint(d->arraySize());
6058 layoutDescAppender = d->serialize(layoutDescAppender);
6059 }
6060}
6061
6062/*!
6063 \fn virtual bool QRhiShaderResourceBindings::create() = 0
6064
6065 Creates the corresponding resource binding set. Depending on the underlying
6066 graphics API, this may involve creating native graphics resources, and
6067 therefore it should not be assumed that this is a cheap operation.
6068
6069 If create() has been called before with no corresponding destroy(), then
6070 destroy() is called implicitly first.
6071
6072 \return \c true when successful, \c false when failed.
6073 Regardless of the return value, calling destroy() is always safe.
6074 */
6075
6076/*!
6077 \fn void QRhiShaderResourceBindings::setBindings(std::initializer_list<QRhiShaderResourceBinding> list)
6078 Sets the \a list of bindings.
6079 */
6080
6081/*!
6082 \fn template<typename InputIterator> void QRhiShaderResourceBindings::setBindings(InputIterator first, InputIterator last)
6083 Sets the list of bindings from the iterators \a first and \a last.
6084 */
6085
6086/*!
6087 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cbeginBindings() const
6088 \return a const iterator pointing to the first item in the binding list.
6089 */
6090
6091/*!
6092 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cendBindings() const
6093 \return a const iterator pointing just after the last item in the binding list.
6094 */
6095
6096/*!
6097 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::bindingAt(qsizetype index) const
6098 \return the binding at the specified \a index.
6099 */
6100
6101/*!
6102 \fn qsizetype QRhiShaderResourceBindings::bindingCount() const
6103 \return the number of bindings.
6104 */
6105
6106/*!
6107 \class QRhiShaderResourceBinding
6108 \inmodule QtGuiPrivate
6109 \inheaderfile rhi/qrhi.h
6110 \since 6.6
6111 \brief Describes the shader resource for a single binding point.
6112
6113 A QRhiShaderResourceBinding cannot be constructed directly. Instead, use the
6114 static functions such as uniformBuffer() or sampledTexture() to get an
6115 instance.
6116
6117 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
6118 for details.
6119 */
6120
6121/*!
6122 \enum QRhiShaderResourceBinding::Type
6123 Specifies type of the shader resource bound to a binding point
6124
6125 \value UniformBuffer Uniform buffer
6126
6127 \value SampledTexture Combined image sampler (a texture and sampler pair).
6128 Even when the shading language associated with the underlying 3D API has no
6129 support for this concept (e.g. D3D and HLSL), this is still supported
6130 because the shader translation layer takes care of the appropriate
6131 translation and remapping of binding points or shader registers.
6132
6133 \value Texture Texture (separate)
6134
6135 \value Sampler Sampler (separate)
6136
6137 \value ImageLoad Image load (with GLSL this maps to doing imageLoad() on a
6138 single level - and either one or all layers - of a texture exposed to the
6139 shader as an image object)
6140
6141 \value ImageStore Image store (with GLSL this maps to doing imageStore() or
6142 imageAtomic*() on a single level - and either one or all layers - of a
6143 texture exposed to the shader as an image object)
6144
6145 \value ImageLoadStore Image load and store
6146
6147 \value BufferLoad Storage buffer load (with GLSL this maps to reading from
6148 a shader storage buffer)
6149
6150 \value BufferStore Storage buffer store (with GLSL this maps to writing to
6151 a shader storage buffer)
6152
6153 \value BufferLoadStore Storage buffer load and store
6154 */
6155
6156/*!
6157 \enum QRhiShaderResourceBinding::StageFlag
6158 Flag values to indicate which stages the shader resource is visible in
6159
6160 \value VertexStage Vertex stage
6161 \value TessellationControlStage Tessellation control (hull shader) stage
6162 \value TessellationEvaluationStage Tessellation evaluation (domain shader) stage
6163 \value FragmentStage Fragment (pixel shader) stage
6164 \value ComputeStage Compute stage
6165 \value GeometryStage Geometry stage
6166 */
6167
6168/*!
6169 \return \c true if the layout is compatible with \a other. The layout does not
6170 include the actual resource (such as, buffer or texture) and related
6171 parameters (such as, offset or size).
6172
6173 For example, \c a and \c b below are not equal, but are compatible layout-wise:
6174
6175 \code
6176 auto a = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buffer);
6177 auto b = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, someOtherBuffer, 256);
6178 \endcode
6179 */
6180bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBinding &other) const
6181{
6182 // everything that goes into a VkDescriptorSetLayoutBinding must match
6183 return d.binding == other.d.binding
6184 && d.stage == other.d.stage
6185 && d.type == other.d.type
6186 && d.arraySize() == other.d.arraySize();
6187}
6188
6189/*!
6190 \return a shader resource binding for the given binding number, pipeline
6191 stages, and buffer specified by \a binding, \a stage, and \a buf.
6192
6193 \note When \a buf is not null, it must have been created with
6194 QRhiBuffer::UniformBuffer.
6195
6196 \note \a buf can be null. It is valid to create a
6197 QRhiShaderResourceBindings with unspecified resources, but such an object
6198 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6199 suitable for creating pipelines. Such a pipeline must then always be used
6200 together with another, layout compatible QRhiShaderResourceBindings with
6201 resources present passed to QRhiCommandBuffer::setShaderResources().
6202
6203 \note If the size of \a buf exceeds the limit reported for
6204 QRhi::MaxUniformBufferRange, unexpected errors may occur.
6205 */
6206QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
6207 int binding, StageFlags stage, QRhiBuffer *buf)
6208{
6209 QRhiShaderResourceBinding b;
6210 b.d.binding = binding;
6211 b.d.stage = stage;
6212 b.d.type = UniformBuffer;
6213 b.d.u.ubuf.buf = buf;
6214 b.d.u.ubuf.offset = 0;
6215 b.d.u.ubuf.maybeSize = 0; // entire buffer
6216 b.d.u.ubuf.hasDynamicOffset = false;
6217 return b;
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. This
6223 overload binds a region only, as specified by \a offset and \a size.
6224
6225 \note It is up to the user to ensure the offset is aligned to
6226 QRhi::ubufAlignment().
6227
6228 \note \a size must be greater than 0.
6229
6230 \note When \a buf is not null, it must have been created with
6231 QRhiBuffer::UniformBuffer.
6232
6233 \note \a buf can be null. It is valid to create a
6234 QRhiShaderResourceBindings with unspecified resources, but such an object
6235 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6236 suitable for creating pipelines. Such a pipeline must then always be used
6237 together with another, layout compatible QRhiShaderResourceBindings with
6238 resources present passed to QRhiCommandBuffer::setShaderResources().
6239
6240 \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
6241 unexpected errors may occur.
6242 */
6243QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
6244 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6245{
6246 Q_ASSERT(size > 0);
6247 QRhiShaderResourceBinding b;
6248 b.d.binding = binding;
6249 b.d.stage = stage;
6250 b.d.type = UniformBuffer;
6251 b.d.u.ubuf.buf = buf;
6252 b.d.u.ubuf.offset = offset;
6253 b.d.u.ubuf.maybeSize = size;
6254 b.d.u.ubuf.hasDynamicOffset = false;
6255 return b;
6256}
6257
6258/*!
6259 \return a shader resource binding for the given binding number, pipeline
6260 stages, and buffer specified by \a binding, \a stage, and \a buf. The
6261 uniform buffer is assumed to have dynamic offset. The dynamic offset can be
6262 specified in QRhiCommandBuffer::setShaderResources(), thus allowing using
6263 varying offset values without creating new bindings for the buffer. The
6264 size of the bound region is specified by \a size. Like with non-dynamic
6265 offsets, \c{offset + size} cannot exceed the size of \a buf.
6266
6267 \note When \a buf is not null, it must have been created with
6268 QRhiBuffer::UniformBuffer.
6269
6270 \note \a buf can be null. It is valid to create a
6271 QRhiShaderResourceBindings with unspecified resources, but such an object
6272 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6273 suitable for creating pipelines. Such a pipeline must then always be used
6274 together with another, layout compatible QRhiShaderResourceBindings with
6275 resources present passed to QRhiCommandBuffer::setShaderResources().
6276
6277 \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
6278 unexpected errors may occur.
6279 */
6280QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(
6281 int binding, StageFlags stage, QRhiBuffer *buf, quint32 size)
6282{
6283 Q_ASSERT(size > 0);
6284 QRhiShaderResourceBinding b;
6285 b.d.binding = binding;
6286 b.d.stage = stage;
6287 b.d.type = UniformBuffer;
6288 b.d.u.ubuf.buf = buf;
6289 b.d.u.ubuf.offset = 0;
6290 b.d.u.ubuf.maybeSize = size;
6291 b.d.u.ubuf.hasDynamicOffset = true;
6292 return b;
6293}
6294
6295/*!
6296 \return a shader resource binding for the given binding number, pipeline
6297 stages, texture, and sampler specified by \a binding, \a stage, \a tex,
6298 \a sampler.
6299
6300 \note This function is equivalent to calling sampledTextures() with a
6301 \c count of 1.
6302
6303 \note \a tex and \a sampler can be null. It is valid to create a
6304 QRhiShaderResourceBindings with unspecified resources, but such an object
6305 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6306 suitable for creating pipelines. Such a pipeline must then always be used
6307 together with another, layout compatible QRhiShaderResourceBindings with
6308 resources present passed to QRhiCommandBuffer::setShaderResources().
6309
6310 \note A shader may not be able to consume more than 16 textures/samplers,
6311 depending on the underlying graphics API. This hard limit must be kept in
6312 mind in renderer design. This does not apply to texture arrays which
6313 consume a single binding point (shader register) and can contain 256-2048
6314 textures, depending on the underlying graphics API. Arrays of textures (see
6315 sampledTextures()) are however no different in this regard than using the
6316 same number of individual textures.
6317
6318 \sa sampledTextures()
6319 */
6320QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
6321 int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
6322{
6323 QRhiShaderResourceBinding b;
6324 b.d.binding = binding;
6325 b.d.stage = stage;
6326 b.d.type = SampledTexture;
6327 b.d.stex.texSamplers.resize(1);
6328 b.d.stex.texSamplers[0] = { tex, sampler };
6329 return b;
6330}
6331
6332/*!
6333 \return a shader resource binding for the given binding number, pipeline
6334 stages, and the array of texture-sampler pairs specified by \a binding, \a
6335 stage, \a count, and \a texSamplers.
6336
6337 \note \a count must be at least 1, and not larger than 16.
6338
6339 \note When \a count is 1, this function is equivalent to sampledTexture().
6340
6341 This function is relevant when arrays of combined image samplers are
6342 involved. For example, in GLSL \c{layout(binding = 5) uniform sampler2D
6343 shadowMaps[8];} declares an array of combined image samplers. The
6344 application is then expected provide a QRhiShaderResourceBinding for
6345 binding point 5, set up by calling this function with \a count set to 8 and
6346 a valid texture and sampler for each element of the array.
6347
6348 \warning All elements of the array must be specified. With the above
6349 example, the only valid, portable approach is calling this function with a
6350 \a count of 8. Additionally, all QRhiTexture and QRhiSampler instances must
6351 be valid, meaning nullptr is not an accepted value. This is due to some of
6352 the underlying APIs, such as, Vulkan, that require a valid image and
6353 sampler object for each element in descriptor arrays. Applications are
6354 advised to provide "dummy" samplers and textures if some array elements are
6355 not relevant (due to not being accessed in the shader).
6356
6357 \note \a texSamplers can be null. It is valid to create a
6358 QRhiShaderResourceBindings with unspecified resources, but such an object
6359 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6360 suitable for creating pipelines. Such a pipeline must then always be used
6361 together with another, layout compatible QRhiShaderResourceBindings with
6362 resources present passed to QRhiCommandBuffer::setShaderResources().
6363
6364 \sa sampledTexture()
6365 */
6366QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTextures(
6367 int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers)
6368{
6369 Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
6370 QRhiShaderResourceBinding b;
6371 b.d.binding = binding;
6372 b.d.stage = stage;
6373 b.d.type = SampledTexture;
6374 b.d.stex.texSamplers.resize(count);
6375 for (int i = 0; i < count; ++i) {
6376 if (texSamplers)
6377 b.d.stex.texSamplers[i] = texSamplers[i];
6378 else
6379 b.d.stex.texSamplers[i] = { nullptr, nullptr };
6380 }
6381 return b;
6382}
6383
6384/*!
6385 \return a shader resource binding for the given binding number, pipeline
6386 stages, and texture specified by \a binding, \a stage, \a tex.
6387
6388 \note This function is equivalent to calling textures() with a
6389 \c count of 1.
6390
6391 \note \a tex can be null. It is valid to create a
6392 QRhiShaderResourceBindings with unspecified resources, but such an object
6393 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6394 suitable for creating pipelines. Such a pipeline must then always be used
6395 together with another, layout compatible QRhiShaderResourceBindings with
6396 resources present passed to QRhiCommandBuffer::setShaderResources().
6397
6398 This creates a binding for a separate texture (image) object, whereas
6399 sampledTexture() is suitable for combined image samplers. In
6400 Vulkan-compatible GLSL code separate textures are declared as \c texture2D
6401 as opposed to \c sampler2D: \c{layout(binding = 1) uniform texture2D tex;}
6402
6403 \note A shader may not be able to consume more than 16 textures, depending
6404 on the underlying graphics API. This hard limit must be kept in mind in
6405 renderer design. This does not apply to texture arrays which consume a
6406 single binding point (shader register) and can contain 256-2048 textures,
6407 depending on the underlying graphics API. Arrays of textures (see
6408 sampledTextures()) are however no different in this regard than using the
6409 same number of individual textures.
6410
6411 \sa textures(), sampler()
6412 */
6413QRhiShaderResourceBinding QRhiShaderResourceBinding::texture(int binding, StageFlags stage, QRhiTexture *tex)
6414{
6415 QRhiShaderResourceBinding b;
6416 b.d.binding = binding;
6417 b.d.stage = stage;
6418 b.d.type = Texture;
6419 b.d.stex.texSamplers.resize(1);
6420 b.d.stex.texSamplers[0] = { tex, nullptr };
6421 return b;
6422}
6423
6424/*!
6425 \return a shader resource binding for the given binding number, pipeline
6426 stages, and the array of (separate) textures specified by \a binding, \a
6427 stage, \a count, and \a tex.
6428
6429 \note \a count must be at least 1, and not larger than 16.
6430
6431 \note When \a count is 1, this function is equivalent to texture().
6432
6433 \warning All elements of the array must be specified.
6434
6435 \note \a tex can be null. It is valid to create a
6436 QRhiShaderResourceBindings with unspecified resources, but such an object
6437 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6438 suitable for creating pipelines. Such a pipeline must then always be used
6439 together with another, layout compatible QRhiShaderResourceBindings with
6440 resources present passed to QRhiCommandBuffer::setShaderResources().
6441
6442 \sa texture(), sampler()
6443 */
6444QRhiShaderResourceBinding QRhiShaderResourceBinding::textures(int binding, StageFlags stage, int count, QRhiTexture **tex)
6445{
6446 Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
6447 QRhiShaderResourceBinding b;
6448 b.d.binding = binding;
6449 b.d.stage = stage;
6450 b.d.type = Texture;
6451 b.d.stex.texSamplers.resize(count);
6452 for (int i = 0; i < count; ++i) {
6453 if (tex)
6454 b.d.stex.texSamplers[i] = { tex[i], nullptr };
6455 else
6456 b.d.stex.texSamplers[i] = { nullptr, nullptr };
6457 }
6458 return b;
6459}
6460
6461/*!
6462 \return a shader resource binding for the given binding number, pipeline
6463 stages, and sampler specified by \a binding, \a stage, \a sampler.
6464
6465 \note \a sampler can be null. It is valid to create a
6466 QRhiShaderResourceBindings with unspecified resources, but such an object
6467 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6468 suitable for creating pipelines. Such a pipeline must then always be used
6469 together with another, layout compatible QRhiShaderResourceBindings with
6470 resources present passed to QRhiCommandBuffer::setShaderResources().
6471
6472 Arrays of separate samplers are not supported.
6473
6474 This creates a binding for a separate sampler object, whereas
6475 sampledTexture() is suitable for combined image samplers. In
6476 Vulkan-compatible GLSL code separate samplers are declared as \c sampler
6477 as opposed to \c sampler2D: \c{layout(binding = 2) uniform sampler samp;}
6478
6479 With both a \c texture2D and \c sampler present, they can be used together
6480 to sample the texture: \c{fragColor = texture(sampler2D(tex, samp),
6481 texcoord);}.
6482
6483 \note A shader may not be able to consume more than 16 samplers, depending
6484 on the underlying graphics API. This hard limit must be kept in mind in
6485 renderer design.
6486
6487 \sa texture()
6488 */
6489QRhiShaderResourceBinding QRhiShaderResourceBinding::sampler(int binding, StageFlags stage, QRhiSampler *sampler)
6490{
6491 QRhiShaderResourceBinding b;
6492 b.d.binding = binding;
6493 b.d.stage = stage;
6494 b.d.type = Sampler;
6495 b.d.stex.texSamplers.resize(1);
6496 b.d.stex.texSamplers[0] = { nullptr, sampler };
6497 return b;
6498}
6499
6500/*!
6501 \return a shader resource binding for a read-only storage image with the
6502 given \a binding number and pipeline \a stage. The image load operations
6503 will have access to all layers of the specified \a level. (so if the texture
6504 is a cubemap, the shader must use imageCube instead of image2D)
6505
6506 \note When \a tex is not null, it must have been created with
6507 QRhiTexture::UsedWithLoadStore.
6508
6509 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6510 with unspecified resources, but such an object cannot be used with
6511 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6512 pipelines. Such a pipeline must then always be used together with another,
6513 layout compatible QRhiShaderResourceBindings with resources present passed
6514 to QRhiCommandBuffer::setShaderResources().
6515
6516 \note Image load/store is only available within the compute and fragment stages.
6517 */
6518QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoad(
6519 int binding, StageFlags stage, QRhiTexture *tex, int level)
6520{
6521 QRhiShaderResourceBinding b;
6522 b.d.binding = binding;
6523 b.d.stage = stage;
6524 b.d.type = ImageLoad;
6525 b.d.u.simage.tex = tex;
6526 b.d.u.simage.level = level;
6527 return b;
6528}
6529
6530/*!
6531 \return a shader resource binding for a write-only storage image with the
6532 given \a binding number and pipeline \a stage. The image store operations
6533 will have access to all layers of the specified \a level. (so if the texture
6534 is a cubemap, the shader must use imageCube instead of image2D)
6535
6536 \note When \a tex is not null, it must have been created with
6537 QRhiTexture::UsedWithLoadStore.
6538
6539 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6540 with unspecified resources, but such an object cannot be used with
6541 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6542 pipelines. Such a pipeline must then always be used together with another,
6543 layout compatible QRhiShaderResourceBindings with resources present passed
6544 to QRhiCommandBuffer::setShaderResources().
6545
6546 \note Image load/store is only available within the compute and fragment stages.
6547 */
6548QRhiShaderResourceBinding QRhiShaderResourceBinding::imageStore(
6549 int binding, StageFlags stage, QRhiTexture *tex, int level)
6550{
6551 QRhiShaderResourceBinding b;
6552 b.d.binding = binding;
6553 b.d.stage = stage;
6554 b.d.type = ImageStore;
6555 b.d.u.simage.tex = tex;
6556 b.d.u.simage.level = level;
6557 return b;
6558}
6559
6560/*!
6561 \return a shader resource binding for a read/write storage image with the
6562 given \a binding number and pipeline \a stage. The image load/store operations
6563 will have access to all layers of the specified \a level. (so if the texture
6564 is a cubemap, the shader must use imageCube instead of image2D)
6565
6566 \note When \a tex is not null, it must have been created with
6567 QRhiTexture::UsedWithLoadStore.
6568
6569 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6570 with unspecified resources, but such an object cannot be used with
6571 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6572 pipelines. Such a pipeline must then always be used together with another,
6573 layout compatible QRhiShaderResourceBindings with resources present passed
6574 to QRhiCommandBuffer::setShaderResources().
6575
6576 \note Image load/store is only available within the compute and fragment stages.
6577 */
6578QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoadStore(
6579 int binding, StageFlags stage, QRhiTexture *tex, int level)
6580{
6581 QRhiShaderResourceBinding b;
6582 b.d.binding = binding;
6583 b.d.stage = stage;
6584 b.d.type = ImageLoadStore;
6585 b.d.u.simage.tex = tex;
6586 b.d.u.simage.level = level;
6587 return b;
6588}
6589
6590/*!
6591 \return a shader resource binding for a read-only storage buffer with the
6592 given \a binding number and pipeline \a stage.
6593
6594 \note When \a buf is not null, must have been created with
6595 QRhiBuffer::StorageBuffer.
6596
6597 \note \a buf can be null. It is valid to create a
6598 QRhiShaderResourceBindings with unspecified resources, but such an object
6599 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6600 suitable for creating pipelines. Such a pipeline must then always be used
6601 together with another, layout compatible QRhiShaderResourceBindings with
6602 resources present passed to QRhiCommandBuffer::setShaderResources().
6603
6604 \note Buffer load/store is only guaranteed to be available within a compute
6605 pipeline. While some backends may support using these resources in a
6606 graphics pipeline as well, this is not universally supported, and even when
6607 it is, unexpected problems may arise when it comes to barriers and
6608 synchronization. Therefore, avoid using such resources with shaders other
6609 than compute.
6610 */
6611QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6612 int binding, StageFlags stage, QRhiBuffer *buf)
6613{
6614 QRhiShaderResourceBinding b;
6615 b.d.binding = binding;
6616 b.d.stage = stage;
6617 b.d.type = BufferLoad;
6618 b.d.u.sbuf.buf = buf;
6619 b.d.u.sbuf.offset = 0;
6620 b.d.u.sbuf.maybeSize = 0; // entire buffer
6621 return b;
6622}
6623
6624/*!
6625 \return a shader resource binding for a read-only storage buffer with the
6626 given \a binding number and pipeline \a stage. This overload binds a region
6627 only, as specified by \a offset and \a size.
6628
6629 \note When \a buf is not null, must have been created with
6630 QRhiBuffer::StorageBuffer.
6631
6632 \note \a buf can be null. It is valid to create a
6633 QRhiShaderResourceBindings with unspecified resources, but such an object
6634 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6635 suitable for creating pipelines. Such a pipeline must then always be used
6636 together with another, layout compatible QRhiShaderResourceBindings with
6637 resources present passed to QRhiCommandBuffer::setShaderResources().
6638
6639 \note Buffer load/store is only guaranteed to be available within a compute
6640 pipeline. While some backends may support using these resources in a
6641 graphics pipeline as well, this is not universally supported, and even when
6642 it is, unexpected problems may arise when it comes to barriers and
6643 synchronization. Therefore, avoid using such resources with shaders other
6644 than compute.
6645 */
6646QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6647 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6648{
6649 Q_ASSERT(size > 0);
6650 QRhiShaderResourceBinding b;
6651 b.d.binding = binding;
6652 b.d.stage = stage;
6653 b.d.type = BufferLoad;
6654 b.d.u.sbuf.buf = buf;
6655 b.d.u.sbuf.offset = offset;
6656 b.d.u.sbuf.maybeSize = size;
6657 return b;
6658}
6659
6660/*!
6661 \return a shader resource binding for a write-only storage buffer with the
6662 given \a binding number and pipeline \a stage.
6663
6664 \note When \a buf is not null, must have been created with
6665 QRhiBuffer::StorageBuffer.
6666
6667 \note \a buf can be null. It is valid to create a
6668 QRhiShaderResourceBindings with unspecified resources, but such an object
6669 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6670 suitable for creating pipelines. Such a pipeline must then always be used
6671 together with another, layout compatible QRhiShaderResourceBindings with
6672 resources present passed to QRhiCommandBuffer::setShaderResources().
6673
6674 \note Buffer load/store is only guaranteed to be available within a compute
6675 pipeline. While some backends may support using these resources in a
6676 graphics pipeline as well, this is not universally supported, and even when
6677 it is, unexpected problems may arise when it comes to barriers and
6678 synchronization. Therefore, avoid using such resources with shaders other
6679 than compute.
6680 */
6681QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6682 int binding, StageFlags stage, QRhiBuffer *buf)
6683{
6684 QRhiShaderResourceBinding b;
6685 b.d.binding = binding;
6686 b.d.stage = stage;
6687 b.d.type = BufferStore;
6688 b.d.u.sbuf.buf = buf;
6689 b.d.u.sbuf.offset = 0;
6690 b.d.u.sbuf.maybeSize = 0; // entire buffer
6691 return b;
6692}
6693
6694/*!
6695 \return a shader resource binding for a write-only storage buffer with the
6696 given \a binding number and pipeline \a stage. This overload binds a region
6697 only, as specified by \a offset and \a size.
6698
6699 \note When \a buf is not null, must have been created with
6700 QRhiBuffer::StorageBuffer.
6701
6702 \note \a buf can be null. It is valid to create a
6703 QRhiShaderResourceBindings with unspecified resources, but such an object
6704 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6705 suitable for creating pipelines. Such a pipeline must then always be used
6706 together with another, layout compatible QRhiShaderResourceBindings with
6707 resources present passed to QRhiCommandBuffer::setShaderResources().
6708
6709 \note Buffer load/store is only guaranteed to be available within a compute
6710 pipeline. While some backends may support using these resources in a
6711 graphics pipeline as well, this is not universally supported, and even when
6712 it is, unexpected problems may arise when it comes to barriers and
6713 synchronization. Therefore, avoid using such resources with shaders other
6714 than compute.
6715 */
6716QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6717 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6718{
6719 Q_ASSERT(size > 0);
6720 QRhiShaderResourceBinding b;
6721 b.d.binding = binding;
6722 b.d.stage = stage;
6723 b.d.type = BufferStore;
6724 b.d.u.sbuf.buf = buf;
6725 b.d.u.sbuf.offset = offset;
6726 b.d.u.sbuf.maybeSize = size;
6727 return b;
6728}
6729
6730/*!
6731 \return a shader resource binding for a read-write storage buffer with the
6732 given \a binding number and pipeline \a stage.
6733
6734 \note When \a buf is not null, must have been created with
6735 QRhiBuffer::StorageBuffer.
6736
6737 \note \a buf can be null. It is valid to create a
6738 QRhiShaderResourceBindings with unspecified resources, but such an object
6739 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6740 suitable for creating pipelines. Such a pipeline must then always be used
6741 together with another, layout compatible QRhiShaderResourceBindings with
6742 resources present passed to QRhiCommandBuffer::setShaderResources().
6743
6744 \note Buffer load/store is only guaranteed to be available within a compute
6745 pipeline. While some backends may support using these resources in a
6746 graphics pipeline as well, this is not universally supported, and even when
6747 it is, unexpected problems may arise when it comes to barriers and
6748 synchronization. Therefore, avoid using such resources with shaders other
6749 than compute.
6750 */
6751QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6752 int binding, StageFlags stage, QRhiBuffer *buf)
6753{
6754 QRhiShaderResourceBinding b;
6755 b.d.binding = binding;
6756 b.d.stage = stage;
6757 b.d.type = BufferLoadStore;
6758 b.d.u.sbuf.buf = buf;
6759 b.d.u.sbuf.offset = 0;
6760 b.d.u.sbuf.maybeSize = 0; // entire buffer
6761 return b;
6762}
6763
6764/*!
6765 \return a shader resource binding for a read-write storage buffer with the
6766 given \a binding number and pipeline \a stage. This overload binds a region
6767 only, as specified by \a offset and \a size.
6768
6769 \note When \a buf is not null, must have been created with
6770 QRhiBuffer::StorageBuffer.
6771
6772 \note \a buf can be null. It is valid to create a
6773 QRhiShaderResourceBindings with unspecified resources, but such an object
6774 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6775 suitable for creating pipelines. Such a pipeline must then always be used
6776 together with another, layout compatible QRhiShaderResourceBindings with
6777 resources present passed to QRhiCommandBuffer::setShaderResources().
6778
6779 \note Buffer load/store is only guaranteed to be available within a compute
6780 pipeline. While some backends may support using these resources in a
6781 graphics pipeline as well, this is not universally supported, and even when
6782 it is, unexpected problems may arise when it comes to barriers and
6783 synchronization. Therefore, avoid using such resources with shaders other
6784 than compute.
6785 */
6786QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6787 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6788{
6789 Q_ASSERT(size > 0);
6790 QRhiShaderResourceBinding b;
6791 b.d.binding = binding;
6792 b.d.stage = stage;
6793 b.d.type = BufferLoadStore;
6794 b.d.u.sbuf.buf = buf;
6795 b.d.u.sbuf.offset = offset;
6796 b.d.u.sbuf.maybeSize = size;
6797 return b;
6798}
6799
6800/*!
6801 \return \c true if the contents of the two QRhiShaderResourceBinding
6802 objects \a a and \a b are equal. This includes the resources (buffer,
6803 texture) and related parameters (offset, size) as well. To only compare
6804 layouts (binding point, pipeline stage, resource type), use
6805 \l{QRhiShaderResourceBinding::isLayoutCompatible()}{isLayoutCompatible()}
6806 instead.
6807
6808 \relates QRhiShaderResourceBinding
6809 */
6810bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6811{
6812 const QRhiShaderResourceBinding::Data *da = QRhiImplementation::shaderResourceBindingData(a);
6813 const QRhiShaderResourceBinding::Data *db = QRhiImplementation::shaderResourceBindingData(b);
6814
6815 if (da == db)
6816 return true;
6817
6818
6819 if (da->binding != db->binding
6820 || da->stage != db->stage
6821 || da->type != db->type)
6822 {
6823 return false;
6824 }
6825
6826 switch (da->type) {
6827 case QRhiShaderResourceBinding::UniformBuffer:
6828 if (da->u.ubuf.buf != db->u.ubuf.buf
6829 || da->u.ubuf.offset != db->u.ubuf.offset
6830 || da->u.ubuf.maybeSize != db->u.ubuf.maybeSize)
6831 {
6832 return false;
6833 }
6834 break;
6835 case QRhiShaderResourceBinding::SampledTexture:
6836 if (da->stex.count() != db->stex.count())
6837 return false;
6838 for (int i = 0; i < da->stex.count(); ++i) {
6839 if (da->stex.texSamplers[i].tex != db->stex.texSamplers[i].tex
6840 || da->stex.texSamplers[i].sampler != db->stex.texSamplers[i].sampler)
6841 {
6842 return false;
6843 }
6844 }
6845 break;
6846 case QRhiShaderResourceBinding::Texture:
6847 if (da->stex.count() != db->stex.count())
6848 return false;
6849 for (int i = 0; i < da->stex.count(); ++i) {
6850 if (da->stex.texSamplers[i].tex != db->stex.texSamplers[i].tex)
6851 return false;
6852 }
6853 break;
6854 case QRhiShaderResourceBinding::Sampler:
6855 if (da->stex.texSamplers[0].sampler != db->stex.texSamplers[0].sampler)
6856 return false;
6857 break;
6858 case QRhiShaderResourceBinding::ImageLoad:
6859 case QRhiShaderResourceBinding::ImageStore:
6860 case QRhiShaderResourceBinding::ImageLoadStore:
6861 if (da->u.simage.tex != db->u.simage.tex
6862 || da->u.simage.level != db->u.simage.level)
6863 {
6864 return false;
6865 }
6866 break;
6867 case QRhiShaderResourceBinding::BufferLoad:
6868 case QRhiShaderResourceBinding::BufferStore:
6869 case QRhiShaderResourceBinding::BufferLoadStore:
6870 if (da->u.sbuf.buf != db->u.sbuf.buf
6871 || da->u.sbuf.offset != db->u.sbuf.offset
6872 || da->u.sbuf.maybeSize != db->u.sbuf.maybeSize)
6873 {
6874 return false;
6875 }
6876 break;
6877 default:
6878 Q_UNREACHABLE_RETURN(false);
6879 }
6880
6881 return true;
6882}
6883
6884/*!
6885 \return \c false if all the bindings in the two QRhiShaderResourceBinding
6886 objects \a a and \a b are equal; otherwise returns \c true.
6887
6888 \relates QRhiShaderResourceBinding
6889 */
6890bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6891{
6892 return !(a == b);
6893}
6894
6895/*!
6896 \fn size_t qHash(const QRhiShaderResourceBinding &key, size_t seed)
6897 \qhashold{QRhiShaderResourceBinding}
6898 */
6899size_t qHash(const QRhiShaderResourceBinding &b, size_t seed) noexcept
6900{
6901 const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6902 QtPrivate::QHashCombineWithSeed hash(seed);
6903 seed = hash(seed, d->binding);
6904 seed = hash(seed, d->stage);
6905 seed = hash(seed, d->type);
6906 switch (d->type) {
6907 case QRhiShaderResourceBinding::UniformBuffer:
6908 seed = hash(seed, reinterpret_cast<quintptr>(d->u.ubuf.buf));
6909 break;
6910 case QRhiShaderResourceBinding::SampledTexture:
6911 seed = hash(seed, reinterpret_cast<quintptr>(d->stex.texSamplers[0].tex));
6912 seed = hash(seed, reinterpret_cast<quintptr>(d->stex.texSamplers[0].sampler));
6913 break;
6914 case QRhiShaderResourceBinding::Texture:
6915 seed = hash(seed, reinterpret_cast<quintptr>(d->stex.texSamplers[0].tex));
6916 break;
6917 case QRhiShaderResourceBinding::Sampler:
6918 seed = hash(seed, reinterpret_cast<quintptr>(d->stex.texSamplers[0].sampler));
6919 break;
6920 case QRhiShaderResourceBinding::ImageLoad:
6921 case QRhiShaderResourceBinding::ImageStore:
6922 case QRhiShaderResourceBinding::ImageLoadStore:
6923 seed = hash(seed, reinterpret_cast<quintptr>(d->u.simage.tex));
6924 break;
6925 case QRhiShaderResourceBinding::BufferLoad:
6926 case QRhiShaderResourceBinding::BufferStore:
6927 case QRhiShaderResourceBinding::BufferLoadStore:
6928 seed = hash(seed, reinterpret_cast<quintptr>(d->u.sbuf.buf));
6929 break;
6930 }
6931 return seed;
6932}
6933
6934#ifndef QT_NO_DEBUG_STREAM
6935QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
6936{
6937 QDebugStateSaver saver(dbg);
6938 const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6939 dbg.nospace() << "QRhiShaderResourceBinding("
6940 << "binding=" << d->binding
6941 << " stage=" << d->stage
6942 << " type=" << d->type;
6943 switch (d->type) {
6944 case QRhiShaderResourceBinding::UniformBuffer:
6945 dbg.nospace() << " UniformBuffer("
6946 << "buffer=" << d->u.ubuf.buf
6947 << " offset=" << d->u.ubuf.offset
6948 << " maybeSize=" << d->u.ubuf.maybeSize
6949 << ')';
6950 break;
6951 case QRhiShaderResourceBinding::SampledTexture:
6952 dbg.nospace() << " SampledTextures("
6953 << "count=" << d->stex.count();
6954 for (int i = 0; i < d->stex.count(); ++i) {
6955 dbg.nospace() << " texture=" << d->stex.texSamplers[i].tex
6956 << " sampler=" << d->stex.texSamplers[i].sampler;
6957 }
6958 dbg.nospace() << ')';
6959 break;
6960 case QRhiShaderResourceBinding::Texture:
6961 dbg.nospace() << " Textures("
6962 << "count=" << d->stex.count();
6963 for (int i = 0; i < d->stex.count(); ++i)
6964 dbg.nospace() << " texture=" << d->stex.texSamplers[i].tex;
6965 dbg.nospace() << ')';
6966 break;
6967 case QRhiShaderResourceBinding::Sampler:
6968 dbg.nospace() << " Sampler("
6969 << " sampler=" << d->stex.texSamplers[0].sampler
6970 << ')';
6971 break;
6972 case QRhiShaderResourceBinding::ImageLoad:
6973 dbg.nospace() << " ImageLoad("
6974 << "texture=" << d->u.simage.tex
6975 << " level=" << d->u.simage.level
6976 << ')';
6977 break;
6978 case QRhiShaderResourceBinding::ImageStore:
6979 dbg.nospace() << " ImageStore("
6980 << "texture=" << d->u.simage.tex
6981 << " level=" << d->u.simage.level
6982 << ')';
6983 break;
6984 case QRhiShaderResourceBinding::ImageLoadStore:
6985 dbg.nospace() << " ImageLoadStore("
6986 << "texture=" << d->u.simage.tex
6987 << " level=" << d->u.simage.level
6988 << ')';
6989 break;
6990 case QRhiShaderResourceBinding::BufferLoad:
6991 dbg.nospace() << " BufferLoad("
6992 << "buffer=" << d->u.sbuf.buf
6993 << " offset=" << d->u.sbuf.offset
6994 << " maybeSize=" << d->u.sbuf.maybeSize
6995 << ')';
6996 break;
6997 case QRhiShaderResourceBinding::BufferStore:
6998 dbg.nospace() << " BufferStore("
6999 << "buffer=" << d->u.sbuf.buf
7000 << " offset=" << d->u.sbuf.offset
7001 << " maybeSize=" << d->u.sbuf.maybeSize
7002 << ')';
7003 break;
7004 case QRhiShaderResourceBinding::BufferLoadStore:
7005 dbg.nospace() << " BufferLoadStore("
7006 << "buffer=" << d->u.sbuf.buf
7007 << " offset=" << d->u.sbuf.offset
7008 << " maybeSize=" << d->u.sbuf.maybeSize
7009 << ')';
7010 break;
7011 default:
7012 dbg.nospace() << " UNKNOWN()";
7013 break;
7014 }
7015 dbg.nospace() << ')';
7016 return dbg;
7017}
7018#endif
7019
7020#ifndef QT_NO_DEBUG_STREAM
7021QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
7022{
7023 QDebugStateSaver saver(dbg);
7024 dbg.nospace() << "QRhiShaderResourceBindings("
7025 << srb.m_bindings
7026 << ')';
7027 return dbg;
7028}
7029#endif
7030
7031/*!
7032 \class QRhiGraphicsPipeline
7033 \inmodule QtGuiPrivate
7034 \inheaderfile rhi/qrhi.h
7035 \since 6.6
7036 \brief Graphics pipeline state resource.
7037
7038 Represents a graphics pipeline. What exactly this map to in the underlying
7039 native graphics API, varies. Where there is a concept of pipeline objects,
7040 for example with Vulkan, the QRhi backend will create such an object upon
7041 calling create(). Elsewhere, for example with OpenGL, the
7042 QRhiGraphicsPipeline may merely collect the various state, and create()'s
7043 main task is to set up the corresponding shader program, but deferring
7044 looking at any of the requested state to a later point.
7045
7046 As with all QRhiResource subclasses, the two-phased initialization pattern
7047 applies: setting any values via the setters, for example setDepthTest(), is
7048 only effective after calling create(). Avoid changing any values once the
7049 QRhiGraphicsPipeline has been initialized via create(). To change some
7050 state, set the new value and call create() again. However, that will
7051 effectively release all underlying native resources and create new ones. As
7052 a result, it may be a heavy, expensive operation. Rather, prefer creating
7053 multiple pipelines with the different states, and
7054 \l{QRhiCommandBuffer::setGraphicsPipeline()}{switch between them} when
7055 recording the render pass.
7056
7057 \note Setting the shader stages is mandatory. There must be at least one
7058 stage, and there must be a vertex stage.
7059
7060 \note Setting the shader resource bindings is mandatory. The referenced
7061 QRhiShaderResourceBindings must already have create() called on it by the
7062 time create() is called. Associating with a QRhiShaderResourceBindings that
7063 has no bindings is also valid, as long as no shader in any stage expects any
7064 resources. Using a QRhiShaderResourceBindings object that does not specify
7065 any actual resources (i.e., the buffers, textures, etc. for the binding
7066 points are set to \nullptr) is valid as well, as long as a
7067 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
7068 QRhiShaderResourceBindings, that specifies resources for all the bindings,
7069 is going to be set via
7070 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} when
7071 recording the render pass.
7072
7073 \note Setting the render pass descriptor is mandatory. To obtain a
7074 QRhiRenderPassDescriptor that can be passed to setRenderPassDescriptor(),
7075 use either QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() or
7076 QRhiSwapChain::newCompatibleRenderPassDescriptor().
7077
7078 \note Setting the vertex input layout is mandatory.
7079
7080 \note sampleCount() defaults to 1 and must match the sample count of the
7081 render target's color and depth stencil attachments.
7082
7083 \note The depth test, depth write, and stencil test are disabled by
7084 default. The face culling mode defaults to no culling.
7085
7086 \note stencilReadMask() and stencilWriteMask() apply to both faces. They
7087 both default to 0xFF.
7088
7089 \section2 Example usage
7090
7091 All settings of a graphics pipeline have defaults which might be suitable
7092 to many applications. Therefore a minimal example of creating a graphics
7093 pipeline could be the following. This assumes that the vertex shader takes
7094 a single \c{vec3 position} input at the input location 0. With the
7095 QRhiShaderResourceBindings and QRhiRenderPassDescriptor objects, plus the
7096 QShader collections for the vertex and fragment stages, a pipeline could be
7097 created like this:
7098
7099 \code
7100 QRhiShaderResourceBindings *srb;
7101 QRhiRenderPassDescriptor *rpDesc;
7102 QShader vs, fs;
7103 // ...
7104
7105 QRhiVertexInputLayout inputLayout;
7106 inputLayout.setBindings({ { 3 * sizeof(float) } });
7107 inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float3, 0 } });
7108
7109 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
7110 ps->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
7111 ps->setVertexInputLayout(inputLayout);
7112 ps->setShaderResourceBindings(srb);
7113 ps->setRenderPassDescriptor(rpDesc);
7114 if (!ps->create()) { error(); }
7115 \endcode
7116
7117 The above code creates a pipeline object that uses the defaults for many
7118 settings and states. For example, it will use a \l Triangles topology, no
7119 backface culling, blending is disabled but color write is enabled for all
7120 four channels, depth test/write are disabled, stencil operations are
7121 disabled.
7122
7123 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7124 for details.
7125
7126 \sa QRhiCommandBuffer, QRhi
7127 */
7128
7129/*!
7130 \enum QRhiGraphicsPipeline::Flag
7131
7132 Flag values for describing the dynamic state of the pipeline, and other
7133 options. The viewport is always dynamic.
7134
7135 \value UsesBlendConstants Indicates that a blend color constant will be set
7136 via QRhiCommandBuffer::setBlendConstants()
7137
7138 \value UsesStencilRef Indicates that a stencil reference value will be set
7139 via QRhiCommandBuffer::setStencilRef()
7140
7141 \value UsesScissor Indicates that a scissor rectangle will be set via
7142 QRhiCommandBuffer::setScissor()
7143
7144 \value CompileShadersWithDebugInfo Requests compiling shaders with debug
7145 information enabled. This is relevant only when runtime shader compilation
7146 from source code is involved, and only when the underlying infrastructure
7147 supports this. With concrete examples, this is not relevant with Vulkan and
7148 SPIR-V, because the GLSL-to-SPIR-V compilation does not happen at run
7149 time. On the other hand, consider Direct3D and HLSL, where there are
7150 multiple options: when the QShader packages ship with pre-compiled bytecode
7151 (\c DXBC), debug information is to be requested through the tool that
7152 generates the \c{.qsb} file, similarly to the case of Vulkan and
7153 SPIR-V. However, when having HLSL source code in the pre- or
7154 runtime-generated QShader packages, the first phase of compilation (HLSL
7155 source to intermediate format) happens at run time too, with this flag taken
7156 into account. Debug information is relevant in particular with tools like
7157 RenderDoc since it allows seeing the original source code when investigating
7158 the pipeline and when performing vertex or fragment shader debugging.
7159
7160 \value UsesShadingRate Indicates that a per-draw (per-pipeline) shading rate
7161 value will be set via QRhiCommandBuffer::setShadingRate(). Not specifying
7162 this flag and still calling setShadingRate() may lead to varying, unexpected
7163 results depending on the underlying graphics API.
7164
7165 \value [since 6.12] UsesIndirectDraws Indicates that this pipeline will be used with
7166 indirect draw calls (QRhiCommandBuffer::drawIndirect() or
7167 QRhiCommandBuffer::drawIndexedIndirect()). Setting this flag allows the
7168 Metal backend to use Indirect Command Buffers (ICB) for GPU-driven
7169 rendering, which significantly reduces CPU overhead for large draw counts.
7170 Not setting this flag when using indirect draws is still functional but may
7171 result in less optimal performance on Metal: QRhi::DrawIndirectMulti reports
7172 what the device can do, without knowing about individual pipelines, so a
7173 pipeline without this flag falls back to CPU-side looping even when that
7174 feature is reported as supported. The exception is
7175 QRhiCommandBuffer::drawIndirectCount() and
7176 QRhiCommandBuffer::drawIndexedIndirectCount(), for which the flag is
7177 mandatory on Metal because there is no non-ICB implementation of those. This
7178 flag has no effect on other backends.
7179 */
7180
7181/*!
7182 \enum QRhiGraphicsPipeline::Topology
7183 Specifies the primitive topology
7184
7185 \value Triangles (default)
7186 \value TriangleStrip
7187 \value TriangleFan (only available if QRhi::TriangleFanTopology is supported)
7188 \value Lines
7189 \value LineStrip
7190 \value Points
7191
7192 \value Patches (only available if QRhi::Tessellation is supported, and
7193 requires the tessellation stages to be present in the pipeline)
7194 */
7195
7196/*!
7197 \enum QRhiGraphicsPipeline::CullMode
7198 Specifies the culling mode
7199
7200 \value None No culling (default)
7201 \value Front Cull front faces
7202 \value Back Cull back faces
7203 */
7204
7205/*!
7206 \enum QRhiGraphicsPipeline::FrontFace
7207 Specifies the front face winding order
7208
7209 \value CCW Counter clockwise (default)
7210 \value CW Clockwise
7211 */
7212
7213/*!
7214 \enum QRhiGraphicsPipeline::ColorMaskComponent
7215 Flag values for specifying the color write mask
7216
7217 \value R
7218 \value G
7219 \value B
7220 \value A
7221 */
7222
7223/*!
7224 \enum QRhiGraphicsPipeline::BlendFactor
7225 Specifies the blend factor
7226
7227 \value Zero
7228 \value One
7229 \value SrcColor
7230 \value OneMinusSrcColor
7231 \value DstColor
7232 \value OneMinusDstColor
7233 \value SrcAlpha
7234 \value OneMinusSrcAlpha
7235 \value DstAlpha
7236 \value OneMinusDstAlpha
7237 \value ConstantColor
7238 \value OneMinusConstantColor
7239 \value ConstantAlpha
7240 \value OneMinusConstantAlpha
7241 \value SrcAlphaSaturate
7242 \value Src1Color
7243 \value OneMinusSrc1Color
7244 \value Src1Alpha
7245 \value OneMinusSrc1Alpha
7246 */
7247
7248/*!
7249 \enum QRhiGraphicsPipeline::BlendOp
7250 Specifies the blend operation
7251
7252 \value Add
7253 \value Subtract
7254 \value ReverseSubtract
7255 \value Min
7256 \value Max
7257 */
7258
7259/*!
7260 \enum QRhiGraphicsPipeline::CompareOp
7261 Specifies the depth or stencil comparison function
7262
7263 \value Never
7264 \value Less (default for depth)
7265 \value Equal
7266 \value LessOrEqual
7267 \value Greater
7268 \value NotEqual
7269 \value GreaterOrEqual
7270 \value Always (default for stencil)
7271 */
7272
7273/*!
7274 \enum QRhiGraphicsPipeline::StencilOp
7275 Specifies the stencil operation
7276
7277 \value StencilZero
7278 \value Keep (default)
7279 \value Replace
7280 \value IncrementAndClamp
7281 \value DecrementAndClamp
7282 \value Invert
7283 \value IncrementAndWrap
7284 \value DecrementAndWrap
7285 */
7286
7287/*!
7288 \enum QRhiGraphicsPipeline::PolygonMode
7289 \brief Specifies the polygon rasterization mode
7290
7291 Polygon Mode (Triangle Fill Mode in Metal, Fill Mode in D3D) specifies
7292 the fill mode used when rasterizing polygons. Polygons may be drawn as
7293 solids (Fill), or as a wire mesh (Line).
7294
7295 Support for non-fill polygon modes is optional and is indicated by the
7296 QRhi::NonFillPolygonMode feature. With OpenGL ES and some Vulkan
7297 implementations the feature will likely be reported as unsupported, which
7298 then means values other than Fill cannot be used.
7299
7300 \value Fill The interior of the polygon is filled (default)
7301 \value Line Boundary edges of the polygon are drawn as line segments.
7302 */
7303
7304/*!
7305 \struct QRhiGraphicsPipeline::TargetBlend
7306 \inmodule QtGuiPrivate
7307 \inheaderfile rhi/qrhi.h
7308 \since 6.6
7309 \brief Describes the blend state for one color attachment.
7310
7311 Defaults to color write enabled, blending disabled. The blend values are
7312 set up for pre-multiplied alpha (One, OneMinusSrcAlpha, One,
7313 OneMinusSrcAlpha) by default. This means that to get the alpha blending
7314 mode Qt Quick uses, it is enough to set the \c enable flag to true while
7315 leaving other values at their defaults.
7316
7317 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7318 for details.
7319 */
7320
7321/*!
7322 \variable QRhiGraphicsPipeline::TargetBlend::colorWrite
7323 */
7324
7325/*!
7326 \variable QRhiGraphicsPipeline::TargetBlend::enable
7327 */
7328
7329/*!
7330 \variable QRhiGraphicsPipeline::TargetBlend::srcColor
7331 */
7332
7333/*!
7334 \variable QRhiGraphicsPipeline::TargetBlend::dstColor
7335 */
7336
7337/*!
7338 \variable QRhiGraphicsPipeline::TargetBlend::opColor
7339 */
7340
7341/*!
7342 \variable QRhiGraphicsPipeline::TargetBlend::srcAlpha
7343 */
7344
7345/*!
7346 \variable QRhiGraphicsPipeline::TargetBlend::dstAlpha
7347 */
7348
7349/*!
7350 \variable QRhiGraphicsPipeline::TargetBlend::opAlpha
7351 */
7352
7353/*!
7354 \struct QRhiGraphicsPipeline::StencilOpState
7355 \inmodule QtGuiPrivate
7356 \inheaderfile rhi/qrhi.h
7357 \since 6.6
7358 \brief Describes the stencil operation state.
7359
7360 The default-constructed StencilOpState has the following set:
7361 \list
7362 \li failOp - \l Keep
7363 \li depthFailOp - \l Keep
7364 \li passOp - \l Keep
7365 \li compareOp \l Always
7366 \endlist
7367
7368 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7369 for details.
7370 */
7371
7372/*!
7373 \variable QRhiGraphicsPipeline::StencilOpState::failOp
7374 */
7375
7376/*!
7377 \variable QRhiGraphicsPipeline::StencilOpState::depthFailOp
7378 */
7379
7380/*!
7381 \variable QRhiGraphicsPipeline::StencilOpState::passOp
7382 */
7383
7384/*!
7385 \variable QRhiGraphicsPipeline::StencilOpState::compareOp
7386 */
7387
7388/*!
7389 \internal
7390 */
7391QRhiGraphicsPipeline::QRhiGraphicsPipeline(QRhiImplementation *rhi)
7392 : QRhiResource(rhi)
7393{
7394}
7395
7396/*!
7397 \return the resource type.
7398 */
7399QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
7400{
7401 return GraphicsPipeline;
7402}
7403
7404/*!
7405 \fn virtual bool QRhiGraphicsPipeline::create() = 0
7406
7407 Creates the corresponding native graphics resources. If there are already
7408 resources present due to an earlier create() with no corresponding
7409 destroy(), then destroy() is called implicitly first.
7410
7411 \return \c true when successful, \c false when a graphics operation failed.
7412 Regardless of the return value, calling destroy() is always safe.
7413
7414 \note This may be, depending on the underlying graphics API, an expensive
7415 operation, especially when shaders get compiled/optimized from source or
7416 from an intermediate bytecode format to the GPU's own instruction set.
7417 Where applicable, the QRhi backend automatically sets up the relevant
7418 non-persistent facilities to accelerate this, for example the Vulkan
7419 backend automatically creates a \c VkPipelineCache to improve data reuse
7420 during the lifetime of the application.
7421
7422 \note Drivers may also employ various persistent (disk-based) caching
7423 strategies for shader and pipeline data, which is hidden to and is outside
7424 of Qt's control. In some cases, depending on the graphics API and the QRhi
7425 backend, there are facilities within QRhi for manually managing such a
7426 cache, allowing the retrieval of a serializable blob that can then be
7427 reloaded in the future runs of the application to ensure faster pipeline
7428 creation times. See QRhi::pipelineCacheData() and
7429 QRhi::setPipelineCacheData() for details. Note also that when working with
7430 a QRhi instance managed by a higher level Qt framework, such as Qt Quick,
7431 it is possible that such disk-based caching is taken care of automatically,
7432 for example QQuickWindow uses a disk-based pipeline cache by default (which
7433 comes in addition to any driver-level caching).
7434 */
7435
7436/*!
7437 \fn QRhiGraphicsPipeline::Flags QRhiGraphicsPipeline::flags() const
7438 \return the currently set flags.
7439 */
7440
7441/*!
7442 \fn void QRhiGraphicsPipeline::setFlags(Flags f)
7443 Sets the flags \a f.
7444 */
7445
7446/*!
7447 \fn QRhiGraphicsPipeline::Topology QRhiGraphicsPipeline::topology() const
7448 \return the currently set primitive topology.
7449 */
7450
7451/*!
7452 \fn void QRhiGraphicsPipeline::setTopology(Topology t)
7453 Sets the primitive topology \a t.
7454 */
7455
7456/*!
7457 \fn QRhiGraphicsPipeline::CullMode QRhiGraphicsPipeline::cullMode() const
7458 \return the currently set face culling mode.
7459 */
7460
7461/*!
7462 \fn void QRhiGraphicsPipeline::setCullMode(CullMode mode)
7463 Sets the specified face culling \a mode.
7464 */
7465
7466/*!
7467 \fn QRhiGraphicsPipeline::FrontFace QRhiGraphicsPipeline::frontFace() const
7468 \return the currently set front face mode.
7469 */
7470
7471/*!
7472 \fn void QRhiGraphicsPipeline::setFrontFace(FrontFace f)
7473 Sets the front face mode \a f.
7474 */
7475
7476/*!
7477 \fn void QRhiGraphicsPipeline::setTargetBlends(std::initializer_list<TargetBlend> list)
7478
7479 Sets the \a list of render target blend settings. This is a list because
7480 when multiple render targets are used (i.e., a QRhiTextureRenderTarget with
7481 more than one QRhiColorAttachment), there needs to be a TargetBlend
7482 structure per render target (color attachment).
7483
7484 By default there is one default-constructed TargetBlend set.
7485
7486 \sa QRhi::MaxColorAttachments
7487 */
7488
7489/*!
7490 \fn template<typename InputIterator> void QRhiGraphicsPipeline::setTargetBlends(InputIterator first, InputIterator last)
7491 Sets the list of render target blend settings from the iterators \a first and \a last.
7492 */
7493
7494/*!
7495 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cbeginTargetBlends() const
7496 \return a const iterator pointing to the first item in the render target blend setting list.
7497 */
7498
7499/*!
7500 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cendTargetBlends() const
7501 \return a const iterator pointing just after the last item in the render target blend setting list.
7502 */
7503
7504/*!
7505 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::targetBlendAt(qsizetype index) const
7506 \return the render target blend setting at the specified \a index.
7507 */
7508
7509/*!
7510 \fn qsizetype QRhiGraphicsPipeline::targetBlendCount() const
7511 \return the number of render target blend settings.
7512 */
7513
7514/*!
7515 \fn bool QRhiGraphicsPipeline::hasDepthTest() const
7516 \return true if depth testing is enabled.
7517 */
7518
7519/*!
7520 \fn void QRhiGraphicsPipeline::setDepthTest(bool enable)
7521
7522 Enables or disables depth testing based on \a enable. Both depth test and
7523 the writing out of depth data are disabled by default.
7524
7525 \sa setDepthWrite()
7526 */
7527
7528/*!
7529 \fn bool QRhiGraphicsPipeline::hasDepthWrite() const
7530 \return true if depth write is enabled.
7531 */
7532
7533/*!
7534 \fn void QRhiGraphicsPipeline::setDepthWrite(bool enable)
7535
7536 Controls the writing out of depth data into the depth buffer based on
7537 \a enable. By default this is disabled. Depth write is typically enabled
7538 together with the depth test.
7539
7540 \note Enabling depth write without having depth testing enabled may not
7541 lead to the desired result, and should be avoided.
7542
7543 \sa setDepthTest()
7544 */
7545
7546/*!
7547 \fn bool QRhiGraphicsPipeline::hasDepthClamp() const
7548 \return true if depth clamp is enabled.
7549
7550 \since 6.11
7551 */
7552
7553/*!
7554 \fn void QRhiGraphicsPipeline::setDepthClamp(bool enable)
7555
7556 Enables depth clamping when \a enable is true. When depth clamping is
7557 enabled, primitives that would otherwise be clipped by the near or far
7558 clip plane are rasterized and their depth values are clamped to the
7559 depth range. When disabled (the default), such primitives are clipped.
7560
7561 \note This setting is ignored when the QRhi::DepthClamp feature is
7562 reported as unsupported.
7563
7564 \since 6.11
7565 */
7566
7567/*!
7568 \fn QRhiGraphicsPipeline::CompareOp QRhiGraphicsPipeline::depthOp() const
7569 \return the depth comparison function.
7570 */
7571
7572/*!
7573 \fn void QRhiGraphicsPipeline::setDepthOp(CompareOp op)
7574 Sets the depth comparison function \a op.
7575 */
7576
7577/*!
7578 \fn bool QRhiGraphicsPipeline::hasStencilTest() const
7579 \return true if stencil testing is enabled.
7580 */
7581
7582/*!
7583 \fn void QRhiGraphicsPipeline::setStencilTest(bool enable)
7584 Enables or disables stencil tests based on \a enable.
7585 By default this is disabled.
7586 */
7587
7588/*!
7589 \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilFront() const
7590 \return the current stencil test state for front faces.
7591 */
7592
7593/*!
7594 \fn void QRhiGraphicsPipeline::setStencilFront(const StencilOpState &state)
7595 Sets the stencil test \a state for front faces.
7596 */
7597
7598/*!
7599 \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilBack() const
7600 \return the current stencil test state for back faces.
7601 */
7602
7603/*!
7604 \fn void QRhiGraphicsPipeline::setStencilBack(const StencilOpState &state)
7605 Sets the stencil test \a state for back faces.
7606 */
7607
7608/*!
7609 \fn quint32 QRhiGraphicsPipeline::stencilReadMask() const
7610 \return the currrent stencil read mask.
7611 */
7612
7613/*!
7614 \fn void QRhiGraphicsPipeline::setStencilReadMask(quint32 mask)
7615 Sets the stencil read \a mask. The default value is 0xFF.
7616 */
7617
7618/*!
7619 \fn quint32 QRhiGraphicsPipeline::stencilWriteMask() const
7620 \return the current stencil write mask.
7621 */
7622
7623/*!
7624 \fn void QRhiGraphicsPipeline::setStencilWriteMask(quint32 mask)
7625 Sets the stencil write \a mask. The default value is 0xFF.
7626 */
7627
7628/*!
7629 \fn int QRhiGraphicsPipeline::sampleCount() const
7630 \return the currently set sample count. 1 means no multisample antialiasing.
7631 */
7632
7633/*!
7634 \fn void QRhiGraphicsPipeline::setSampleCount(int s)
7635
7636 Sets the sample count. Typical values for \a s are 1, 4, or 8. The pipeline
7637 must always be compatible with the render target, i.e. the sample counts
7638 must match.
7639
7640 \sa QRhi::supportedSampleCounts()
7641 */
7642
7643/*!
7644 \fn float QRhiGraphicsPipeline::lineWidth() const
7645 \return the currently set line width. The default is 1.0f.
7646 */
7647
7648/*!
7649 \fn void QRhiGraphicsPipeline::setLineWidth(float width)
7650
7651 Sets the line \a width. If the QRhi::WideLines feature is reported as
7652 unsupported at runtime, values other than 1.0f are ignored.
7653 */
7654
7655/*!
7656 \fn int QRhiGraphicsPipeline::depthBias() const
7657 \return the currently set depth bias.
7658 */
7659
7660/*!
7661 \fn void QRhiGraphicsPipeline::setDepthBias(int bias)
7662 Sets the depth \a bias. The default value is 0.
7663 */
7664
7665/*!
7666 \fn float QRhiGraphicsPipeline::slopeScaledDepthBias() const
7667 \return the currently set slope scaled depth bias.
7668 */
7669
7670/*!
7671 \fn void QRhiGraphicsPipeline::setSlopeScaledDepthBias(float bias)
7672 Sets the slope scaled depth \a bias. The default value is 0.
7673 */
7674
7675/*!
7676 \fn void QRhiGraphicsPipeline::setShaderStages(std::initializer_list<QRhiShaderStage> list)
7677 Sets the \a list of shader stages.
7678 */
7679
7680/*!
7681 \fn template<typename InputIterator> void QRhiGraphicsPipeline::setShaderStages(InputIterator first, InputIterator last)
7682 Sets the list of shader stages from the iterators \a first and \a last.
7683 */
7684
7685/*!
7686 \fn const QRhiShaderStage *QRhiGraphicsPipeline::cbeginShaderStages() const
7687 \return a const iterator pointing to the first item in the shader stage list.
7688 */
7689
7690/*!
7691 \fn const QRhiShaderStage *QRhiGraphicsPipeline::cendShaderStages() const
7692 \return a const iterator pointing just after the last item in the shader stage list.
7693 */
7694
7695/*!
7696 \fn const QRhiShaderStage *QRhiGraphicsPipeline::shaderStageAt(qsizetype index) const
7697 \return the shader stage at the specified \a index.
7698 */
7699
7700/*!
7701 \fn qsizetype QRhiGraphicsPipeline::shaderStageCount() const
7702 \return the number of shader stages in this pipeline.
7703 */
7704
7705/*!
7706 \fn QRhiVertexInputLayout QRhiGraphicsPipeline::vertexInputLayout() const
7707 \return the currently set vertex input layout specification.
7708 */
7709
7710/*!
7711 \fn void QRhiGraphicsPipeline::setVertexInputLayout(const QRhiVertexInputLayout &layout)
7712 Specifies the vertex input \a layout.
7713 */
7714
7715/*!
7716 \fn QRhiShaderResourceBindings *QRhiGraphicsPipeline::shaderResourceBindings() const
7717 \return the currently associated QRhiShaderResourceBindings object.
7718 */
7719
7720/*!
7721 \fn void QRhiGraphicsPipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
7722
7723 Associates with \a srb describing the resource binding layout and the
7724 resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional,
7725 because only the layout matters during pipeline creation. Therefore, the \a
7726 srb passed in here can leave the actual buffer or texture objects
7727 unspecified (\nullptr) as long as there is another,
7728 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
7729 QRhiShaderResourceBindings bound via
7730 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
7731 recording the draw calls.
7732 */
7733
7734/*!
7735 \fn QRhiRenderPassDescriptor *QRhiGraphicsPipeline::renderPassDescriptor() const
7736 \return the currently set QRhiRenderPassDescriptor.
7737 */
7738
7739/*!
7740 \fn void QRhiGraphicsPipeline::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
7741 Associates with the specified QRhiRenderPassDescriptor \a desc.
7742 */
7743
7744/*!
7745 \fn int QRhiGraphicsPipeline::patchControlPointCount() const
7746 \return the currently set patch control point count.
7747 */
7748
7749/*!
7750 \fn void QRhiGraphicsPipeline::setPatchControlPointCount(int count)
7751
7752 Sets the number of patch control points to \a count. The default value is
7753 3. This is used only when the topology is set to \l Patches.
7754 */
7755
7756/*!
7757 \fn QRhiGraphicsPipeline::PolygonMode QRhiGraphicsPipeline::polygonMode() const
7758 \return the polygon mode.
7759 */
7760
7761/*!
7762 \fn void QRhiGraphicsPipeline::setPolygonMode(PolygonMode mode)
7763 Sets the polygon \a mode. The default is Fill.
7764
7765 \sa QRhi::NonFillPolygonMode
7766 */
7767
7768/*!
7769 \fn int QRhiGraphicsPipeline::multiViewCount() const
7770 \return the view count. The default is 0, indicating no multiview rendering.
7771 \since 6.7
7772 */
7773
7774/*!
7775 \fn void QRhiGraphicsPipeline::setMultiViewCount(int count)
7776 Sets the view \a count for multiview rendering. The default is 0,
7777 indicating no multiview rendering.
7778 \a count must be 2 or larger to trigger multiview rendering.
7779
7780 Multiview is only available when the \l{QRhi::MultiView}{MultiView feature}
7781 is reported as supported. The render target must be a 2D texture array, and
7782 the color attachment for the render target must have the same \a count set.
7783
7784 See QRhiColorAttachment::setMultiViewCount() for further details on
7785 multiview rendering.
7786
7787 \since 6.7
7788 \sa QRhi::MultiView, QRhiColorAttachment::setMultiViewCount()
7789 */
7790
7791/*!
7792 \class QRhiSwapChain
7793 \inmodule QtGuiPrivate
7794 \inheaderfile rhi/qrhi.h
7795 \since 6.6
7796 \brief Swapchain resource.
7797
7798 A swapchain enables presenting rendering results to a surface. A swapchain
7799 is typically backed by a set of color buffers. Of these, one is displayed
7800 at a time.
7801
7802 Below is a typical pattern for creating and managing a swapchain and some
7803 associated resources in order to render onto a QWindow:
7804
7805 \code
7806 void init()
7807 {
7808 sc = rhi->newSwapChain();
7809 ds = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
7810 QSize(), // no need to set the size here due to UsedWithSwapChainOnly
7811 1,
7812 QRhiRenderBuffer::UsedWithSwapChainOnly);
7813 sc->setWindow(window);
7814 sc->setDepthStencil(ds);
7815 rp = sc->newCompatibleRenderPassDescriptor();
7816 sc->setRenderPassDescriptor(rp);
7817 resizeSwapChain();
7818 }
7819
7820 void resizeSwapChain()
7821 {
7822 hasSwapChain = sc->createOrResize();
7823 }
7824
7825 void render()
7826 {
7827 if (!hasSwapChain || notExposed)
7828 return;
7829
7830 if (sc->currentPixelSize() != sc->surfacePixelSize() || newlyExposed) {
7831 resizeSwapChain();
7832 if (!hasSwapChain)
7833 return;
7834 newlyExposed = false;
7835 }
7836
7837 rhi->beginFrame(sc);
7838 // ...
7839 rhi->endFrame(sc);
7840 }
7841 \endcode
7842
7843 Avoid relying on QWindow resize events to resize swapchains, especially
7844 considering that surface sizes may not always fully match the QWindow
7845 reported dimensions. The safe, cross-platform approach is to do the check
7846 via surfacePixelSize() whenever starting a new frame.
7847
7848 Releasing the swapchain must happen while the QWindow and the underlying
7849 native window is fully up and running. Building on the previous example:
7850
7851 \code
7852 void releaseSwapChain()
7853 {
7854 if (hasSwapChain) {
7855 sc->destroy();
7856 hasSwapChain = false;
7857 }
7858 }
7859
7860 // assuming Window is our QWindow subclass
7861 bool Window::event(QEvent *e)
7862 {
7863 switch (e->type()) {
7864 case QEvent::UpdateRequest: // for QWindow::requestUpdate()
7865 render();
7866 break;
7867 case QEvent::PlatformSurface:
7868 if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
7869 releaseSwapChain();
7870 break;
7871 default:
7872 break;
7873 }
7874 return QWindow::event(e);
7875 }
7876 \endcode
7877
7878 Initializing the swapchain and starting to render the first frame cannot
7879 start at any time. The safe, cross-platform approach is to rely on expose
7880 events. QExposeEvent is a loosely specified event that is sent whenever a
7881 window gets mapped, obscured, and resized, depending on the platform.
7882
7883 \code
7884 void Window::exposeEvent(QExposeEvent *)
7885 {
7886 // initialize and start rendering when the window becomes usable for graphics purposes
7887 if (isExposed() && !running) {
7888 running = true;
7889 init();
7890 }
7891
7892 // stop pushing frames when not exposed or size becomes 0
7893 if ((!isExposed() || (hasSwapChain && sc->surfacePixelSize().isEmpty())) && running)
7894 notExposed = true;
7895
7896 // continue when exposed again and the surface has a valid size
7897 if (isExposed() && running && notExposed && !sc->surfacePixelSize().isEmpty()) {
7898 notExposed = false;
7899 newlyExposed = true;
7900 }
7901
7902 if (isExposed() && !sc->surfacePixelSize().isEmpty())
7903 render();
7904 }
7905 \endcode
7906
7907 Once the rendering has started, a simple way to request a new frame is
7908 QWindow::requestUpdate(). While on some platforms this is merely a small
7909 timer, on others it has a specific implementation: for instance on macOS or
7910 iOS it may be backed by
7911 \l{https://developer.apple.com/documentation/corevideo/cvdisplaylink?language=objc}{CVDisplayLink}.
7912 The example above is already prepared for update requests by handling
7913 QEvent::UpdateRequest.
7914
7915 While acting as a QRhiRenderTarget, QRhiSwapChain also manages a
7916 QRhiCommandBuffer. Calling QRhi::endFrame() submits the recorded commands
7917 and also enqueues a \c present request. The default behavior is to do this
7918 with a swap interval of 1, meaning synchronizing to the display's vertical
7919 refresh is enabled. Thus the rendering thread calling beginFrame() and
7920 endFrame() will get throttled to vsync. On some backends this can be
7921 disabled by passing QRhiSwapChain:NoVSync in flags().
7922
7923 Multisampling (MSAA) is handled transparently to the applications when
7924 requested via setSampleCount(). Where applicable, QRhiSwapChain will take
7925 care of creating additional color buffers and issuing a multisample resolve
7926 command at the end of a frame. For OpenGL, it is necessary to request the
7927 appropriate sample count also via QSurfaceFormat, by calling
7928 QSurfaceFormat::setDefaultFormat() before initializing the QRhi.
7929
7930 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7931 for details.
7932 */
7933
7934/*!
7935 \enum QRhiSwapChain::Flag
7936 Flag values to describe swapchain properties
7937
7938 \value SurfaceHasPreMulAlpha Indicates that the target surface has
7939 transparency with premultiplied alpha. For example, this is what Qt Quick
7940 uses when the alpha channel is enabled on the target QWindow, because the
7941 scenegraph rendrerer always outputs fragments with alpha multiplied into
7942 the red, green, and blue values. To ensure identical behavior across
7943 platforms, always set QSurfaceFormat::alphaBufferSize() to a non-zero value
7944 on the target QWindow whenever this flag is set on the swapchain.
7945
7946 \value SurfaceHasNonPreMulAlpha Indicates the target surface has
7947 transparency with non-premultiplied alpha. Be aware that this may not be
7948 supported on some systems, if the system compositor always expects content
7949 with premultiplied alpha. In that case the behavior with this flag set is
7950 expected to be equivalent to SurfaceHasPreMulAlpha.
7951
7952 \value sRGB Requests to pick an sRGB format for the swapchain's color
7953 buffers and/or render target views, where applicable. Note that this
7954 implies that sRGB framebuffer update and blending will get enabled for all
7955 content targeting this swapchain, and opting out is not possible. For
7956 OpenGL, set \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the
7957 QSurfaceFormat of the QWindow in addition. Applicable only when the
7958 swapchain format is set to QRhiSwapChain::SDR.
7959
7960 \value UsedAsTransferSource Indicates the swapchain will be used as the
7961 source of a readback in QRhiResourceUpdateBatch::readBackTexture().
7962
7963 \value NoVSync Requests disabling waiting for vertical sync, also avoiding
7964 throttling the rendering thread. The behavior is backend specific and
7965 applicable only where it is possible to control this. Some may ignore the
7966 request altogether. For OpenGL, try instead setting the swap interval to 0
7967 on the QWindow via QSurfaceFormat::setSwapInterval().
7968
7969 \value MinimalBufferCount Requests creating the swapchain with the minimum
7970 number of buffers, which is in practice 2, unless the graphics
7971 implementation has a higher minimum number than that. Only applicable with
7972 backends where such control is available via the graphics API, for example,
7973 Vulkan. By default it is up to the backend to decide what number of buffers
7974 it requests (in practice this is almost always either 2 or 3), and it is
7975 not the applications' concern. However, on Vulkan for instance the backend
7976 will likely prefer the higher number (3), for example to avoid odd
7977 performance issues with some Vulkan implementations on mobile devices. It
7978 could be that on some platforms it can prove to be beneficial to force the
7979 lower buffer count (2), so this flag allows forcing that. Note that all
7980 this has no effect on the number of frames kept in flight, so the CPU
7981 (QRhi) will still prepare frames at most \c{N - 1} frames ahead of the GPU,
7982 even when the swapchain image buffer count larger than \c N. (\c{N} =
7983 QRhi::FramesInFlight and typically 2).
7984 */
7985
7986/*!
7987 \enum QRhiSwapChain::Format
7988 Describes the swapchain format. The default format is SDR.
7989
7990 This enum is used with
7991 \l{QRhiSwapChain::isFormatSupported()}{isFormatSupported()} to check
7992 upfront if creating the swapchain with the given format is supported by the
7993 platform and the window's associated screen, and with
7994 \l{QRhiSwapChain::setFormat()}{setFormat()}
7995 to set the requested format in the swapchain before calling
7996 \l{QRhiSwapChain::createOrResize()}{createOrResize()} for the first time.
7997
7998 \value SDR 8-bit RGBA or BGRA, depending on the backend and platform. With
7999 OpenGL ES in particular, it could happen that the platform provides less
8000 than 8 bits (e.g. due to EGL and the QSurfaceFormat choosing a 565 or 444
8001 format - this is outside the control of QRhi). Standard dynamic range. May
8002 be combined with setting the QRhiSwapChain::sRGB flag.
8003
8004 \value HDRExtendedSrgbLinear 16-bit float RGBA, high dynamic range,
8005 extended linear sRGB (scRGB) color space. This involves Rec. 709 primaries
8006 (same as SDR/sRGB) and linear colors. Conversion to the display's native
8007 color space (such as, HDR10) is performed by the windowing system. On
8008 Windows this is the canonical color space of the system compositor, and is
8009 the recommended format for HDR swapchains in general on desktop platforms.
8010
8011 \value HDR10 10-bit unsigned int RGB or BGR with 2 bit alpha, high dynamic
8012 range, HDR10 (Rec. 2020) color space with an ST2084 PQ transfer function.
8013
8014 \value HDRExtendedDisplayP3Linear 16-bit float RGBA, high dynamic range,
8015 extended linear Display P3 color space. The primary choice for HDR on
8016 platforms such as iOS and VisionOS.
8017 */
8018
8019/*!
8020 \internal
8021 */
8022QRhiSwapChain::QRhiSwapChain(QRhiImplementation *rhi)
8023 : QRhiResource(rhi)
8024{
8025}
8026
8027/*!
8028 \return the resource type.
8029 */
8030QRhiResource::Type QRhiSwapChain::resourceType() const
8031{
8032 return SwapChain;
8033}
8034
8035/*!
8036 \fn QSize QRhiSwapChain::currentPixelSize() const
8037
8038 \return the size with which the swapchain was last successfully built. Use
8039 this to decide if createOrResize() needs to be called again: if
8040 \c{currentPixelSize() != surfacePixelSize()} then the swapchain needs to be
8041 resized.
8042
8043 \note Typical rendering logic will call this function to get the output
8044 size when starting to prepare a new frame, and base dependent calculations
8045 (such as, the viewport) on the size returned from this function.
8046
8047 While in many cases the value is the same as \c{QWindow::size() *
8048 QWindow::devicePixelRatio()}, relying on the QWindow-reported size is not
8049 guaranteed to be correct on all platforms and graphics API implementations.
8050 Using this function is therefore strongly recommended whenever there is a
8051 need to identify the dimensions, in pixels, of the output layer or surface.
8052
8053 This also has the added benefit of avoiding potential data races when QRhi
8054 is used on a dedicated rendering thread, because the need to call QWindow
8055 functions, that may then access data updated on the main thread, is
8056 avoided.
8057
8058 \sa surfacePixelSize()
8059 */
8060
8061/*!
8062 \fn virtual QSize QRhiSwapChain::surfacePixelSize() = 0
8063
8064 \return The size of the window's associated surface or layer.
8065
8066 \warning Do not assume this is the same as \c{QWindow::size() *
8067 QWindow::devicePixelRatio()}. With some graphics APIs and windowing system
8068 interfaces (for example, Vulkan) there is a theoretical possibility for a
8069 surface to assume a size different from the associated window. To support
8070 these cases, \b{rendering logic must always base size-derived calculations
8071 (such as, viewports) on the size reported from QRhiSwapChain, and never on
8072 the size queried from QWindow}.
8073
8074 \note \b{Can also be called before createOrResize(), if at least window() is
8075 already set. This in combination with currentPixelSize() allows to detect
8076 when a swapchain needs to be resized.} However, watch out for the fact that
8077 the size of the underlying native object (surface, layer, or similar) is
8078 "live", so whenever this function is called, it returns the latest value
8079 reported by the underlying implementation, without any atomicity guarantee.
8080 Therefore, using this function to determine pixel sizes for graphics
8081 resources that are used in a frame is strongly discouraged. Rely on
8082 currentPixelSize() instead which returns a size that is atomic and will not
8083 change between createOrResize() invocations.
8084
8085 \note For depth-stencil buffers used in combination with the swapchain's
8086 color buffers, it is strongly recommended to rely on the automatic sizing
8087 and rebuilding behavior provided by the
8088 QRhiRenderBuffer:UsedWithSwapChainOnly flag. Avoid querying the surface
8089 size via this function just to get a size that can be passed to
8090 QRhiRenderBuffer::setPixelSize() as that would suffer from the lack of
8091 atomicity as described above.
8092
8093 \sa currentPixelSize()
8094 */
8095
8096/*!
8097 \fn virtual bool QRhiSwapChain::isFormatSupported(Format f) = 0
8098
8099 \return true if the given swapchain format \a f is supported. SDR is always
8100 supported.
8101
8102 \note Can be called independently of createOrResize(), but window() must
8103 already be set. Calling without the window set may lead to unexpected
8104 results depending on the backend and platform (most likely false for any
8105 HDR format), because HDR format support is usually tied to the output
8106 (screen) to which the swapchain's associated window belongs at any given
8107 time. If the result is true for a HDR format, then creating the swapchain
8108 with that format is expected to succeed as long as the window is not moved
8109 to another screen in the meantime.
8110
8111 The main use of this function is to call it before the first
8112 createOrResize() after the window is already set. This allow the QRhi
8113 backends to perform platform or windowing system specific queries to
8114 determine if the window (and the screen it is on) is capable of true HDR
8115 output with the specified format.
8116
8117 When the format is reported as supported, call setFormat() to set the
8118 requested format and call createOrResize(). Be aware of the consequences
8119 however: successfully requesting a HDR format will involve having to deal
8120 with a different color space, possibly doing white level correction for
8121 non-HDR-aware content, adjusting tonemapping methods, adjusting offscreen
8122 render target settings, etc.
8123
8124 \sa setFormat()
8125 */
8126
8127/*!
8128 \fn virtual QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer() = 0
8129
8130 \return a command buffer on which rendering commands and resource updates
8131 can be recorded within a \l{QRhi::beginFrame()}{beginFrame} -
8132 \l{QRhi::endFrame()}{endFrame} block, assuming beginFrame() was called with
8133 this swapchain.
8134
8135 \note The returned object is valid also after endFrame(), up until the next
8136 beginFrame(), but the returned command buffer should not be used to record
8137 any commands then. Rather, it can be used to query data collected during
8138 the frame (or previous frames), for example by calling
8139 \l{QRhiCommandBuffer::lastCompletedGpuTime()}{lastCompletedGpuTime()}.
8140
8141 \note The value must not be cached and reused between frames. The caller
8142 should not hold on to the returned object once
8143 \l{QRhi::beginFrame()}{beginFrame()} is called again. Instead, the command
8144 buffer object should be queried again by calling this function.
8145*/
8146
8147/*!
8148 \fn virtual QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget() = 0
8149
8150 \return a render target that can used with beginPass() in order to render
8151 the swapchain's current backbuffer. Only valid within a
8152 QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called
8153 with this swapchain.
8154
8155 \note the value must not be cached and reused between frames
8156 */
8157
8158/*!
8159 \enum QRhiSwapChain::StereoTargetBuffer
8160 Selects the backbuffer to use with a stereoscopic swapchain.
8161
8162 \value LeftBuffer
8163 \value RightBuffer
8164 */
8165
8166/*!
8167 \return a render target that can be used with beginPass() in order to
8168 render to the swapchain's left or right backbuffer. This overload should be
8169 used only with stereoscopic rendering, that is, when the associated QWindow
8170 is backed by two color buffers, one for each eye, instead of just one.
8171
8172 When stereoscopic rendering is not supported, the return value will be
8173 the default target. It is supported by all hardware backends except for Metal, in
8174 combination with \l QSurfaceFormat::StereoBuffers, assuming it is supported
8175 by the graphics and display driver stack at run time. Metal and Null backends
8176 are going to return the default render target from this overload.
8177
8178 \note the value must not be cached and reused between frames
8179 */
8180QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
8181{
8182 Q_UNUSED(targetBuffer);
8183 return currentFrameRenderTarget();
8184}
8185
8186/*!
8187 \fn virtual bool QRhiSwapChain::createOrResize() = 0
8188
8189 Creates the swapchain if not already done and resizes the swapchain buffers
8190 to match the current size of the targeted surface. Call this whenever the
8191 size of the target surface is different than before.
8192
8193 \note call destroy() only when the swapchain needs to be released
8194 completely, typically upon
8195 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed. To perform resizing, just
8196 call createOrResize().
8197
8198 \return \c true when successful, \c false when a graphics operation failed.
8199 Regardless of the return value, calling destroy() is always safe.
8200 */
8201
8202/*!
8203 \fn QWindow *QRhiSwapChain::window() const
8204 \return the currently set window.
8205 */
8206
8207/*!
8208 \fn void QRhiSwapChain::setWindow(QWindow *window)
8209 Sets the \a window.
8210 */
8211
8212/*!
8213 \fn QRhiSwapChainProxyData QRhiSwapChain::proxyData() const
8214 \return the currently set proxy data.
8215 */
8216
8217/*!
8218 \fn void QRhiSwapChain::setProxyData(const QRhiSwapChainProxyData &d)
8219 Sets the proxy data \a d.
8220
8221 \sa QRhi::updateSwapChainProxyData()
8222 */
8223
8224/*!
8225 \fn QRhiSwapChain::Flags QRhiSwapChain::flags() const
8226 \return the currently set flags.
8227 */
8228
8229/*!
8230 \fn void QRhiSwapChain::setFlags(Flags f)
8231 Sets the flags \a f.
8232 */
8233
8234/*!
8235 \fn QRhiSwapChain::Format QRhiSwapChain::format() const
8236 \return the currently set format.
8237 */
8238
8239/*!
8240 \fn void QRhiSwapChain::setFormat(Format f)
8241 Sets the format \a f.
8242
8243 Avoid setting formats that are reported as unsupported from
8244 isFormatSupported(). Note that support for a given format may depend on the
8245 screen the swapchain's associated window is opened on. On some platforms,
8246 such as Windows and macOS, for HDR output to work it is necessary to have
8247 HDR output enabled in the display settings.
8248
8249 See isFormatSupported(), \l QRhiSwapChainHdrInfo, and \l Format for more
8250 information on high dynamic range output.
8251 */
8252
8253/*!
8254 \fn QRhiRenderBuffer *QRhiSwapChain::depthStencil() const
8255 \return the currently associated renderbuffer for depth-stencil.
8256 */
8257
8258/*!
8259 \fn void QRhiSwapChain::setDepthStencil(QRhiRenderBuffer *ds)
8260 Sets the renderbuffer \a ds for use as a depth-stencil buffer.
8261 */
8262
8263/*!
8264 \fn int QRhiSwapChain::sampleCount() const
8265 \return the currently set sample count. 1 means no multisample antialiasing.
8266 */
8267
8268/*!
8269 \fn void QRhiSwapChain::setSampleCount(int samples)
8270
8271 Sets the sample count. Common values for \a samples are 1 (no MSAA), 4 (4x
8272 MSAA), or 8 (8x MSAA).
8273
8274 \sa QRhi::supportedSampleCounts()
8275 */
8276
8277/*!
8278 \fn QRhiRenderPassDescriptor *QRhiSwapChain::renderPassDescriptor() const
8279 \return the currently associated QRhiRenderPassDescriptor object.
8280 */
8281
8282/*!
8283 \fn void QRhiSwapChain::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
8284 Associates with the QRhiRenderPassDescriptor \a desc.
8285 */
8286
8287/*!
8288 \fn virtual QRhiRenderPassDescriptor *QRhiSwapChain::newCompatibleRenderPassDescriptor() = 0;
8289
8290 \return a new QRhiRenderPassDescriptor that is compatible with this swapchain.
8291
8292 The returned value is used in two ways: it can be passed to
8293 setRenderPassDescriptor() and
8294 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
8295 describes the attachments (color, depth/stencil) and the load/store
8296 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
8297 be used in combination with a swapchain that has a
8298 \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
8299 QRhiRenderPassDescriptor set.
8300
8301 \sa createOrResize()
8302 */
8303
8304/*!
8305 \fn QRhiShadingRateMap *QRhiSwapChain::shadingRateMap() const
8306 \return the currently set QRhiShadingRateMap. By default this is \nullptr.
8307 \since 6.9
8308 */
8309
8310/*!
8311 \fn void QRhiSwapChain::setShadingRateMap(QRhiShadingRateMap *map)
8312
8313 Associates with the specified QRhiShadingRateMap \a map. This is functional
8314 only when the \l QRhi::VariableRateShadingMap feature is reported as
8315 supported.
8316
8317 When QRhiCommandBuffer::setShadingRate() is also called, the higher of the
8318 two shading rates is used for each tile. There is currently no control
8319 offered over the combiner behavior.
8320
8321 \note Setting a shading rate map implies that a different, new
8322 QRhiRenderPassDescriptor is needed and some of the native swapchain objects
8323 must be rebuilt. Therefore, if the swapchain is already set up, call
8324 newCompatibleRenderPassDescriptor() and setRenderPassDescriptor() right
8325 after setShadingRateMap(). Then, createOrResize() must also be called again.
8326 This has rolling consequences, for example for graphics pipelines: those
8327 also need to be associated with the new QRhiRenderPassDescriptor and then
8328 rebuilt. See \l QRhiRenderPassDescriptor::serializedFormat() for some
8329 suggestions on how to deal with this. Remember to set the
8330 QRhiGraphicsPipeline::UsesShadingRate flag for them as well.
8331
8332 \since 6.9
8333 */
8334
8335/*!
8336 \struct QRhiSwapChainHdrInfo
8337 \inmodule QtGuiPrivate
8338 \inheaderfile rhi/qrhi.h
8339 \since 6.6
8340
8341 \brief Describes the high dynamic range related information of the
8342 swapchain's associated output.
8343
8344 To perform HDR-compatible tonemapping, where the target range is not [0,1],
8345 one often needs to know the maximum luminance of the display the
8346 swapchain's window is associated with. While this is often made
8347 user-configurable (think brightness, gamma and similar settings in games),
8348 it can be highly useful to set defaults based on the values reported by the
8349 display itself, thus providing a decent starting point.
8350
8351 There are some problems however: the information is exposed in different
8352 forms on different platforms, whereas with cross-platform graphics APIs
8353 there is often no associated solution at all, because managing such
8354 information is not in the scope of the API (and may rather be retrievable
8355 via other platform-specific means, if any).
8356
8357 With Metal on macOS/iOS, there is no luminance values exposed in the
8358 platform APIs. Instead, the maximum color component value, that would be
8359 1.0 in a non-HDR setup, is provided. The \c limitsType field indicates what
8360 kind of information is available. It is then up to the clients of QRhi to
8361 access the correct data from the \c limits union and use it as they see
8362 fit.
8363
8364 With an API like Vulkan, where there is no way to get such information, the
8365 values are always the built-in defaults.
8366
8367 Therefore, the struct returned from QRhiSwapChain::hdrInfo() contains
8368 either some hard-coded defaults or real values received from an API such as
8369 DXGI (IDXGIOutput6) or Cocoa (NSScreen). When no platform queries are
8370 available (or needs using platform facilities out of scope for QRhi), the
8371 hard-coded defaults are a maximum luminance of 1000 nits and an SDR white
8372 level of 200.
8373
8374 The struct also exposes the presumed luminance behavior of the platform and
8375 its compositor, to indicate what a color component value of 1.0 is treated
8376 as in a HDR color buffer. In some cases it will be necessary to perform
8377 color correction of non-HDR content composited with HDR content. To enable
8378 this, the SDR white level is queried from the system on some platforms
8379 (Windows) and exposed here.
8380
8381 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8382 for details.
8383
8384 \sa QRhiSwapChain::hdrInfo()
8385 */
8386
8387/*!
8388 \enum QRhiSwapChainHdrInfo::LimitsType
8389
8390 \value LuminanceInNits Indicates that the \l limits union has its
8391 \c luminanceInNits struct set
8392
8393 \value ColorComponentValue Indicates that the \l limits union has its
8394 \c colorComponentValue struct set
8395*/
8396
8397/*!
8398 \enum QRhiSwapChainHdrInfo::LuminanceBehavior
8399
8400 \value SceneReferred Indicates that the color value of 1.0 is interpreted
8401 as 80 nits. This is the behavior of HDR-enabled windows with the Windows
8402 compositor. See
8403 \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range}{this
8404 page} for more information on HDR on Windows.
8405
8406 \value DisplayReferred Indicates that the color value of 1.0 is interpreted
8407 as the value of the SDR white. (which can be e.g. 200 nits, but will vary
8408 depending on screen brightness) This is the behavior of HDR-enabled windows
8409 on Apple platforms. See
8410 \l{https://developer.apple.com/documentation/metal/hdr_content/displaying_hdr_content_in_a_metal_layer}{this
8411 page} for more information on Apple's EDR system.
8412*/
8413
8414/*!
8415 \variable QRhiSwapChainHdrInfo::limitsType
8416
8417 With Metal on macOS/iOS, there is no luminance values exposed in the
8418 platform APIs. Instead, the maximum color component value, that would be
8419 1.0 in a non-HDR setup, is provided. This value indicates what kind of
8420 information is available in \l limits.
8421
8422 \sa QRhiSwapChain::hdrInfo()
8423*/
8424
8425/*!
8426 \variable QRhiSwapChainHdrInfo::limits
8427
8428 Contains the actual values queried from the graphics API or the platform.
8429 The type of data is indicated by \l limitsType. This is therefore a union.
8430 There are currently two options:
8431
8432 Luminance values in nits:
8433
8434 \code
8435 struct {
8436 float minLuminance;
8437 float maxLuminance;
8438 } luminanceInNits;
8439 \endcode
8440
8441 On Windows the minimum and maximum luminance depends on the screen
8442 brightness. While not relevant for desktops, on laptops the screen
8443 brightness may change at any time. Increasing brightness implies decreased
8444 maximum luminance. In addition, the results may also be dependent on the
8445 HDR Content Brightness set in Windows Settings' System/Display/HDR view,
8446 if there is such a setting.
8447
8448 Note however that the changes made to the laptop screen's brightness or in
8449 the system settings while the application is running are not necessarily
8450 reflected in the returned values, meaning calling hdrInfo() again may still
8451 return the same luminance range as before for the rest of the process'
8452 lifetime. The exact behavior is up to DXGI and Qt has no control over it.
8453
8454 \note The Windows compositor works in scene-referred mode for HDR content.
8455 A color component value of 1.0 corresponds to a luminance of 80 nits. When
8456 rendering non-HDR content (e.g. 2D UI elements), the correction of the
8457 white level is often necessary. (e.g., outputting the fragment color (1, 1,
8458 1) will likely lead to showing a shade of white that is too dim on-screen)
8459 See \l sdrWhiteLevel.
8460
8461 For macOS/iOS, the current maximum and potential maximum color
8462 component values are provided:
8463
8464 \code
8465 struct {
8466 float maxColorComponentValue;
8467 float maxPotentialColorComponentValue;
8468 } colorComponentValue;
8469 \endcode
8470
8471 The value may depend on the screen brightness, which on laptops means that
8472 the result may change in the next call to hdrInfo() if the brightness was
8473 changed in the meantime. The maximum screen brightness implies a maximum
8474 color value of 1.0.
8475
8476 \note Apple's EDR is display-referred. 1.0 corresponds to a luminance level
8477 of SDR white (e.g. 200 nits), the value of which varies based on the screen
8478 brightness and possibly other settings. The exact luminance value for that,
8479 or the maximum luminance of the display, are not exposed to the
8480 applications.
8481
8482 \note It has been observed that the color component values are not set to
8483 the correct larger-than-1 value right away on startup on some macOS
8484 systems, but the values tend to change during or after the first frame.
8485
8486 \sa QRhiSwapChain::hdrInfo()
8487*/
8488
8489/*!
8490 \variable QRhiSwapChainHdrInfo::luminanceBehavior
8491
8492 Describes the platform's presumed behavior with regards to color values.
8493
8494 \sa sdrWhiteLevel
8495 */
8496
8497/*!
8498 \variable QRhiSwapChainHdrInfo::sdrWhiteLevel
8499
8500 On Windows this is the dynamic SDR white level in nits. The value is
8501 dependent on the screen brightness (on laptops), and the SDR or HDR Content
8502 Brightness settings in the Windows settings' System/Display/HDR view.
8503
8504 To perform white level correction for non-HDR (SDR) content, such as 2D UI
8505 elemenents, multiply the final color with sdrWhiteLevel / 80.0 whenever
8506 \l luminanceBehavior is SceneReferred. (assuming Windows and a linear
8507 extended sRGB (scRGB) color space)
8508
8509 On other platforms the value is always a pre-defined value, 200. This may
8510 not match the system's actual SDR white level, but the value of this
8511 variable is not relevant in practice when the \l luminanceBehavior is
8512 DisplayReferred, because then the color component value of 1.0 refers to
8513 the SDR white by default.
8514
8515 \sa luminanceBehavior
8516*/
8517
8518/*!
8519 \return the HDR information for the associated display.
8520
8521 Do not assume that this is a cheap operation. Depending on the platform,
8522 this function makes various platform queries which may have a performance
8523 impact.
8524
8525 \note Can be called before createOrResize() as long as the window is
8526 \l{setWindow()}{set}.
8527
8528 \note What happens when moving a window with an initialized swapchain
8529 between displays (HDR to HDR with different characteristics, HDR to SDR,
8530 etc.) is not currently well-defined and depends heavily on the windowing
8531 system and compositor, with potentially varying behavior between platforms.
8532 Currently QRhi only guarantees that hdrInfo() returns valid data, if
8533 available, for the display to which the swapchain's associated window
8534 belonged at the time of createOrResize().
8535
8536 \sa QRhiSwapChainHdrInfo
8537 */
8538QRhiSwapChainHdrInfo QRhiSwapChain::hdrInfo()
8539{
8540 QRhiSwapChainHdrInfo info;
8541 info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
8542 info.limits.luminanceInNits.minLuminance = 0.0f;
8543 info.limits.luminanceInNits.maxLuminance = 1000.0f;
8544 info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
8545 info.sdrWhiteLevel = 200.0f;
8546 return info;
8547}
8548
8549#ifndef QT_NO_DEBUG_STREAM
8550QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
8551{
8552 QDebugStateSaver saver(dbg);
8553 dbg.nospace() << "QRhiSwapChainHdrInfo(";
8554 switch (info.limitsType) {
8556 dbg.nospace() << " minLuminance=" << info.limits.luminanceInNits.minLuminance
8557 << " maxLuminance=" << info.limits.luminanceInNits.maxLuminance;
8558 break;
8560 dbg.nospace() << " maxColorComponentValue=" << info.limits.colorComponentValue.maxColorComponentValue;
8561 dbg.nospace() << " maxPotentialColorComponentValue=" << info.limits.colorComponentValue.maxPotentialColorComponentValue;
8562 break;
8563 }
8564 switch (info.luminanceBehavior) {
8566 dbg.nospace() << " scene-referred, SDR white level=" << info.sdrWhiteLevel;
8567 break;
8569 dbg.nospace() << " display-referred";
8570 break;
8571 }
8572 dbg.nospace() << ')';
8573 return dbg;
8574}
8575#endif
8576
8577/*!
8578 \class QRhiComputePipeline
8579 \inmodule QtGuiPrivate
8580 \inheaderfile rhi/qrhi.h
8581 \since 6.6
8582 \brief Compute pipeline state resource.
8583
8584 \note Setting the shader resource bindings is mandatory. The referenced
8585 QRhiShaderResourceBindings must already have created() called on it by the
8586 time create() is called.
8587
8588 \note Setting the shader is mandatory.
8589
8590 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8591 for details.
8592 */
8593
8594/*!
8595 \enum QRhiComputePipeline::Flag
8596
8597 Flag values for describing pipeline options.
8598
8599 \value CompileShadersWithDebugInfo Requests compiling shaders with debug
8600 information enabled, when applicable. See
8601 QRhiGraphicsPipeline::CompileShadersWithDebugInfo for more information.
8602 */
8603
8604/*!
8605 \return the resource type.
8606 */
8607QRhiResource::Type QRhiComputePipeline::resourceType() const
8608{
8609 return ComputePipeline;
8610}
8611
8612/*!
8613 \internal
8614 */
8615QRhiComputePipeline::QRhiComputePipeline(QRhiImplementation *rhi)
8616 : QRhiResource(rhi)
8617{
8618}
8619
8620/*!
8621 \fn QRhiComputePipeline::Flags QRhiComputePipeline::flags() const
8622 \return the currently set flags.
8623 */
8624
8625/*!
8626 \fn void QRhiComputePipeline::setFlags(Flags f)
8627 Sets the flags \a f.
8628 */
8629
8630/*!
8631 \fn QRhiShaderStage QRhiComputePipeline::shaderStage() const
8632 \return the currently set shader.
8633 */
8634
8635/*!
8636 \fn void QRhiComputePipeline::setShaderStage(const QRhiShaderStage &stage)
8637
8638 Sets the shader to use. \a stage can only refer to the
8639 \l{QRhiShaderStage::Compute}{compute stage}.
8640 */
8641
8642/*!
8643 \fn QRhiShaderResourceBindings *QRhiComputePipeline::shaderResourceBindings() const
8644 \return the currently associated QRhiShaderResourceBindings object.
8645 */
8646
8647/*!
8648 \fn void QRhiComputePipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
8649
8650 Associates with \a srb describing the resource binding layout and the
8651 resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional. As
8652 with graphics pipelines, the \a srb passed in here can leave the actual
8653 buffer or texture objects unspecified (\nullptr) as long as there is
8654 another,
8655 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
8656 QRhiShaderResourceBindings bound via
8657 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
8658 recording the dispatch call.
8659 */
8660
8661/*!
8662 \struct QRhiIndirectDrawCommand
8663 \inmodule QtGuiPrivate
8664 \inheaderfile rhi/qrhi.h
8665 \since 6.12
8666 \brief Draw command.
8667
8668 A draw command that can be uploaded to a QRhiBuffer of usage
8669 QRhiBuffer::UsageFlag::IndirectBuffer.
8670
8671 \sa QRhiCommandBuffer::drawIndirect()
8672
8673 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8674 for details.
8675 */
8676
8677/*!
8678 \variable QRhiIndirectDrawCommand::vertexCount
8679*/
8680
8681/*!
8682 \variable QRhiIndirectDrawCommand::instanceCount
8683*/
8684
8685/*!
8686 \variable QRhiIndirectDrawCommand::firstVertex
8687*/
8688
8689/*!
8690 \variable QRhiIndirectDrawCommand::firstInstance
8691*/
8692
8693/*!
8694 \struct QRhiIndexedIndirectDrawCommand
8695 \inmodule QtGuiPrivate
8696 \inheaderfile rhi/qrhi.h
8697 \since 6.12
8698 \brief Indexed draw command.
8699
8700 An indexed draw command that can be uploaded to a QRhiBuffer of usage
8701 QRhiBuffer::UsageFlag::IndirectBuffer.
8702
8703 \sa QRhiCommandBuffer::drawIndexedIndirect()
8704
8705 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8706 for details.
8707 */
8708
8709/*!
8710 \variable QRhiIndexedIndirectDrawCommand::indexCount
8711*/
8712
8713/*!
8714 \variable QRhiIndexedIndirectDrawCommand::instanceCount
8715*/
8716
8717/*!
8718 \variable QRhiIndexedIndirectDrawCommand::firstIndex
8719*/
8720
8721/*!
8722 \variable QRhiIndexedIndirectDrawCommand::vertexOffset
8723*/
8724
8725/*!
8726 \variable QRhiIndexedIndirectDrawCommand::firstInstance
8727*/
8728
8729/*!
8730 \struct QRhiDispatchIndirectCommand
8731 \inmodule QtGuiPrivate
8732 \inheaderfile rhi/qrhi.h
8733 \since 6.13
8734 \brief Compute dispatch command.
8735
8736 A compute dispatch command that can be uploaded to a QRhiBuffer of usage
8737 QRhiBuffer::UsageFlag::IndirectBuffer. The fields specify the number of
8738 local work groups along each dimension and have the same meaning as the
8739 \c x, \c y, \c z parameters of QRhiCommandBuffer::dispatch().
8740
8741 \c y and \c z default to 1, so a one dimensional dispatch only needs \c x
8742 to be set. Note that a count of 0 in any dimension is valid and results in
8743 no work groups being launched at all.
8744
8745 \sa QRhiCommandBuffer::dispatchIndirect()
8746
8747 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8748 for details.
8749 */
8750
8751/*!
8752 \variable QRhiDispatchIndirectCommand::x
8753*/
8754
8755/*!
8756 \variable QRhiDispatchIndirectCommand::y
8757*/
8758
8759/*!
8760 \variable QRhiDispatchIndirectCommand::z
8761*/
8762
8763/*!
8764 \class QRhiIndirectCommandBuffer
8765 \inmodule QtGuiPrivate
8766 \inheaderfile rhi/qrhi.h
8767 \since 6.13
8768 \brief A prerecorded batch of indirect draw commands.
8769
8770 A QRhiIndirectCommandBuffer holds a number of draw commands that are
8771 recorded once and can then be replayed any number of times with a single
8772 QRhiCommandBuffer::executeIndirect() call. It is an alternative to the
8773 buffer-based QRhiCommandBuffer::drawIndirect() family of functions. Under
8774 the hood, it may do exactly the same as does (typical with Vulkan, Direct
8775 3D, and OpenGL), or may be implemented differently (Metal).
8776
8777 Create one with QRhi::newIndirectCommandBuffer(), passing in the type and
8778 the maximum number of commands, and call create(). The (maximum) command
8779 count is mandatory, whichever way the commands are going to be provided: it
8780 is the capacity of the object, and create() fails when it is 0.
8781
8782 \badcode
8783 icb = rhi->newIndirectCommandBuffer(QRhiIndirectCommandBuffer::IndexedDraws, 1024);
8784 if (!icb->create()) { error(); }
8785 \endcode
8786
8787 Record commands with draw() or drawIndexed(), then hand the object to a
8788 resource update batch so that the recorded contents reach the GPU.
8789 commitIndirectCommandBuffer() has to be called after recording and before
8790 the pass that executes the commands. It is a no-op when nothing changed
8791 since the last time, so calling it every frame is cheap.
8792
8793 Executing happens inside a render pass:
8794
8795 \badcode
8796 icb->clear();
8797 for (const Item &item : items)
8798 icb->drawIndexed(item.indexCount, 1, item.firstIndex, item.vertexOffset);
8799
8800 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
8801 u->commitIndirectCommandBuffer(icb);
8802
8803 cb->beginPass(rt, Qt::black, { 1.0f, 0 }, u);
8804 cb->setGraphicsPipeline(ps);
8805 cb->setVertexInput(0, 1, &vbufBinding, ibuf, 0, QRhiCommandBuffer::IndexUInt16);
8806 cb->setShaderResources();
8807 cb->executeIndirect(icb);
8808 cb->endPass();
8809 \endcode
8810
8811 The commands can also be generated on the GPU instead of being recorded on
8812 the CPU. In that case fill a buffer with QRhiIndirectDrawCommand or
8813 QRhiIndexedIndirectDrawCommand entries from a compute shader, and call
8814 QRhiCommandBuffer::buildIndirect() with that buffer. That call must happen
8815 outside of any pass. The CPU-side recording functions of
8816 QRhiIndirectCommandBuffer are not used in this case.
8817
8818 \badcode
8819 cb->beginComputePass();
8820 ... // a cb->dispatch() to invoke a compute shader that writes to indirectBuf
8821 cb->endComputePass();
8822
8823 QRhiIndirectCommandBufferBuildInfo buildInfo;
8824 buildInfo.topology = ps->topology();
8825 buildInfo.sourceBuffer = indirectBuf;
8826 buildInfo.commandCount = itemCount; // as many as the compute shader wrote
8827 buildInfo.indexBuffer = indexBuffer;
8828 buildInfo.indexFormat = QRhiCommandBuffer::IndexUInt16;
8829 cb->buildIndirect(icb, buildInfo);
8830
8831 cb->beginPass(rt, Qt::black, { 1.0f, 0 });
8832 cb->setGraphicsPipeline(ps);
8833 cb->setVertexInput(0, 1, &vbufBinding, ibuf, 0, QRhiCommandBuffer::IndexUInt16);
8834 cb->setShaderResources();
8835 cb->executeIndirect(icb);
8836 cb->endPass();
8837 \endcode
8838
8839 When the number of commands is itself decided on the device, set
8840 QRhiIndirectCommandBufferBuildInfo::countBuffer instead of working out
8841 \c itemCount on the CPU. See \l{Command counts} below.
8842
8843 \section2 Command counts
8844
8845 Three counts are involved, and they are not the same thing:
8846
8847 \list
8848
8849 \li maxCommandCount() is the capacity. It is fixed at create() time and
8850 sizes whatever native object the backend needs. Neither of the two ways of
8851 providing commands can exceed it; attempting to does not grow the object.
8852
8853 \li recordedCommandCount() is how many draw() or drawIndexed() calls were
8854 made since the last clear(). It only concerns the CPU-recorded case.
8855
8856 \li commandCount() is how many commands QRhiCommandBuffer::executeIndirect()
8857 issues by default. For a CPU-recorded indirect command buffer that is
8858 recordedCommandCount(). Once QRhiCommandBuffer::buildIndirect() has been
8859 called, isGpuBuilt() returns true and commandCount() is the count resolved
8860 from QRhiIndirectCommandBufferBuildInfo::commandCount instead (but note that
8861 that value is the actual command count only when no
8862 \l{QRhiIndirectCommandBufferBuildInfo::}countBuffer is set, is just a
8863 maximum with a counter buffer present).
8864
8865 \endlist
8866
8867 The size of QRhiIndirectCommandBufferBuildInfo::sourceBuffer plays no part
8868 in any of this: no count is ever derived from it. The buffer is written by
8869 the GPU and is free to be larger than the number of commands actually in
8870 it, so leaving QRhiIndirectCommandBufferBuildInfo::commandCount at 0 does
8871 not mean "as many as fit", it means maxCommandCount().
8872
8873 A device-side count, via QRhiIndirectCommandBufferBuildInfo::countBuffer,
8874 narrows the count further when the commands are executed, and can only
8875 reduce it: the value in the count buffer is clamped to what
8876 commandCount() returns.
8877
8878 Either way, the indirect command buffer is fully prepared before the render
8879 pass begins. That is what separates it from the buffer-based
8880 QRhiCommandBuffer::drawIndirect() family, where some backends (Metal above a
8881 certain draw count, and always for the count variants) have to interrupt and
8882 restart the render pass in order to encode the commands. Such an
8883 interruption costs a QRhiRenderBuffer depth-stencil buffer its contents
8884 unless QRhiRenderBuffer::NoTransientBacking was set, and may also be degrading
8885 performance due to having to reload the color buffer values. With
8886 executeIndirect() the question does not arise.
8887
8888 For Metal, the buffer-based API implies (ahove a certain draw count, or
8889 whhen using the count variants) having to run a compute kernel to create an
8890 MTLIndirectCommandBuffer from the Vulkan/Direct 3D/OpenGL style indirect
8891 buffer. With QRhiIndirectCommandBuffer this is not always necessary, because
8892 now, at least when the commands are generated on the CPU side, an
8893 MTLIndirectCommandBuffer can be created and set up normally, by calling
8894 MTLIndirectCommandBuffer's Objective-C API, instead of having to inject a
8895 compute pass. When generating the commands on the GPU, the extra compute
8896 pass is still necessary, but at least it will not interrupt the render pass,
8897 by design, unlike with the direct buffer-based API. Note however that using
8898 MTLIndirectCommandBuffer natively from C++/Objective-C to perform repeated
8899 CPU-side draw call generation can prove to be quite expensive (when
8900 frequently re-recording a larger set of draw commands), compared to the
8901 GPU-side draw command generation, even though that involves an extra encoding
8902 compute pass to "convert" the Vulkan/Direct 3D/OpenGL style indirect buffer
8903 to what Metal prefers. See the next section.
8904
8905 \section2 Recording on the CPU or building on the GPU
8906
8907 The two ways of populating an indirect command buffer are not equivalent in
8908 cost, and the difference grows with the number of commands.
8909
8910 Recording with draw() or drawIndexed() is work proportional to the number of
8911 commands, and it is repeated whenever the contents change. Where that work
8912 lands depends on the backend: those that keep the commands in a buffer
8913 upload it from QRhiResourceUpdateBatch::commitIndirectCommandBuffer(),
8914 whereas Metal encodes each command individually into a native
8915 \c MTLIndirectCommandBuffer, one native call per command, and does so from
8916 QRhiCommandBuffer::executeIndirect().
8917
8918 Either way the result is cached and keyed on the recorded contents, so an
8919 indirect command buffer that is recorded once and then executed unchanged
8920 frame after frame costs nothing beyond the first few frames. That is the
8921 case CPU recording is meant for: a command set that is stable, or changes
8922 rarely, relative to how often it is executed.
8923
8924 The opposite case - many commands, cleared and re-recorded every frame - is
8925 the one to avoid. Regenerating tens of thousands of commands per frame that
8926 way can be an order of magnitude more expensive on Apple platforms than
8927 filling a QRhiBuffer and calling QRhiCommandBuffer::drawIndexedIndirect() on
8928 it, because of the per-command native encoding. When the command set is both
8929 large and regenerated every frame, generate it on the GPU and use
8930 QRhiCommandBuffer::buildIndirect(); the alternative is to stay with the
8931 buffer-based drawIndirect() family and accept the render pass interruption
8932 it may cause (which is still not recommended, even if it would perform
8933 better).
8934
8935 A given QRhiIndirectCommandBuffer holds one kind of command: either
8936 non-indexed draws (\c Draws) or indexed draws (\c IndexedDraws), never a
8937 mix of the two. This mirrors what the underlying APIs can express: a single
8938 indirect draw call always has one command type and one stride.
8939
8940 The requirements are the same as for the indirect draws this stands in for:
8941 QRhi::DrawIndirect has to be supported, the graphics pipeline should be
8942 created with \l{QRhiGraphicsPipeline::UsesIndirectDraws}{UsesIndirectDraws},
8943 and a count buffer additionally needs QRhi::DrawIndirectCount to be
8944 supported.
8945
8946 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8947 for details.
8948
8949 \sa QRhiCommandBuffer::executeIndirect(), QRhiCommandBuffer::drawIndirect()
8950 */
8951
8952/*!
8953 \enum QRhiIndirectCommandBuffer::Type
8954 Specifies the kind of commands an indirect command buffer holds.
8955
8956 \value Draws Non-indexed draw commands, recorded with draw().
8957 \value IndexedDraws Indexed draw commands, recorded with drawIndexed().
8958 */
8959
8960/*!
8961 \fn QRhiIndirectCommandBuffer::Type QRhiIndirectCommandBuffer::type() const
8962 \return the type of commands this indirect command buffer holds.
8963 */
8964
8965/*!
8966 \fn void QRhiIndirectCommandBuffer::setType(Type t)
8967
8968 Sets the command type \a t. The type is normally specified in
8969 QRhi::newIndirectCommandBuffer(), so this function is only used when it has
8970 to be changed. As with other setters, it only takes effect when calling
8971 create().
8972 */
8973
8974/*!
8975 \fn quint32 QRhiIndirectCommandBuffer::maxCommandCount() const
8976 \return the capacity, i.e. the maximum number of commands.
8977 */
8978
8979/*!
8980 \fn void QRhiIndirectCommandBuffer::setMaxCommandCount(quint32 count)
8981
8982 Sets the capacity, the maximum number of commands, to \a count. The
8983 capacity is normally specified in QRhi::newIndirectCommandBuffer(), so this
8984 function is only used when it has to be changed. As with other setters, it
8985 only takes effect when calling create(), which fails when \a count is 0.
8986
8987 The capacity applies regardless of how the commands are going to be
8988 provided: recording them with draw() and drawIndexed() and building them
8989 with QRhiCommandBuffer::buildIndirect() are both bounded by it.
8990
8991 draw() and drawIndexed() ignore, with a warning, any command past the first
8992 \a count ones. QRhiCommandBuffer::buildIndirect() clamps, also with a
8993 warning, when QRhiIndirectCommandBufferBuildInfo::commandCount is larger.
8994
8995 \sa commandCount(), recordedCommandCount()
8996 */
8997
8998/*!
8999 \fn quint32 QRhiIndirectCommandBuffer::recordedCommandCount() const
9000
9001 \return the number of commands recorded with draw() or drawIndexed() since
9002 the last clear().
9003
9004 This is unaffected by QRhiCommandBuffer::buildIndirect(): once the commands
9005 come from the GPU, whatever was recorded on the CPU is ignored. Use
9006 commandCount() to get the number of commands that will actually be
9007 executed.
9008 */
9009
9010/*!
9011 \fn bool QRhiIndirectCommandBuffer::isGpuBuilt() const
9012
9013 \return \c true when QRhiCommandBuffer::buildIndirect() has been called on
9014 this indirect command buffer, meaning its contents come from a QRhiBuffer
9015 instead of from draw() and drawIndexed().
9016
9017 Once true, this stays true until the next create().
9018 */
9019
9020/*!
9021 \fn quint32 QRhiIndirectCommandBuffer::commandCount() const
9022
9023 \return the number of commands QRhiCommandBuffer::executeIndirect() issues
9024 by default.
9025
9026 This is recordedCommandCount() for a CPU-recorded indirect command buffer,
9027 and the count resolved from
9028 QRhiIndirectCommandBufferBuildInfo::commandCount once
9029 QRhiCommandBuffer::buildIndirect() has been called.
9030
9031 A count buffer, if there is one, can reduce the number of draws further at
9032 execution time. This function does not, and cannot, account for that.
9033 */
9034
9035/*!
9036 \fn virtual bool QRhiIndirectCommandBuffer::create() = 0
9037
9038 Creates the corresponding native objects.
9039
9040 Fails when maxCommandCount() is 0.
9041
9042 A given QRhiIndirectCommandBuffer takes its commands either from draw() and
9043 drawIndexed() followed by
9044 QRhiResourceUpdateBatch::commitIndirectCommandBuffer(), or from
9045 QRhiCommandBuffer::buildIndirect(), but not from both. Moving to the latter
9046 is one-way: clear() does not undo it, and neither does a subsequent
9047 commitIndirectCommandBuffer(); isGpuBuilt() stays true and the commands keep
9048 coming from the buffer. Call create() again to get an indirect command
9049 buffer that is populated from the CPU once more.
9050
9051 \note Like with every other QRhi resource, destroy() gives up the contents,
9052 and so create() starts from an empty indirect command buffer:
9053 recordedCommandCount() is 0 afterwards. Setting a different type() or
9054 maxCommandCount() and calling create() again therefore needs the commands
9055 to be recorded again as well.
9056
9057 \return \c true when successful, \c false when a graphics operation failed.
9058 */
9059
9060/*!
9061 \internal
9062 */
9063QRhiIndirectCommandBuffer::QRhiIndirectCommandBuffer(QRhiImplementation *rhi, Type type_,
9064 quint32 maxCommandCount_)
9065 : QRhiResource(rhi),
9066 m_type(type_), m_maxCommandCount(maxCommandCount_)
9067{
9068}
9069
9070/*!
9071 \return the resource type.
9072 */
9073QRhiResource::Type QRhiIndirectCommandBuffer::resourceType() const
9074{
9075 return IndirectCommandBuffer;
9076}
9077
9078/*!
9079 Discards all commands recorded so far.
9080
9081 Can be called at any time, also before create(). The recorded contents only
9082 become visible to the GPU once the object is passed to
9083 QRhiResourceUpdateBatch::commitIndirectCommandBuffer().
9084
9085 This resets recordedCommandCount() to 0. It does not undo a
9086 QRhiCommandBuffer::buildIndirect(): an indirect command buffer that gets
9087 its commands from the GPU keeps doing so, and commandCount() is unchanged.
9088
9089 \note Clearing and re-recording invalidates whatever the backend cached for
9090 the previous contents, so the per-command cost of recording is paid again.
9091 Call this only when the commands actually have to change. See
9092 \l{Recording on the CPU or building on the GPU} for why that matters at high
9093 command counts.
9094 */
9095void QRhiIndirectCommandBuffer::clear()
9096{
9097 m_data.clear();
9098 m_commandCount = 0;
9099 m_generation += 1;
9100}
9101
9102/*!
9103 Records a non-indexed draw command with \a vertexCount, \a instanceCount,
9104 \a firstVertex, and \a firstInstance.
9105
9106 The semantics are the same as QRhiCommandBuffer::draw().
9107
9108 \note Only valid on an indirect command buffer of type Draws.
9109 */
9110void QRhiIndirectCommandBuffer::draw(quint32 vertexCount, quint32 instanceCount,
9111 quint32 firstVertex, quint32 firstInstance)
9112{
9113 if (m_type != Draws) {
9114 qWarning("QRhiIndirectCommandBuffer: draw() on an IndexedDraws indirect command buffer; ignored");
9115 return;
9116 }
9117 if (m_commandCount == m_maxCommandCount) {
9118 qWarning("QRhiIndirectCommandBuffer: maxCommandCount (%u) reached; command ignored",
9119 m_maxCommandCount);
9120 return;
9121 }
9122 const QRhiIndirectDrawCommand cmd = { vertexCount, instanceCount, firstVertex, firstInstance };
9123 m_data.append(reinterpret_cast<const char *>(&cmd), sizeof(cmd));
9124 m_commandCount += 1;
9125 m_generation += 1;
9126}
9127
9128/*!
9129 Records an indexed draw command with \a indexCount, \a instanceCount, \a
9130 firstIndex, \a vertexOffset, and \a firstInstance.
9131
9132 The semantics are the same as QRhiCommandBuffer::drawIndexed().
9133
9134 \note Only valid on an indirect command buffer of type IndexedDraws.
9135 */
9136void QRhiIndirectCommandBuffer::drawIndexed(quint32 indexCount, quint32 instanceCount,
9137 quint32 firstIndex, qint32 vertexOffset,
9138 quint32 firstInstance)
9139{
9140 if (m_type != IndexedDraws) {
9141 qWarning("QRhiIndirectCommandBuffer: drawIndexed() on a Draws indirect command buffer; ignored");
9142 return;
9143 }
9144 if (m_commandCount == m_maxCommandCount) {
9145 qWarning("QRhiIndirectCommandBuffer: maxCommandCount (%u) reached; command ignored",
9146 m_maxCommandCount);
9147 return;
9148 }
9149 const QRhiIndexedIndirectDrawCommand cmd = { indexCount, instanceCount, firstIndex,
9150 vertexOffset, firstInstance };
9151 m_data.append(reinterpret_cast<const char *>(&cmd), sizeof(cmd));
9152 m_commandCount += 1;
9153 m_generation += 1;
9154}
9155
9156/*!
9157 \struct QRhiIndirectCommandBufferBuildInfo
9158 \inmodule QtGuiPrivate
9159 \inheaderfile rhi/qrhi.h
9160 \since 6.13
9161 \brief Describes how to build an indirect command buffer from a QRhiBuffer.
9162
9163 \sa QRhiCommandBuffer::buildIndirect()
9164
9165 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9166 for details.
9167 */
9168
9169/*!
9170 \variable QRhiIndirectCommandBufferBuildInfo::topology
9171
9172 The topology the commands will be drawn with. Must match the topology of the
9173 graphics pipeline that is set when QRhiCommandBuffer::executeIndirect() is
9174 called. Some backends need it in order to build their native indirect
9175 command buffer, and it is not available to them outside of a render pass.
9176*/
9177
9178/*!
9179 \variable QRhiIndirectCommandBufferBuildInfo::sourceBuffer
9180
9181 The buffer holding the QRhiIndirectDrawCommand or
9182 QRhiIndexedIndirectDrawCommand entries. Must have IndirectBuffer usage.
9183
9184 Its size is not used to work out how many commands there are, see
9185 commandCount.
9186*/
9187
9188/*!
9189 \variable QRhiIndirectCommandBufferBuildInfo::sourceBufferOffset
9190*/
9191
9192/*!
9193 \variable QRhiIndirectCommandBufferBuildInfo::commandCount
9194
9195 The number of commands to take from sourceBuffer. This is what
9196 QRhiIndirectCommandBuffer::commandCount() reports afterwards, and so how
9197 many draws QRhiCommandBuffer::executeIndirect() issues by default.
9198
9199 0 means QRhiIndirectCommandBuffer::maxCommandCount(). It does not mean "as
9200 many as fit in sourceBuffer": a buffer written by the GPU can be larger
9201 than the number of commands in it, so no count is ever derived from its
9202 size. A value above QRhiIndirectCommandBuffer::maxCommandCount() is clamped
9203 to it, with a warning.
9204
9205 \note Specifying countBuffer changes what this value means: it stops being
9206 the number of commands and becomes the \e maximum number of commands, with
9207 the device-side count in countBuffer deciding the actual number. Without a
9208 countBuffer, exactly this many commands are executed.
9209*/
9210
9211/*!
9212 \variable QRhiIndirectCommandBufferBuildInfo::stride
9213
9214 The byte distance between two commands in sourceBuffer. 0 means the size of
9215 the corresponding command struct.
9216*/
9217
9218/*!
9219 \variable QRhiIndirectCommandBufferBuildInfo::countBuffer
9220
9221 An optional buffer whose first quint32 holds the number of commands to
9222 execute. Requires QRhi::DrawIndirectCount.
9223
9224 \note Setting this turns commandCount into an upper bound. The device-side
9225 value is clamped to it, so a count buffer can only ever reduce the number
9226 of draws, never raise it.
9227*/
9228
9229/*!
9230 \variable QRhiIndirectCommandBufferBuildInfo::countBufferOffset
9231*/
9232
9233/*!
9234 \variable QRhiIndirectCommandBufferBuildInfo::indexBuffer
9235
9236 The index buffer the commands index into. Required for IndexedDraws.
9237*/
9238
9239/*!
9240 \variable QRhiIndirectCommandBufferBuildInfo::indexBufferOffset
9241*/
9242
9243/*!
9244 \variable QRhiIndirectCommandBufferBuildInfo::indexFormat
9245*/
9246
9248 Type type,
9249 quint32 maxCommandCount)
9251{
9252}
9253
9258
9260{
9261 // Unconditionally, also when there is nothing else to do: like with every
9262 // other resource, destroy() gives up the contents. Carrying a recording
9263 // over into the next create() would not survive a changed maxCommandCount
9264 // or type.
9265 clear();
9266
9267 if (!valid)
9268 return;
9269
9270 delete buffer;
9271 buffer = nullptr;
9272 uploadedGeneration = 0;
9273 buildInfo = {};
9274 m_gpuBuilt = false;
9275 m_gpuBuiltCommandCount = 0;
9276 valid = false;
9277
9278 if (m_rhi)
9279 m_rhi->unregisterResource(this);
9280}
9281
9283{
9284 // Either way the recorded commands go: they may not fit maxCommandCount()
9285 // or match type() anymore.
9286 if (valid)
9287 destroy();
9288 else
9289 clear();
9290
9291 if (!m_maxCommandCount) {
9292 qWarning("QRhiIndirectCommandBuffer: maxCommandCount is 0");
9293 return false;
9294 }
9295
9296 valid = true;
9297 m_rhi->registerResource(this);
9298 return true;
9299}
9300
9302{
9303 // m_gpuBuilt: the commands come from the source buffer from now on, so
9304 // there is nothing to upload, as documented for commitIndirectCommandBuffer().
9305 if (!valid || m_gpuBuilt || m_data.isEmpty() || uploadedGeneration == m_generation)
9306 return;
9307
9308 if (!buffer) {
9309 const quint32 commandSize = m_type == IndexedDraws ? sizeof(QRhiIndexedIndirectDrawCommand)
9310 : sizeof(QRhiIndirectDrawCommand);
9311 buffer = m_rhi->createBuffer(QRhiBuffer::Static, QRhiBuffer::IndirectBuffer,
9312 m_maxCommandCount * commandSize);
9313 if (!buffer || !buffer->create()) {
9314 delete buffer;
9315 buffer = nullptr;
9316 return;
9317 }
9318 }
9319
9320 u->uploadStaticBuffer(buffer, 0, quint32(m_data.size()), m_data.constData());
9321 uploadedGeneration = m_generation;
9322}
9323
9324void QRhiBufferBackedIndirectCommandBuffer::build(const QRhiIndirectCommandBufferBuildInfo &info)
9325{
9326 buildInfo = info;
9327 quint32 count = info.commandCount ? info.commandCount : m_maxCommandCount;
9328 if (count > m_maxCommandCount) {
9329 qWarning("QRhiIndirectCommandBuffer: buildIndirect() with commandCount %u exceeds "
9330 "maxCommandCount %u; clamping", count, m_maxCommandCount);
9331 count = m_maxCommandCount;
9332 }
9333 m_gpuBuilt = true;
9334 m_gpuBuiltCommandCount = count;
9335}
9336
9338 quint32 firstCommand,
9339 quint32 commandCount)
9340{
9341 const bool indexed = m_type == IndexedDraws;
9342 const quint32 canonicalStride = m_type == IndexedDraws ? sizeof(QRhiIndexedIndirectDrawCommand)
9343 : sizeof(QRhiIndirectDrawCommand);
9344
9345 if (m_gpuBuilt) {
9346 const quint32 stride = buildInfo.stride ? buildInfo.stride : canonicalStride;
9347 const quint32 available = m_gpuBuiltCommandCount > firstCommand
9348 ? m_gpuBuiltCommandCount - firstCommand : 0;
9349 const quint32 count = qMin(commandCount, available);
9350 if (!count)
9351 return;
9352 const quint32 offset = buildInfo.sourceBufferOffset + firstCommand * stride;
9353 if (buildInfo.countBuffer) {
9354 // Note that a non-zero firstCommand shifts the window, but the
9355 // device-side count is still relative to the start of that window.
9356 if (indexed) {
9357 cb->drawIndexedIndirectCount(buildInfo.sourceBuffer, offset,
9358 buildInfo.countBuffer, buildInfo.countBufferOffset,
9359 count, stride);
9360 } else {
9361 cb->drawIndirectCount(buildInfo.sourceBuffer, offset,
9362 buildInfo.countBuffer, buildInfo.countBufferOffset,
9363 count, stride);
9364 }
9365 } else {
9366 if (indexed)
9367 cb->drawIndexedIndirect(buildInfo.sourceBuffer, offset, count, stride);
9368 else
9369 cb->drawIndirect(buildInfo.sourceBuffer, offset, count, stride);
9370 }
9371 return;
9372 }
9373
9374 if (!buffer) {
9375 // Metal encodes on the spot in executeIndirect() and so needs no
9376 // commit. Everywhere else a missing one means drawing nothing.
9377 if (m_commandCount) {
9378 qWarning("QRhiIndirectCommandBuffer: %u command(s) recorded but never flushed with "
9379 "QRhiResourceUpdateBatch::commitIndirectCommandBuffer(); nothing to draw",
9380 m_commandCount);
9381 }
9382 return;
9383 }
9384 if (!m_commandCount)
9385 return;
9386
9387 const quint32 available = m_commandCount > firstCommand ? m_commandCount - firstCommand : 0;
9388 const quint32 count = qMin(commandCount, available);
9389 if (!count)
9390 return;
9391
9392 const quint32 offset = firstCommand * canonicalStride;
9393 if (indexed)
9394 cb->drawIndexedIndirect(buffer, offset, count, canonicalStride);
9395 else
9396 cb->drawIndirect(buffer, offset, count, canonicalStride);
9397}
9398
9399QRhiIndirectCommandBuffer *QRhiImplementation::createIndirectCommandBuffer(QRhiIndirectCommandBuffer::Type type,
9400 quint32 maxCommandCount)
9401{
9402 return new QRhiBufferBackedIndirectCommandBuffer(this, type, maxCommandCount);
9403}
9404
9405void QRhiImplementation::buildIndirect(QRhiCommandBuffer *cb, QRhiIndirectCommandBuffer *icb,
9406 const QRhiIndirectCommandBufferBuildInfo &info)
9407{
9408 Q_UNUSED(cb);
9409 static_cast<QRhiBufferBackedIndirectCommandBuffer *>(icb)->build(info);
9410}
9411
9412void QRhiImplementation::executeIndirect(QRhiCommandBuffer *cb, QRhiIndirectCommandBuffer *icb,
9413 quint32 firstCommand, quint32 commandCount)
9414{
9415 static_cast<QRhiBufferBackedIndirectCommandBuffer *>(icb)->execute(cb, firstCommand, commandCount);
9416}
9417
9418void QRhiImplementation::commitIndirectCommandBuffer(QRhiResourceUpdateBatch *u,
9419 QRhiIndirectCommandBuffer *icb)
9420{
9421 static_cast<QRhiBufferBackedIndirectCommandBuffer *>(icb)->enqueueUpload(u);
9422}
9423
9424/*!
9425 \class QRhiCommandBuffer
9426 \inmodule QtGuiPrivate
9427 \inheaderfile rhi/qrhi.h
9428 \since 6.6
9429 \brief Command buffer resource.
9430
9431 Not creatable by applications at the moment. The only ways to obtain a
9432 valid QRhiCommandBuffer are to get it from the targeted swapchain via
9433 QRhiSwapChain::currentFrameCommandBuffer(), or, in case of rendering
9434 completely offscreen, initializing one via QRhi::beginOffscreenFrame().
9435
9436 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9437 for details.
9438 */
9439
9440/*!
9441 \enum QRhiCommandBuffer::IndexFormat
9442 Specifies the index data type
9443
9444 \value IndexUInt16 Unsigned 16-bit (quint16)
9445 \value IndexUInt32 Unsigned 32-bit (quint32)
9446 */
9447
9448/*!
9449 \enum QRhiCommandBuffer::BeginPassFlag
9450 Flag values for QRhi::beginPass()
9451
9452 \value ExternalContent Specifies that there will be a call to
9453 QRhiCommandBuffer::beginExternal() in this pass. Some backends, Vulkan in
9454 particular, will fail if this flag is not set and beginExternal() is still
9455 called.
9456
9457 \value DoNotTrackResourcesForCompute Specifies that there is no need to
9458 track resources used in this pass if the only purpose of such tracking is
9459 to generate barriers for compute. Implies that there are no compute passes
9460 in the frame. This is an optimization hint that may be taken into account
9461 by certain backends, OpenGL in particular, allowing them to skip certain
9462 operations. When this flag is set for a render pass in a frame, calling
9463 \l{QRhiCommandBuffer::beginComputePass()}{beginComputePass()} in that frame
9464 may lead to unexpected behavior, depending on the resource dependencies
9465 between the render and compute passes.
9466 */
9467
9468/*!
9469 \typedef QRhiCommandBuffer::DynamicOffset
9470
9471 Synonym for std::pair<int, quint32>. The first entry is the binding, the second
9472 is the offset in the buffer.
9473*/
9474
9475/*!
9476 \typedef QRhiCommandBuffer::VertexInput
9477
9478 Synonym for std::pair<QRhiBuffer *, quint32>. The second entry is an offset in
9479 the buffer specified by the first.
9480*/
9481
9482/*!
9483 \internal
9484 */
9485QRhiCommandBuffer::QRhiCommandBuffer(QRhiImplementation *rhi)
9486 : QRhiResource(rhi)
9487{
9488}
9489
9490/*!
9491 \return the resource type.
9492 */
9493QRhiResource::Type QRhiCommandBuffer::resourceType() const
9494{
9495 return CommandBuffer;
9496}
9497
9498static const char *resourceTypeStr(const QRhiResource *res)
9499{
9500 switch (res->resourceType()) {
9501 case QRhiResource::Buffer:
9502 return "Buffer";
9503 case QRhiResource::Texture:
9504 return "Texture";
9505 case QRhiResource::Sampler:
9506 return "Sampler";
9507 case QRhiResource::RenderBuffer:
9508 return "RenderBuffer";
9509 case QRhiResource::RenderPassDescriptor:
9510 return "RenderPassDescriptor";
9511 case QRhiResource::SwapChainRenderTarget:
9512 return "SwapChainRenderTarget";
9513 case QRhiResource::TextureRenderTarget:
9514 return "TextureRenderTarget";
9515 case QRhiResource::ShaderResourceBindings:
9516 return "ShaderResourceBindings";
9517 case QRhiResource::GraphicsPipeline:
9518 return "GraphicsPipeline";
9519 case QRhiResource::SwapChain:
9520 return "SwapChain";
9521 case QRhiResource::ComputePipeline:
9522 return "ComputePipeline";
9523 case QRhiResource::CommandBuffer:
9524 return "CommandBuffer";
9525 case QRhiResource::ShadingRateMap:
9526 return "ShadingRateMap";
9527 case QRhiResource::IndirectCommandBuffer:
9528 return "IndirectCommandBuffer";
9529 }
9530
9531 Q_UNREACHABLE_RETURN("");
9532}
9533
9534QRhiImplementation::~QRhiImplementation()
9535{
9536 qDeleteAll(resUpdPool);
9537
9538 // Be nice and show something about leaked stuff. Though we may not get
9539 // this far with some backends where the allocator or the api may check
9540 // and freak out for unfreed graphics objects in the derived dtor already.
9541#ifndef QT_NO_DEBUG
9542 // debug builds: just do it always
9543 static bool leakCheck = true;
9544#else
9545 // release builds: opt-in
9546 static bool leakCheck = qEnvironmentVariableIntValue("QT_RHI_LEAK_CHECK");
9547#endif
9548 if (!resources.isEmpty()) {
9549 if (leakCheck) {
9550 qWarning("QRhi %p going down with %d unreleased resources that own native graphics objects. This is not nice.",
9551 q, int(resources.size()));
9552 }
9553 for (auto it = resources.cbegin(), end = resources.cend(); it != end; ++it) {
9554 QRhiResource *res = it.key();
9555 const bool ownsNativeResources = it.value();
9556 if (leakCheck && ownsNativeResources)
9557 qWarning(" %s resource %p (%s)", resourceTypeStr(res), res, res->m_objectName.constData());
9558
9559 // Null out the resource's rhi pointer. This is why it makes sense to do null
9560 // checks in the destroy() implementations of the various resource types. It
9561 // allows to survive in bad applications that somehow manage to destroy a
9562 // resource of a QRhi after the QRhi itself.
9563 res->m_rhi = nullptr;
9564 }
9565 }
9566}
9567
9568bool QRhiImplementation::isCompressedFormat(QRhiTexture::Format format) const
9569{
9570 return (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
9571 || (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
9572 || (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12);
9573}
9574
9575bool QRhiImplementation::compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
9576 quint32 *bpl, quint32 *byteSize,
9577 QSize *blockDim) const
9578{
9579 int xdim = 4;
9580 int ydim = 4;
9581 quint32 blockSize = 0;
9582
9583 switch (format) {
9584 case QRhiTexture::BC1:
9585 blockSize = 8;
9586 break;
9587 case QRhiTexture::BC2:
9588 blockSize = 16;
9589 break;
9590 case QRhiTexture::BC3:
9591 blockSize = 16;
9592 break;
9593 case QRhiTexture::BC4:
9594 blockSize = 8;
9595 break;
9596 case QRhiTexture::BC5:
9597 blockSize = 16;
9598 break;
9599 case QRhiTexture::BC6H:
9600 blockSize = 16;
9601 break;
9602 case QRhiTexture::BC7:
9603 blockSize = 16;
9604 break;
9605
9606 case QRhiTexture::ETC2_RGB8:
9607 blockSize = 8;
9608 break;
9609 case QRhiTexture::ETC2_RGB8A1:
9610 blockSize = 8;
9611 break;
9612 case QRhiTexture::ETC2_RGBA8:
9613 blockSize = 16;
9614 break;
9615
9616 case QRhiTexture::ASTC_4x4:
9617 blockSize = 16;
9618 break;
9619 case QRhiTexture::ASTC_5x4:
9620 blockSize = 16;
9621 xdim = 5;
9622 break;
9623 case QRhiTexture::ASTC_5x5:
9624 blockSize = 16;
9625 xdim = ydim = 5;
9626 break;
9627 case QRhiTexture::ASTC_6x5:
9628 blockSize = 16;
9629 xdim = 6;
9630 ydim = 5;
9631 break;
9632 case QRhiTexture::ASTC_6x6:
9633 blockSize = 16;
9634 xdim = ydim = 6;
9635 break;
9636 case QRhiTexture::ASTC_8x5:
9637 blockSize = 16;
9638 xdim = 8;
9639 ydim = 5;
9640 break;
9641 case QRhiTexture::ASTC_8x6:
9642 blockSize = 16;
9643 xdim = 8;
9644 ydim = 6;
9645 break;
9646 case QRhiTexture::ASTC_8x8:
9647 blockSize = 16;
9648 xdim = ydim = 8;
9649 break;
9650 case QRhiTexture::ASTC_10x5:
9651 blockSize = 16;
9652 xdim = 10;
9653 ydim = 5;
9654 break;
9655 case QRhiTexture::ASTC_10x6:
9656 blockSize = 16;
9657 xdim = 10;
9658 ydim = 6;
9659 break;
9660 case QRhiTexture::ASTC_10x8:
9661 blockSize = 16;
9662 xdim = 10;
9663 ydim = 8;
9664 break;
9665 case QRhiTexture::ASTC_10x10:
9666 blockSize = 16;
9667 xdim = ydim = 10;
9668 break;
9669 case QRhiTexture::ASTC_12x10:
9670 blockSize = 16;
9671 xdim = 12;
9672 ydim = 10;
9673 break;
9674 case QRhiTexture::ASTC_12x12:
9675 blockSize = 16;
9676 xdim = ydim = 12;
9677 break;
9678
9679 default:
9680 Q_UNREACHABLE();
9681 break;
9682 }
9683
9684 const quint32 wblocks = quint32((qint64(qMax(0, size.width())) + xdim - 1) / xdim);
9685 const quint32 hblocks = quint32((qint64(qMax(0, size.height())) + ydim - 1) / ydim);
9686
9687 if (blockDim)
9688 *blockDim = QSize(xdim, ydim);
9689
9690 // Compute in 64-bit, as safety for extreme geometry that would not fit.
9691 // wblocks and hblocks are at most 2^29 and blockSize at most 16.
9692 const quint64 bytesPerLine = quint64(wblocks) * quint64(blockSize);
9693 const quint64 totalSize = quint64(wblocks) * quint64(hblocks) * quint64(blockSize);
9694 if (bytesPerLine > std::numeric_limits<quint32>::max()
9695 || totalSize > std::numeric_limits<quint32>::max())
9696 {
9697 qWarning("Compressed texture of size %dx%d with format %d has a byte size of %llu "
9698 "which is too large to be handled",
9699 size.width(), size.height(), int(format), totalSize);
9700 if (bpl)
9701 *bpl = 0;
9702 if (byteSize)
9703 *byteSize = 0;
9704 return false;
9705 }
9706
9707 if (bpl)
9708 *bpl = quint32(bytesPerLine);
9709 if (byteSize)
9710 *byteSize = quint32(totalSize);
9711
9712 return true;
9713}
9714
9715bool QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSize &size,
9716 quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const
9717{
9718 if (isCompressedFormat(format))
9719 return compressedFormatInfo(format, size, bpl, byteSize, nullptr);
9720
9721 quint32 bpc = 0;
9722 switch (format) {
9723 case QRhiTexture::RGBA8:
9724 bpc = 4;
9725 break;
9726 case QRhiTexture::BGRA8:
9727 bpc = 4;
9728 break;
9729 case QRhiTexture::R8:
9730 bpc = 1;
9731 break;
9732 case QRhiTexture::RG8:
9733 bpc = 2;
9734 break;
9735 case QRhiTexture::R16:
9736 bpc = 2;
9737 break;
9738 case QRhiTexture::RG16:
9739 bpc = 4;
9740 break;
9741 case QRhiTexture::RED_OR_ALPHA8:
9742 bpc = 1;
9743 break;
9744
9745 case QRhiTexture::RGBA16F:
9746 bpc = 8;
9747 break;
9748 case QRhiTexture::RGBA32F:
9749 bpc = 16;
9750 break;
9751 case QRhiTexture::R16F:
9752 bpc = 2;
9753 break;
9754 case QRhiTexture::R32F:
9755 bpc = 4;
9756 break;
9757
9758 case QRhiTexture::RGB10A2:
9759 bpc = 4;
9760 break;
9761
9762 case QRhiTexture::D16:
9763 bpc = 2;
9764 break;
9765 case QRhiTexture::D24:
9766 case QRhiTexture::D24S8:
9767 case QRhiTexture::D32F:
9768 bpc = 4;
9769 break;
9770
9771 case QRhiTexture::D32FS8:
9772 bpc = 8;
9773 break;
9774
9775 case QRhiTexture::R8SI:
9776 case QRhiTexture::R8UI:
9777 bpc = 1;
9778 break;
9779 case QRhiTexture::R32SI:
9780 case QRhiTexture::R32UI:
9781 bpc = 4;
9782 break;
9783 case QRhiTexture::RG32SI:
9784 case QRhiTexture::RG32UI:
9785 bpc = 8;
9786 break;
9787 case QRhiTexture::RGBA32SI:
9788 case QRhiTexture::RGBA32UI:
9789 bpc = 16;
9790 break;
9791
9792 default:
9793 Q_UNREACHABLE();
9794 break;
9795 }
9796
9797 const quint32 width = uint(qMax(0, size.width()));
9798 const quint32 height = uint(qMax(0, size.height()));
9799
9800 if (bytesPerPixel)
9801 *bytesPerPixel = bpc;
9802
9803 // Compute in 64-bit, as safety for extreme geometry that would not fit.
9804 const quint64 bytesPerLine = quint64(width) * quint64(bpc);
9805 const quint64 pixelCount = quint64(width) * quint64(height);
9806 if (bytesPerLine > std::numeric_limits<quint32>::max()
9807 || pixelCount > std::numeric_limits<quint32>::max() / bpc)
9808 {
9809 qWarning("Texture of size %dx%d with format %d has a byte size "
9810 "which is too large to be handled",
9811 size.width(), size.height(), int(format));
9812 if (bpl)
9813 *bpl = 0;
9814 if (byteSize)
9815 *byteSize = 0;
9816 return false;
9817 }
9818
9819 if (bpl)
9820 *bpl = quint32(bytesPerLine);
9821 if (byteSize)
9822 *byteSize = quint32(pixelCount * quint64(bpc));
9823
9824 return true;
9825}
9826
9827bool QRhiImplementation::isStencilSupportingFormat(QRhiTexture::Format format) const
9828{
9829 switch (format) {
9830 case QRhiTexture::D24S8:
9831 case QRhiTexture::D32FS8:
9832 return true;
9833 default:
9834 break;
9835 }
9836 return false;
9837}
9838
9839bool QRhiImplementation::sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps)
9840{
9841 if (ps->cbeginShaderStages() == ps->cendShaderStages()) {
9842 qWarning("Cannot build a graphics pipeline without any stages");
9843 return false;
9844 }
9845
9846 bool hasVertexStage = false;
9847 for (auto it = ps->cbeginShaderStages(), itEnd = ps->cendShaderStages(); it != itEnd; ++it) {
9848 if (!it->shader().isValid()) {
9849 qWarning("Empty shader passed to graphics pipeline");
9850 return false;
9851 }
9852 if (it->type() == QRhiShaderStage::Vertex)
9853 hasVertexStage = true;
9854 }
9855 if (!hasVertexStage) {
9856 qWarning("Cannot build a graphics pipeline without a vertex stage");
9857 return false;
9858 }
9859
9860 if (!ps->renderPassDescriptor()) {
9861 qWarning("Cannot build a graphics pipeline without a QRhiRenderPassDescriptor");
9862 return false;
9863 }
9864
9865 if (!ps->shaderResourceBindings()) {
9866 qWarning("Cannot build a graphics pipeline without QRhiShaderResourceBindings");
9867 return false;
9868 }
9869
9870 return true;
9871}
9872
9873bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb)
9874{
9875#ifndef QT_NO_DEBUG
9876 bool bindingsOk = true;
9877 const int CHECKED_BINDINGS_COUNT = 64;
9878 bool bindingSeen[CHECKED_BINDINGS_COUNT] = {};
9879 for (auto it = srb->cbeginBindings(), end = srb->cendBindings(); it != end; ++it) {
9880 const int binding = shaderResourceBindingData(*it)->binding;
9881 if (binding >= CHECKED_BINDINGS_COUNT)
9882 continue;
9883 if (binding < 0) {
9884 qWarning("Invalid binding number %d", binding);
9885 bindingsOk = false;
9886 continue;
9887 }
9888 switch (shaderResourceBindingData(*it)->type) {
9889 case QRhiShaderResourceBinding::UniformBuffer:
9890 if (!bindingSeen[binding]) {
9891 bindingSeen[binding] = true;
9892 } else {
9893 qWarning("Uniform buffer duplicates an existing binding number %d", binding);
9894 bindingsOk = false;
9895 }
9896 break;
9897 case QRhiShaderResourceBinding::SampledTexture:
9898 if (!bindingSeen[binding]) {
9899 bindingSeen[binding] = true;
9900 } else {
9901 qWarning("Combined image sampler duplicates an existing binding number %d", binding);
9902 bindingsOk = false;
9903 }
9904 break;
9905 case QRhiShaderResourceBinding::Texture:
9906 if (!bindingSeen[binding]) {
9907 bindingSeen[binding] = true;
9908 } else {
9909 qWarning("Texture duplicates an existing binding number %d", binding);
9910 bindingsOk = false;
9911 }
9912 break;
9913 case QRhiShaderResourceBinding::Sampler:
9914 if (!bindingSeen[binding]) {
9915 bindingSeen[binding] = true;
9916 } else {
9917 qWarning("Sampler duplicates an existing binding number %d", binding);
9918 bindingsOk = false;
9919 }
9920 break;
9921 case QRhiShaderResourceBinding::ImageLoad:
9922 case QRhiShaderResourceBinding::ImageStore:
9923 case QRhiShaderResourceBinding::ImageLoadStore:
9924 if (!bindingSeen[binding]) {
9925 bindingSeen[binding] = true;
9926 } else {
9927 qWarning("Image duplicates an existing binding number %d", binding);
9928 bindingsOk = false;
9929 }
9930 break;
9931 case QRhiShaderResourceBinding::BufferLoad:
9932 case QRhiShaderResourceBinding::BufferStore:
9933 case QRhiShaderResourceBinding::BufferLoadStore:
9934 if (!bindingSeen[binding]) {
9935 bindingSeen[binding] = true;
9936 } else {
9937 qWarning("Buffer duplicates an existing binding number %d", binding);
9938 bindingsOk = false;
9939 }
9940 break;
9941 default:
9942 qWarning("Unknown binding type %d", int(shaderResourceBindingData(*it)->type));
9943 bindingsOk = false;
9944 break;
9945 }
9946 }
9947
9948 if (!bindingsOk) {
9949 qWarning() << *srb;
9950 return false;
9951 }
9952#else
9953 Q_UNUSED(srb);
9954#endif
9955 return true;
9956}
9957
9958bool QRhiImplementation::sanityCheckResourceOwnership(QRhiResource *maybeResource)
9959{
9960 if (maybeResource == nullptr || maybeResource->m_rhi == nullptr)
9961 return true;
9962
9963 if (maybeResource->m_rhi->q != q) {
9964 qWarning("%s %p (%s) belongs to QRhi %p, but client code attempted to use it with QRhi %p. This is wrong.",
9965 resourceTypeStr(maybeResource),
9966 maybeResource,
9967 maybeResource->m_objectName.constData(),
9968 maybeResource->m_rhi->q,
9969 q);
9970 return false;
9971 }
9972
9973 return true;
9974}
9975
9976int QRhiImplementation::effectiveSampleCount(int sampleCount) const
9977{
9978 // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
9979 const int s = qBound(1, sampleCount, 64);
9980 const QList<int> supported = supportedSampleCounts();
9981 int result = 1;
9982
9983 // Stay compatible with Qt 5 in that requesting an unsupported sample count
9984 // is not an error (although we still do a categorized debug print about
9985 // this), and rather a supported value, preferably a close one, not just 1,
9986 // is used instead. This is actually deviating from Qt 5 as that performs a
9987 // clamping only and does not handle cases such as when sample count 2 is
9988 // not supported but 4 is. (OpenGL handles things like that gracefully,
9989 // other APIs may not, so improve this by picking the next largest, or in
9990 // absence of that, the largest value; this with the goal to not reduce
9991 // quality by rather picking a larger-than-requested value than a smaller one)
9992
9993 for (int i = 0, ie = supported.count(); i != ie; ++i) {
9994 // assumes the 'supported' list is sorted
9995 if (supported[i] >= s) {
9996 result = supported[i];
9997 break;
9998 }
9999 }
10000
10001 if (result != s) {
10002 if (result == 1 && !supported.isEmpty())
10003 result = supported.last();
10004 qCDebug(QRHI_LOG_INFO, "Attempted to set unsupported sample count %d, using %d instead",
10005 sampleCount, result);
10006 }
10007
10008 return result;
10009}
10010
10011/*!
10012 \internal
10013 */
10014QRhi::QRhi()
10015{
10016}
10017
10018/*!
10019 Destructor. Destroys the backend and releases resources.
10020 */
10021QRhi::~QRhi()
10022{
10023 if (!d)
10024 return;
10025
10026 if (qrhiDebugHooks.rhiAboutToBeDestroyed)
10027 qrhiDebugHooks.rhiAboutToBeDestroyed(d);
10028
10029 d->runCleanup();
10030
10031 qDeleteAll(d->pendingDeleteResources);
10032 d->pendingDeleteResources.clear();
10033
10034 d->destroy();
10035 delete d;
10036}
10037
10038QRhiImplementation *QRhiImplementation::newInstance(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *importDevice)
10039{
10040 QRhiImplementation *d = nullptr;
10041
10042 switch (impl) {
10043 case QRhi::Null:
10044 d = new QRhiNull(static_cast<QRhiNullInitParams *>(params));
10045 break;
10046 case QRhi::Vulkan:
10047#if QT_CONFIG(vulkan)
10048 d = new QRhiVulkan(static_cast<QRhiVulkanInitParams *>(params),
10049 static_cast<QRhiVulkanNativeHandles *>(importDevice));
10050 break;
10051#else
10052 Q_UNUSED(importDevice);
10053 qWarning("This build of Qt has no Vulkan support");
10054 break;
10055#endif
10056 case QRhi::OpenGLES2:
10057#ifndef QT_NO_OPENGL
10058 d = new QRhiGles2(static_cast<QRhiGles2InitParams *>(params),
10059 static_cast<QRhiGles2NativeHandles *>(importDevice));
10060 break;
10061#else
10062 qWarning("This build of Qt has no OpenGL support");
10063 break;
10064#endif
10065 case QRhi::D3D11:
10066#ifdef Q_OS_WIN
10067 d = new QRhiD3D11(static_cast<QRhiD3D11InitParams *>(params),
10068 static_cast<QRhiD3D11NativeHandles *>(importDevice));
10069 break;
10070#else
10071 qWarning("This platform has no Direct3D 11 support");
10072 break;
10073#endif
10074 case QRhi::Metal:
10075#if QT_CONFIG(metal)
10076 d = new QRhiMetal(static_cast<QRhiMetalInitParams *>(params),
10077 static_cast<QRhiMetalNativeHandles *>(importDevice));
10078 break;
10079#else
10080 qWarning("This platform has no Metal support");
10081 break;
10082#endif
10083 case QRhi::D3D12:
10084#ifdef Q_OS_WIN
10085#ifdef QRHI_D3D12_AVAILABLE
10086 d = new QRhiD3D12(static_cast<QRhiD3D12InitParams *>(params),
10087 static_cast<QRhiD3D12NativeHandles *>(importDevice));
10088 break;
10089#else
10090 qWarning("Qt was built without Direct3D 12 support. "
10091 "This is likely due to having ancient SDK headers (such as d3d12.h) in the Qt build environment. "
10092 "Rebuild Qt with an SDK supporting D3D12 features introduced in Windows 10 version 1703, "
10093 "or use an MSVC build as those typically are built with more up-to-date SDKs.");
10094 break;
10095#endif
10096#else
10097 qWarning("This platform has no Direct3D 12 support");
10098 break;
10099#endif
10100 }
10101
10102 return d;
10103}
10104
10105void QRhiImplementation::prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags, QRhiAdapter *adapter)
10106{
10107 q = rhi;
10108
10109 debugMarkers = flags.testFlag(QRhi::EnableDebugMarkers);
10110 timestamps = flags.testFlag(QRhi::EnableTimestamps);
10111
10112 implType = impl;
10113 implThread = QThread::currentThread();
10114
10115 requestedRhiAdapter = adapter;
10116}
10117
10118QRhi::AdapterList QRhiImplementation::enumerateAdaptersBeforeCreate(QRhiNativeHandles *) const
10119{
10120 return {};
10121}
10122
10123/*!
10124 \overload
10125
10126 Equivalent to create(\a impl, \a params, \a flags, \a importDevice, \c nullptr).
10127 */
10128QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice)
10129{
10130 return create(impl, params, flags, importDevice, nullptr);
10131}
10132
10133/*!
10134 \return a new QRhi instance with a backend for the graphics API specified
10135 by \a impl with the specified \a flags. \return \c nullptr if the
10136 function fails.
10137
10138 \a params must point to an instance of one of the backend-specific
10139 subclasses of QRhiInitParams, such as, QRhiVulkanInitParams,
10140 QRhiMetalInitParams, QRhiD3D11InitParams, QRhiD3D12InitParams,
10141 QRhiGles2InitParams. See these classes for examples on creating a QRhi.
10142
10143 QRhi by design does not implement any fallback logic: if the specified API
10144 cannot be initialized, create() will fail, with warnings printed on the
10145 debug output by the backends. The clients of QRhi, for example Qt Quick,
10146 may however provide additional logic that allow falling back to an API
10147 different than what was requested, depending on the platform. If the
10148 intention is just to test if initialization would succeed when calling
10149 create() at later point, it is preferable to use probe() instead of
10150 create(), because with some backends probing can be implemented in a more
10151 lightweight manner as opposed to create(), which performs full
10152 initialization of the infrastructure and is wasteful if that QRhi instance
10153 is then thrown immediately away.
10154
10155 \a importDevice allows using an already existing graphics device, without
10156 QRhi creating its own. When not null, this parameter must point to an
10157 instance of one of the subclasses of QRhiNativeHandles:
10158 QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles,
10159 QRhiMetalNativeHandles, QRhiGles2NativeHandles. The exact details and
10160 semantics depend on the backand and the underlying graphics API.
10161
10162 Specifying a QRhiAdapter in \a adapter offers a transparent, cross-API
10163 alternative to passing in a \c VkPhysicalDevice via QRhiVulkanNativeHandles,
10164 or an adapter LUID via QRhiD3D12NativeHandles. The ownership of \a adapter
10165 is not taken. See enumerateAdapters() for more information on this approach.
10166
10167 \note \a importDevice and \a adapter cannot be both specified.
10168
10169 \sa probe()
10170 */
10171QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice, QRhiAdapter *adapter)
10172{
10173 if (adapter && importDevice)
10174 qWarning("adapter and importDevice should not both be non-null in QRhi::create()");
10175
10176 std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, importDevice));
10177 if (!rd)
10178 return nullptr;
10179
10180 std::unique_ptr<QRhi> r(new QRhi);
10181 r->d = rd.release();
10182 r->d->prepareForCreate(r.get(), impl, flags, adapter);
10183 if (!r->d->create(flags))
10184 return nullptr;
10185
10186 return r.release();
10187}
10188
10189/*!
10190 \return true if create() can be expected to succeed when called the given
10191 \a impl and \a params.
10192
10193 For some backends this is equivalent to calling create(), checking its
10194 return value, and then destroying the resulting QRhi.
10195
10196 For others, in particular with Metal, there may be a specific probing
10197 implementation, which allows testing in a more lightweight manner without
10198 polluting the debug output with warnings upon failures.
10199
10200 \sa create()
10201 */
10202bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)
10203{
10204 bool ok = false;
10205
10206 // The only place currently where this makes sense is Metal, where the API
10207 // is simple enough so that a special probing function - doing nothing but
10208 // a MTLCreateSystemDefaultDevice - is reasonable. Elsewhere, just call
10209 // create() and then drop the result.
10210
10211 if (impl == Metal) {
10212#if QT_CONFIG(metal)
10213 ok = QRhiMetal::probe(static_cast<QRhiMetalInitParams *>(params));
10214#endif
10215 } else {
10216 QRhi *rhi = create(impl, params);
10217 ok = rhi != nullptr;
10218 delete rhi;
10219 }
10220 return ok;
10221}
10222
10223/*!
10224 \typedef QRhi::AdapterList
10225 \relates QRhi
10226 \since 6.10
10227
10228 Synonym for QVector<QRhiAdapter *>.
10229*/
10230
10231/*!
10232 \return the list of adapters (physical devices) present, or an empty list
10233 when such control is not available with a given graphics API.
10234
10235 Backends where such level of control is not available, the returned list is
10236 always empty. Thus an empty list does not indicate there are no graphics
10237 devices in the system, but that fine-grained control over selecting which
10238 one to use is not available.
10239
10240 Backends for Direct 3D 11, Direct 3D 12, and Vulkan can be expected to fully
10241 support enumerating adapters. Others may not. The backend is specified by \a
10242 impl. A QRhiAdapter returned from this function must only be used in a
10243 create() call with the same \a impl. Some underlying APIs may present
10244 further limitations, with Vulkan in particular the QRhiAdapter is specified
10245 to the QVulkanInstance (\c VkInstance).
10246
10247 The caller is expected to destroy the QRhiAdapter objects in the list. Apart
10248 from querying \l{QRhiAdapter::}{info()}, the only purpose of these objects is
10249 to be passed on to create(), or the corresponding functions in higher layers
10250 such as Qt Quick.
10251
10252 The following snippet, written specifically for Vulkan, shows how to
10253 enumerate the available physical devices and request to create a QRhi for
10254 the chosen one. This in practice is equivalent to passing in a \c
10255 VkPhysicalDevice via a QRhiVulkanNativeHandles to create(), but it involves
10256 less API-specific code on the application side:
10257
10258 \code
10259 QRhiVulkanInitParams initParams;
10260 initParams.inst = &vulkanInstance;
10261 QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::Vulkan, &initParams);
10262 QRhiAdapter *chosenAdapter = nullptr;
10263 for (QRhiAdapter *adapter : adapters) {
10264 if (looksGood(adapter->info())) {
10265 chosenAdapter = adapter;
10266 break;
10267 }
10268 }
10269 QRhi *rhi = QRhi::create(QRhi::Vulkan, &initParams, {}, nullptr, chosenAdapter);
10270 qDeleteAll(adapters);
10271 \endcode
10272
10273 Passing in \a params is required due to some of the underlying graphics
10274 APIs' design. With Vulkan in particular, the QVulkanInstance must be
10275 provided, since enumerating is not possible without it. Other fields in the
10276 backend-specific \a params will not actually be used by this function.
10277
10278 \a nativeHandles is optional. When specified, it must be a valid
10279 QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, or QRhiVulkanNativeHandles,
10280 similarly to create(). However, unlike create(), only the physical device
10281 (in case of Vulkan) or the adapter LUID (in case of D3D) fields are used,
10282 all other fields are ignored. This can be used the restrict the results to a
10283 given adapter. The returned list will contain 1 or 0 elements in this case.
10284
10285 Note how in the previous code snippet the looksGood() function
10286 implementation cannot perform any platform-specific filtering based on the
10287 true adapter / physical device identity, such as the adapter LUID on Windows
10288 or the VkPhysicalDevice with Vulkan. This is because QRhiDriverInfo does not
10289 contain platform-specific data. Instead, use \a nativeHandles to get the
10290 results filtered already inside enumerateAdapters().
10291
10292 The following two snippets, using Direct 3D 12 as an example, are equivalent
10293 in practice:
10294
10295 \code
10296 // enumerateAdapters-based approach from Qt 6.10 on
10297 QRhiD3D12InitParams initParams;
10298 QRhiD3D12NativeHandles nativeHandles;
10299 nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
10300 nativeHandles.adapterLuidHigh = luid.HighPart;
10301 QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::D3D12, &initParams, &nativeHandles);
10302 if (adapters.isEmpty()) { qWarning("Requested adapter was not found"); }
10303 QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, nullptr, adapters[0]);
10304 qDeleteAll(adapters);
10305 \endcode
10306
10307 \code
10308 // traditional approach, more lightweight
10309 QRhiD3D12InitParams initParams;
10310 QRhiD3D12NativeHandles nativeHandles;
10311 nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
10312 nativeHandles.adapterLuidHigh = luid.HighPart;
10313 QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, &nativeHandles, nullptr);
10314 \endcode
10315
10316 \since 6.10
10317 \sa create()
10318 */
10319QRhi::AdapterList QRhi::enumerateAdapters(Implementation impl, QRhiInitParams *params, QRhiNativeHandles *nativeHandles)
10320{
10321 std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, nullptr));
10322 if (!rd)
10323 return {};
10324
10325 return rd->enumerateAdaptersBeforeCreate(nativeHandles);
10326}
10327
10328/*!
10329 \struct QRhiSwapChainProxyData
10330 \inmodule QtGuiPrivate
10331 \inheaderfile rhi/qrhi.h
10332 \since 6.6
10333
10334 \brief Opaque data describing native objects needed to set up a swapchain.
10335
10336 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10337 for details.
10338
10339 \sa QRhi::updateSwapChainProxyData()
10340 */
10341
10342/*!
10343 Generates and returns a QRhiSwapChainProxyData struct containing opaque
10344 data specific to the backend and graphics API specified by \a impl. \a
10345 window is the QWindow a swapchain is targeting.
10346
10347 The returned struct can be passed to QRhiSwapChain::setProxyData(). This
10348 makes sense in threaded rendering systems: this static function is expected
10349 to be called on the \b{main (gui) thread}, unlike all QRhi operations, then
10350 transferred to the thread working with the QRhi and QRhiSwapChain and passed
10351 on to the swapchain. This allows doing native platform queries that are
10352 only safe to be called on the main thread, for example to query the
10353 CAMetalLayer from a NSView, and then passing on the data to the
10354 QRhiSwapChain living on the rendering thread. With the Metal example, doing
10355 the view.layer access on a dedicated rendering thread causes a warning in
10356 the Xcode Thread Checker. With the data proxy mechanism, this is avoided.
10357
10358 When threads are not involved, generating and passing on the
10359 QRhiSwapChainProxyData is not required: backends are guaranteed to be able
10360 to query whatever is needed on their own, and if everything lives on the
10361 main (gui) thread, that should be sufficient.
10362
10363 \note \a impl should match what the QRhi is created with. For example,
10364 calling with QRhi::Metal on a non-Apple platform will not generate any
10365 useful data.
10366 */
10367QRhiSwapChainProxyData QRhi::updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)
10368{
10369#if QT_CONFIG(metal)
10370 if (impl == Metal)
10371 return QRhiMetal::updateSwapChainProxyData(window);
10372#else
10373 Q_UNUSED(impl);
10374 Q_UNUSED(window);
10375#endif
10376 return {};
10377}
10378
10379/*!
10380 \return the backend type for this QRhi.
10381 */
10382QRhi::Implementation QRhi::backend() const
10383{
10384 return d->implType;
10385}
10386
10387/*!
10388 \return a friendly name for the backend \a impl, usually the name of the 3D
10389 API in use.
10390 */
10391const char *QRhi::backendName(Implementation impl)
10392{
10393 switch (impl) {
10394 case QRhi::Null:
10395 return "Null";
10396 case QRhi::Vulkan:
10397 return "Vulkan";
10398 case QRhi::OpenGLES2:
10399 return "OpenGL";
10400 case QRhi::D3D11:
10401 return "D3D11";
10402 case QRhi::Metal:
10403 return "Metal";
10404 case QRhi::D3D12:
10405 return "D3D12";
10406 }
10407
10408 Q_UNREACHABLE_RETURN("Unknown");
10409}
10410
10411/*!
10412 \return the backend type as string for this QRhi.
10413 */
10414const char *QRhi::backendName() const
10415{
10416 return backendName(d->implType);
10417}
10418
10419/*!
10420 \enum QRhiDriverInfo::DeviceType
10421 Specifies the graphics device's type, when the information is available.
10422
10423 In practice this is only applicable with Vulkan and Metal. With Direct 3D
10424 11 and 12, using an adapter with the software flag set leads to the value
10425 \c CpuDevice. Otherwise, and with OpenGL, the value is always UnknownDevice.
10426
10427 \value UnknownDevice
10428 \value IntegratedDevice
10429 \value DiscreteDevice
10430 \value ExternalDevice
10431 \value VirtualDevice
10432 \value CpuDevice
10433*/
10434
10435/*!
10436 \struct QRhiDriverInfo
10437 \inmodule QtGuiPrivate
10438 \inheaderfile rhi/qrhi.h
10439 \since 6.6
10440
10441 \brief Describes the physical device, adapter, or graphics API
10442 implementation that is used by an initialized QRhi.
10443
10444 Graphics APIs offer different levels and kinds of information. The only
10445 value that is available across all APIs is the deviceName, which is a
10446 freetext description of the physical device, adapter, or is a combination
10447 of the strings reported for \c{GL_VENDOR} + \c{GL_RENDERER} +
10448 \c{GL_VERSION}. The deviceId is always 0 for OpenGL. vendorId is always 0
10449 for OpenGL and Metal. deviceType is always UnknownDevice for OpenGL and
10450 Direct 3D.
10451
10452 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10453 for details.
10454 */
10455
10456/*!
10457 \variable QRhiDriverInfo::deviceName
10458
10459 \sa QRhi::driverInfo()
10460*/
10461
10462/*!
10463 \variable QRhiDriverInfo::deviceId
10464
10465 \sa QRhi::driverInfo()
10466*/
10467
10468/*!
10469 \variable QRhiDriverInfo::vendorId
10470
10471 \sa QRhi::driverInfo()
10472*/
10473
10474/*!
10475 \variable QRhiDriverInfo::deviceType
10476
10477 \sa QRhi::driverInfo(), QRhiDriverInfo::DeviceType
10478*/
10479
10480#ifndef QT_NO_DEBUG_STREAM
10481static inline const char *deviceTypeStr(QRhiDriverInfo::DeviceType type)
10482{
10483 switch (type) {
10484 case QRhiDriverInfo::UnknownDevice:
10485 return "Unknown";
10486 case QRhiDriverInfo::IntegratedDevice:
10487 return "Integrated";
10488 case QRhiDriverInfo::DiscreteDevice:
10489 return "Discrete";
10490 case QRhiDriverInfo::ExternalDevice:
10491 return "External";
10492 case QRhiDriverInfo::VirtualDevice:
10493 return "Virtual";
10494 case QRhiDriverInfo::CpuDevice:
10495 return "Cpu";
10496 }
10497
10498 Q_UNREACHABLE_RETURN(nullptr);
10499}
10500QDebug operator<<(QDebug dbg, const QRhiDriverInfo &info)
10501{
10502 QDebugStateSaver saver(dbg);
10503 dbg.nospace() << "QRhiDriverInfo(deviceName=" << info.deviceName
10504 << " deviceId=0x" << Qt::hex << info.deviceId
10505 << " vendorId=0x" << info.vendorId
10506 << " deviceType=" << deviceTypeStr(info.deviceType)
10507 << ')';
10508 return dbg;
10509}
10510#endif
10511
10512/*!
10513 \return metadata for the graphics device used by this successfully
10514 initialized QRhi instance.
10515 */
10516QRhiDriverInfo QRhi::driverInfo() const
10517{
10518 return d->driverInfo();
10519}
10520
10521/*!
10522 \class QRhiAdapter
10523 \inmodule QtGuiPrivate
10524 \inheaderfile rhi/qrhi.h
10525 \since 6.10
10526
10527 \brief Represents a physical graphics device.
10528
10529 Some QRhi backends target graphics APIs that expose the concept of \c
10530 adapters or \c{physical devices}. Call the static \l
10531 {QRhi::}{enumerateAdapters()} function to retrieve a list of the adapters
10532 present in the system. Pass one of the returned QRhiAdapter objects to \l
10533 {QRhi::}{create()} in order to request using the adapter or physical device
10534 the QRhiAdapter corresponds to. Other than exposing the QRhiDriverInfo,
10535 QRhiAdapter is to be treated as an opaque handle.
10536
10537 \note With Vulkan, the QRhiAdapter is valid only as long as the
10538 QVulkanInstance that was used for \l{QRhi::}{enumerateAdapters()} is valid.
10539 This also means that a QRhiAdapter is tied to the Vulkan instance
10540 (QVulkanInstance, \c VkInstance) and cannot be used in the context of
10541 another Vulkan instance.
10542
10543 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10544 for details.
10545 */
10546
10547/*!
10548 \fn virtual QRhiDriverInfo QRhiAdapter::info() const = 0
10549
10550 \return the corresponding QRhiDriverInfo.
10551 */
10552
10553/*!
10554 \internal
10555 */
10556QRhiAdapter::~QRhiAdapter()
10557{
10558}
10559
10560/*!
10561 \return the thread on which the QRhi was \l{QRhi::create()}{initialized}.
10562 */
10563QThread *QRhi::thread() const
10564{
10565 return d->implThread;
10566}
10567
10568/*!
10569 Registers a \a callback that is invoked when the QRhi is destroyed.
10570
10571 The callback will run with the graphics resource still available, so this
10572 provides an opportunity for the application to cleanly release QRhiResource
10573 instances belonging to the QRhi. This is particularly useful for managing
10574 the lifetime of resources stored in \c cache type of objects, where the
10575 cache holds QRhiResources or objects containing QRhiResources.
10576
10577 \sa ~QRhi()
10578 */
10579void QRhi::addCleanupCallback(const CleanupCallback &callback)
10580{
10581 d->addCleanupCallback(callback);
10582}
10583
10584/*!
10585 \overload
10586
10587 Registers \a callback to be invoked when the QRhi is destroyed. This
10588 overload takes an opaque pointer, \a key, that is used to ensure that a
10589 given callback is registered (and so called) only once.
10590
10591 \sa removeCleanupCallback()
10592 */
10593void QRhi::addCleanupCallback(const void *key, const CleanupCallback &callback)
10594{
10595 d->addCleanupCallback(key, callback);
10596}
10597
10598/*!
10599 Deregisters the callback with \a key. If no cleanup callback was registered
10600 with \a key, the function does nothing. Callbacks registered without a key
10601 cannot be removed.
10602
10603 \sa addCleanupCallback()
10604 */
10605void QRhi::removeCleanupCallback(const void *key)
10606{
10607 d->removeCleanupCallback(key);
10608}
10609
10610void QRhiImplementation::runCleanup()
10611{
10612 for (const QRhi::CleanupCallback &f : std::as_const(cleanupCallbacks))
10613 f(q);
10614
10615 cleanupCallbacks.clear();
10616
10617 for (auto it = keyedCleanupCallbacks.cbegin(), end = keyedCleanupCallbacks.cend(); it != end; ++it)
10618 it.value()(q);
10619
10620 keyedCleanupCallbacks.clear();
10621}
10622
10623/*!
10624 \class QRhiResourceUpdateBatch
10625 \inmodule QtGuiPrivate
10626 \inheaderfile rhi/qrhi.h
10627 \since 6.6
10628 \brief Records upload and copy type of operations.
10629
10630 With QRhi it is no longer possible to perform copy type of operations at
10631 arbitrary times. Instead, all such operations are recorded into batches
10632 that are then passed, most commonly, to QRhiCommandBuffer::beginPass().
10633 What then happens under the hood is hidden from the application: the
10634 underlying implementations can defer and implement these operations in
10635 various different ways.
10636
10637 A resource update batch owns no graphics resources and does not perform any
10638 actual operations on its own. It should rather be viewed as a command
10639 buffer for update, upload, and copy type of commands.
10640
10641 To get an available, empty batch from the pool, call
10642 QRhi::nextResourceUpdateBatch().
10643
10644 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10645 for details.
10646 */
10647
10648/*!
10649 \internal
10650 */
10651QRhiResourceUpdateBatch::QRhiResourceUpdateBatch(QRhiImplementation *rhi)
10652 : d(new QRhiResourceUpdateBatchPrivate)
10653{
10654 d->q = this;
10655 d->rhi = rhi;
10656}
10657
10658QRhiResourceUpdateBatch::~QRhiResourceUpdateBatch()
10659{
10660 delete d;
10661}
10662
10663/*!
10664 \return the batch to the pool. This should only be used when the batch is
10665 not passed to one of QRhiCommandBuffer::beginPass(),
10666 QRhiCommandBuffer::endPass(), or QRhiCommandBuffer::resourceUpdate()
10667 because these implicitly call destroy().
10668
10669 \note QRhiResourceUpdateBatch instances must never by \c deleted by
10670 applications.
10671 */
10672void QRhiResourceUpdateBatch::release()
10673{
10674 d->free();
10675}
10676
10677/*!
10678 Copies all queued operations from the \a other batch into this one.
10679
10680 \note \a other may no longer contain valid data after the merge operation,
10681 and must not be submitted, but it will still need to be released by calling
10682 release().
10683
10684 This allows for a convenient pattern where resource updates that are
10685 already known during the initialization step are collected into a batch
10686 that is then merged into another when starting to first render pass later
10687 on:
10688
10689 \code
10690 void init()
10691 {
10692 initialUpdates = rhi->nextResourceUpdateBatch();
10693 initialUpdates->uploadStaticBuffer(vbuf, vertexData);
10694 initialUpdates->uploadStaticBuffer(ibuf, indexData);
10695 // ...
10696 }
10697
10698 void render()
10699 {
10700 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
10701 if (initialUpdates) {
10702 resUpdates->merge(initialUpdates);
10703 initialUpdates->release();
10704 initialUpdates = nullptr;
10705 }
10706 // resUpdates->updateDynamicBuffer(...);
10707 cb->beginPass(rt, clearCol, clearDs, resUpdates);
10708 }
10709 \endcode
10710 */
10711void QRhiResourceUpdateBatch::merge(QRhiResourceUpdateBatch *other)
10712{
10713 d->merge(other->d);
10714}
10715
10716/*!
10717 \return true until the number of buffer and texture operations enqueued
10718 onto this batch is below a reasonable limit.
10719
10720 The return value is false when the number of buffer and/or texture
10721 operations added to this batch have reached, or are about to reach, a
10722 certain limit. The batch is fully functional afterwards as well, but may
10723 need to allocate additional memory. Therefore, a renderer that collects
10724 lots of buffer and texture updates in a single batch when preparing a frame
10725 may want to consider \l{QRhiCommandBuffer::resourceUpdate()}{submitting the
10726 batch} and \l{QRhi::nextResourceUpdateBatch()}{starting a new one} when
10727 this function returns false.
10728 */
10729bool QRhiResourceUpdateBatch::hasOptimalCapacity() const
10730{
10731 return d->hasOptimalCapacity();
10732}
10733
10734/*!
10735 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10736 QRhiBuffer::Dynamic.
10737
10738 The region is specified \a offset and \a size. The actual bytes to write
10739 are specified by \a data which must have at least \a size bytes available.
10740
10741 \a data is copied and can safely be destroyed or changed once this function
10742 returns.
10743
10744 \note If host writes are involved, which is the case with
10745 updateDynamicBuffer() typically as such buffers are backed by host visible
10746 memory with most backends, they may accumulate within a frame. Thus pass 1
10747 reading a region changed by a batch passed to pass 2 may see the changes
10748 specified in pass 2's update batch.
10749
10750 \note QRhi transparently manages double buffering in order to prevent
10751 stalling the graphics pipeline. The fact that a QRhiBuffer may have
10752 multiple native buffer objects underneath can be safely ignored when using
10753 the QRhi and QRhiResourceUpdateBatch.
10754 */
10755void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
10756{
10757 if (size > 0) {
10758 const int idx = d->activeBufferOpCount++;
10759 const int opListSize = d->bufferOps.size();
10760 if (idx < opListSize)
10761 QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, size, data);
10762 else
10763 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, size, data));
10764 }
10765}
10766
10767/*!
10768 \overload
10769 \since 6.10
10770
10771 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10772 QRhiBuffer::Dynamic.
10773
10774 \a data is moved into the batch instead of copied with this overload.
10775 */
10776void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
10777{
10778 if (!data.isEmpty()) {
10779 const int idx = d->activeBufferOpCount++;
10780 const int opListSize = d->bufferOps.size();
10781 if (idx < opListSize)
10782 QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, std::move(data));
10783 else
10784 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, std::move(data)));
10785 }
10786}
10787
10788/*!
10789 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10790 QRhiBuffer::Immutable or QRhiBuffer::Static.
10791
10792 The region is specified \a offset and \a size. The actual bytes to write
10793 are specified by \a data which must have at least \a size bytes available.
10794
10795 \a data is copied and can safely be destroyed or changed once this function
10796 returns.
10797
10798 \note Whether the upload is performed on the GPU timeline, and so is ordered
10799 against the other operations recorded in the same batch, is indicated by the
10800 \l QRhi::StaticBuffersOnGpuTimeline feature. This only matters when
10801 combining uploads with
10802 \l{QRhiResourceUpdateBatch::copyBuffer()}{copyBuffer()} on the same buffer.
10803
10804 \sa copyBuffer()
10805 */
10806void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
10807{
10808 if (size > 0) {
10809 const int idx = d->activeBufferOpCount++;
10810 if (idx < d->bufferOps.size())
10811 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, size, data);
10812 else
10813 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, size, data));
10814 }
10815}
10816
10817/*!
10818 \overload
10819 \since 6.10
10820
10821 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10822 QRhiBuffer::Immutable or QRhiBuffer::Static.
10823
10824 \a data is moved into the batch instead of copied with this overload.
10825 */
10826void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
10827{
10828 if (!data.isEmpty()) {
10829 const int idx = d->activeBufferOpCount++;
10830 if (idx < d->bufferOps.size())
10831 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, std::move(data));
10832 else
10833 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, std::move(data)));
10834 }
10835}
10836
10837/*!
10838 \overload
10839
10840 Enqueues updating the entire QRhiBuffer \a buf created with the type
10841 QRhiBuffer::Immutable or QRhiBuffer::Static.
10842 */
10843void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *data)
10844{
10845 if (buf->size() > 0) {
10846 const int idx = d->activeBufferOpCount++;
10847 if (idx < d->bufferOps.size())
10848 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, 0, data);
10849 else
10850 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, 0, data));
10851 }
10852}
10853
10854/*!
10855 \overload
10856 \since 6.10
10857
10858 Enqueues updating the entire QRhiBuffer \a buf created with the type
10859 QRhiBuffer::Immutable or QRhiBuffer::Static.
10860
10861 \a data is moved into the batch instead of copied with this overload.
10862
10863 \a data size must equal the size of \a buf.
10864 */
10865void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, QByteArray data)
10866{
10867 if (buf->size() > 0 && quint32(data.size()) == buf->size()) {
10868 const int idx = d->activeBufferOpCount++;
10869 if (idx < d->bufferOps.size())
10870 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, std::move(data));
10871 else
10872 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, std::move(data)));
10873 }
10874}
10875
10876/*!
10877 Enqueues reading back a region of the QRhiBuffer \a buf. The size of the
10878 region is specified by \a size in bytes, \a offset is the offset in bytes
10879 to start reading from.
10880
10881 A readback is asynchronous. \a result contains a callback that is invoked
10882 when the operation has completed. The data is provided in
10883 QRhiReadbackResult::data. Upon successful completion that QByteArray
10884 will have a size equal to \a size. On failure the QByteArray will be empty.
10885
10886 \note Reading buffers with a usage different than QRhiBuffer::UniformBuffer
10887 is supported only when the QRhi::ReadBackNonUniformBuffer feature is
10888 reported as supported.
10889
10890 \note The asynchronous readback is guaranteed to have completed when one of
10891 the following conditions is met: \l{QRhi::finish()}{finish()} has been
10892 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
10893 including the frame that issued the readback operation, and the
10894 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
10895 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
10896 QRhi::MaxAsyncReadbackFrames.
10897
10898 \sa readBackTexture(), QRhi::isFeatureSupported(), QRhi::resourceLimit()
10899 */
10900void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
10901{
10902 const int idx = d->activeBufferOpCount++;
10903 if (idx < d->bufferOps.size())
10904 d->bufferOps[idx] = QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result);
10905 else
10906 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result));
10907}
10908
10909/*!
10910 Enqueues a buffer-to-buffer copy operation from \a src into \a dst as
10911 described by \a desc.
10912
10913 The copy is performed on the GPU, without involving the CPU. This is the
10914 preferred way of moving data between two non-Dynamic QRhiBuffer objects.
10915
10916 Availability is indicated by the \l QRhi::BufferToBufferCopy feature. When
10917 that is reported as not supported, which in practice means OpenGL ES 2.0 and
10918 old desktop OpenGL versions, calling this function has no effect.
10919
10920 A \l{QRhiBufferCopyDescription::size()}{size} of 0 in \a desc, which is what
10921 a default constructed description has, means the entire \a src buffer. Watch
10922 out for this when \a dst is smaller than \a src, because the copy then does
10923 not fit and gets dropped, as described below.
10924
10925 \note Neither buffer can be of the type QRhiBuffer::Dynamic, and neither can
10926 have QRhiBuffer::UniformBuffer usage. With some of the underlying 3D APIs
10927 such buffers are backed by host visible memory, or are not real GPU buffers
10928 at all, and so cannot take part in a GPU-side copy.
10929
10930 \note The size and offsets in \a desc should all be multiples of 4. This is a
10931 requirement of the blit encoder in Metal, and it applies on macOS on
10932 Intel-based devices. Other platforms and 3D APIs, including Metal on Apple
10933 Silicon and on iOS, have no such restriction, but portable code has to assume
10934 the strictest of these. Keep in mind that a
10935 \l{QRhiBufferCopyDescription::size()}{size} of 0 leads to using the full size
10936 of \a src, which is not necessarily a multiple of 4 either.
10937
10938 \note Mixing GPU-side copies with host-side updates
10939 (\l{QRhiResourceUpdateBatch::uploadStaticBuffer()}{uploadStaticBuffer()}) on
10940 the same buffer within the same frame follows the order in which the
10941 operations were recorded in the batch, but only when the
10942 \l QRhi::StaticBuffersOnGpuTimeline feature is reported as supported. Where
10943 it is not, which in practice means Metal on macOS on devices without an
10944 Apple GPU, buffer uploads are implemented by writing to host visible memory,
10945 and so the ordering between the two kinds of updates is not defined.
10946 Portable applications need to either avoid the pattern or check the feature
10947 flag.
10948
10949 \since 6.13
10950 \sa copyTexture(), QRhi::isFeatureSupported()
10951 */
10952void QRhiResourceUpdateBatch::copyBuffer(QRhiBuffer *dst, QRhiBuffer *src, const QRhiBufferCopyDescription &desc)
10953{
10954 if (!dst || !src) {
10955 qWarning("Buffer copy with a null source or destination is not supported");
10956 return;
10957 }
10958 if (dst == src) {
10959 qWarning("Buffer copy with matching source and destination is not supported");
10960 return;
10961 }
10962 // Dynamic buffers are host visible, or shadowed on the CPU, with some of
10963 // the backends, and so cannot be the source or the destination of a
10964 // GPU-side copy. UniformBuffer is not necessarily backed by a real GPU
10965 // buffer either.
10966 if (dst->usage().testFlag(QRhiBuffer::UniformBuffer) || src->usage().testFlag(QRhiBuffer::UniformBuffer)) {
10967 qWarning("Buffer copy is not supported for buffers with UniformBuffer usage");
10968 return;
10969 }
10970 if (dst->type() == QRhiBuffer::Dynamic || src->type() == QRhiBuffer::Dynamic) {
10971 qWarning("Buffer copy is not supported for Dynamic buffers");
10972 return;
10973 }
10974
10975 const quint32 size = desc.size() ? desc.size() : src->size();
10976 if (!size)
10977 return;
10978 if (quint64(desc.sourceOffset()) + size > src->size() || quint64(desc.destinationOffset()) + size > dst->size()) {
10979 qWarning("Buffer copy of %u bytes (source offset %u, destination offset %u) "
10980 "does not fit the source (%u bytes) or destination (%u bytes) buffer",
10981 size, desc.sourceOffset(), desc.destinationOffset(),
10982 src->size(), dst->size());
10983 return;
10984 }
10985
10986 const int idx = d->activeBufferOpCount++;
10987 const QRhiResourceUpdateBatchPrivate::BufferOp op = QRhiResourceUpdateBatchPrivate::BufferOp::copy(dst, src,
10988 desc.destinationOffset(), desc.sourceOffset(), size);
10989
10990 if (idx < d->bufferOps.size())
10991 d->bufferOps[idx] = op;
10992 else
10993 d->bufferOps.append(op);
10994}
10995
10996/*!
10997 Enqueues filling \a size bytes of the buffer \a buf, starting at \a offset,
10998 with the byte \a value.
10999
11000 The buffer must have been created with the QRhiBuffer::StorageBuffer usage.
11001 Such buffers are only available when the \l QRhi::Compute feature is
11002 reported as supported, and are never of the type QRhiBuffer::Dynamic. The
11003 clear is performed on the GPU, and it takes effect in the order it was
11004 recorded in, relative to the compute and render passes, and to the other
11005 buffer operations in the batch that are performed on the GPU, such as
11006 copyBuffer(). This makes it suitable for resetting storage buffers
11007 (counters, accumulators) between compute dispatches.
11008
11009 \note \a offset must be a multiple of 4, otherwise the clear is ignored,
11010 with a warning. When \a size is not a multiple of 4, it is rounded down to
11011 the previous multiple of 4, again with a warning, which means the
11012 remaining one to three bytes are left untouched. These are restrictions of
11013 some of the underlying 3D APIs.
11014
11015 \note The clear maps to the native buffer fill or clear operation of the
11016 underlying 3D API, such as \c vkCmdFillBuffer or
11017 \c ClearUnorderedAccessViewUint, without transferring data from the CPU.
11018 The exception is OpenGL ES, which has no way of clearing the contents of a
11019 buffer on the GPU. There the clear is implemented by uploading \a size
11020 bytes of data.
11021
11022 \note Mixing clears with host-side updates
11023 (\l{QRhiResourceUpdateBatch::uploadStaticBuffer()}{uploadStaticBuffer()}) on
11024 the same buffer within the same frame follows the order in which the
11025 operations were recorded in the batch only when the
11026 \l QRhi::StaticBuffersOnGpuTimeline feature is reported as supported. See
11027 copyBuffer() for details.
11028
11029 \since 6.13
11030 \sa copyBuffer()
11031 */
11032void QRhiResourceUpdateBatch::clearStorageBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, quint8 value)
11033{
11034 if (!buf) {
11035 qWarning("Buffer clear with a null buffer is not supported");
11036 return;
11037 }
11038 if (!buf->usage().testFlag(QRhiBuffer::StorageBuffer)) {
11039 qWarning("Buffer clear is only supported for buffers with StorageBuffer usage");
11040 return;
11041 }
11042 // StorageBuffer is not supposed to be combined with Dynamic, but not all
11043 // backends reject it
11044 if (buf->type() == QRhiBuffer::Dynamic) {
11045 qWarning("Buffer clear is not supported for Dynamic buffers");
11046 return;
11047 }
11048 if (offset % 4u) {
11049 qWarning("Buffer clear offset %u is not a multiple of 4", offset);
11050 return;
11051 }
11052 if (quint64(offset) + size > buf->size()) {
11053 qWarning("Buffer clear of %u bytes at offset %u does not fit the buffer (%u bytes)",
11054 size, offset, buf->size());
11055 return;
11056 }
11057 if (size % 4u) {
11058 qWarning("Buffer clear size %u is not a multiple of 4, rounding down", size);
11059 size &= ~3u;
11060 }
11061 if (!size)
11062 return;
11063
11064 const int idx = d->activeBufferOpCount++;
11065 const QRhiResourceUpdateBatchPrivate::BufferOp op = QRhiResourceUpdateBatchPrivate::BufferOp::clear(buf,
11066 offset, size, value);
11067
11068 if (idx < d->bufferOps.size())
11069 d->bufferOps[idx] = op;
11070 else
11071 d->bufferOps.append(op);
11072}
11073
11074/*!
11075 \overload
11076
11077 Enqueues filling the entire buffer \a buf with the byte \a value. When the
11078 size of \a buf is not a multiple of 4, the last one to three bytes are left
11079 untouched, and a warning is printed.
11080
11081 \since 6.13
11082 */
11083void QRhiResourceUpdateBatch::clearStorageBuffer(QRhiBuffer *buf, quint8 value)
11084{
11085 clearStorageBuffer(buf, 0, buf ? buf->size() : 0, value);
11086}
11087
11088/*!
11089 Enqueues uploading the image data for one or more mip levels in one or more
11090 layers of the texture \a tex.
11091
11092 The details of the copy (source QImage or compressed texture data, regions,
11093 target layers and levels) are described in \a desc.
11094 */
11095void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
11096{
11097 if (desc.cbeginEntries() != desc.cendEntries()) {
11098 const int idx = d->activeTextureOpCount++;
11099 if (idx < d->textureOps.size())
11100 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc);
11101 else
11102 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc));
11103 }
11104}
11105
11106/*!
11107 Enqueues uploading the image data for mip level 0 of layer 0 of the texture
11108 \a tex.
11109
11110 \a tex must have an uncompressed format. Its format must also be compatible
11111 with the QImage::format() of \a image. The source data is given in \a
11112 image.
11113 */
11114void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &image)
11115{
11116 uploadTexture(tex,
11117 QRhiTextureUploadEntry(0, 0, QRhiTextureSubresourceUploadDescription(image)));
11118}
11119
11120/*!
11121 Enqueues a texture-to-texture copy operation from \a src into \a dst as
11122 described by \a desc.
11123
11124 \note The source texture \a src must be created with
11125 QRhiTexture::UsedAsTransferSource.
11126
11127 \note The format of the textures must match. With most graphics
11128 APIs the data is copied as-is without any format conversions. If
11129 \a dst and \a src are created with different formats, unspecified
11130 issues may arise.
11131 */
11132void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
11133{
11134 const int idx = d->activeTextureOpCount++;
11135 if (idx < d->textureOps.size())
11136 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc);
11137 else
11138 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc));
11139}
11140
11141/*!
11142 Enqueues a texture-to-host copy operation as described by \a rb.
11143
11144 Normally \a rb will specify a QRhiTexture as the source. However, when the
11145 swapchain in the current frame was created with
11146 QRhiSwapChain::UsedAsTransferSource, it can also be the source of the
11147 readback. For this, leave the texture set to null in \a rb.
11148
11149 Unlike other operations, the results here need to be processed by the
11150 application. Therefore, \a result provides not just the data but also a
11151 callback as operations on the batch are asynchronous by nature:
11152
11153 \code
11154 rhi->beginFrame(swapchain);
11155 cb->beginPass(swapchain->currentFrameRenderTarget(), colorClear, dsClear);
11156 // ...
11157 QRhiReadbackResult *rbResult = new QRhiReadbackResult;
11158 rbResult->completed = [rbResult] {
11159 {
11160 const QImage::Format fmt = QImage::Format_RGBA8888_Premultiplied; // fits QRhiTexture::RGBA8
11161 const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
11162 QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
11163 image.save("result.png");
11164 }
11165 delete rbResult;
11166 };
11167 QRhiResourceUpdateBatch *u = nextResourceUpdateBatch();
11168 QRhiReadbackDescription rb; // no texture -> uses the current backbuffer of sc
11169 u->readBackTexture(rb, rbResult);
11170 cb->endPass(u);
11171 rhi->endFrame(swapchain);
11172 \endcode
11173
11174 \note The texture must be created with QRhiTexture::UsedAsTransferSource.
11175
11176 \note Multisample textures cannot be read back.
11177
11178 \note The readback returns raw byte data, in order to allow the applications
11179 to interpret it in any way they see fit. Be aware of the blending settings
11180 of rendering code: if the blending is set up to rely on premultiplied alpha,
11181 the results of the readback must also be interpreted as Premultiplied.
11182
11183 \note When interpreting the resulting raw data, be aware that the readback
11184 happens with a byte ordered format. A \l{QRhiTexture::RGBA8}{RGBA8} texture
11185 maps therefore to byte ordered QImage formats, such as,
11186 QImage::Format_RGBA8888.
11187
11188 \note The asynchronous readback is guaranteed to have completed when one of
11189 the following conditions is met: \l{QRhi::finish()}{finish()} has been
11190 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
11191 including the frame that issued the readback operation, and the
11192 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
11193 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
11194 QRhi::MaxAsyncReadbackFrames.
11195
11196 A single readback operation copies one mip level of one layer (cubemap face
11197 or 3D slice or texture array element) at a time. The level and layer are
11198 specified by the respective fields in \a rb.
11199
11200 \sa readBackBuffer(), QRhi::resourceLimit()
11201 */
11202void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
11203{
11204 const int idx = d->activeTextureOpCount++;
11205 if (idx < d->textureOps.size())
11206 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result);
11207 else
11208 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result));
11209}
11210
11211/*!
11212 Enqueues a mipmap generation operation for the specified texture \a tex.
11213
11214 2D and cube textures are supported. 1D and 3D textures are supported when
11215 the QRhi::OneDimensionalTextureMipmaps or QRhi::ThreeDimensionalTextureMipmaps
11216 feature is reported as supported, respectively.
11217
11218 \note The texture must be created with QRhiTexture::MipMapped and
11219 QRhiTexture::UsedWithGenerateMips.
11220
11221 \warning QRhi cannot guarantee that mipmaps can be generated for all
11222 supported texture formats. For example, QRhiTexture::RGBA32F is not a \c
11223 filterable format in OpenGL ES 3.0 and Metal on iOS, and therefore the
11224 mipmap generation request may fail. RGBA8 and RGBA16F are typically
11225 filterable, so it is recommended to use these formats when mipmap generation
11226 is desired.
11227 */
11228void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex)
11229{
11230 const int idx = d->activeTextureOpCount++;
11231 if (idx < d->textureOps.size())
11232 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex);
11233 else
11234 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex));
11235}
11236
11237/*!
11238 Enqueues updating the contents of the indirect command buffer \a icb from
11239 the commands recorded on it with QRhiIndirectCommandBuffer::draw() or
11240 QRhiIndirectCommandBuffer::drawIndexed().
11241
11242 Has to be called after recording and before the render pass that executes
11243 the commands. Does nothing when nothing changed since the last time, so
11244 calling it once per frame is inexpensive.
11245
11246 Has no effect on an indirect command buffer that was populated with
11247 QRhiCommandBuffer::buildIndirect() instead.
11248
11249 \note This is where backends that keep the commands in a buffer perform the
11250 upload, but it is not necessarily where the cost of a CPU-recorded indirect
11251 command buffer is: Metal has nothing to upload here and does its per-command
11252 encoding in QRhiCommandBuffer::executeIndirect() instead. An inexpensive
11253 commitIndirectCommandBuffer() therefore does not by itself mean that
11254 recording the commands was inexpensive. See \l QRhiIndirectCommandBuffer for
11255 how the cost of CPU recording scales.
11256
11257 \since 6.13
11258 */
11259void QRhiResourceUpdateBatch::commitIndirectCommandBuffer(QRhiIndirectCommandBuffer *icb)
11260{
11261 Q_ASSERT(icb);
11262 d->rhi->commitIndirectCommandBuffer(this, icb);
11263}
11264
11265/*!
11266 \return an available, empty batch to which copy type of operations can be
11267 recorded.
11268
11269 \note the return value is not owned by the caller and must never be
11270 destroyed. Instead, the batch is returned the pool for reuse by passing
11271 it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or
11272 QRhiCommandBuffer::resourceUpdate(), or by calling
11273 QRhiResourceUpdateBatch::release() on it.
11274
11275 \note Can be called outside beginFrame() - endFrame() as well since a batch
11276 instance just collects data on its own, it does not perform any operations.
11277
11278 Due to not being tied to a frame being recorded, the following sequence is
11279 valid for example:
11280
11281 \code
11282 rhi->beginFrame(swapchain);
11283 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
11284 u->uploadStaticBuffer(buf, data);
11285 // ... do not commit the batch
11286 rhi->endFrame();
11287 // u stays valid (assuming buf stays valid as well)
11288 rhi->beginFrame(swapchain);
11289 swapchain->currentFrameCommandBuffer()->resourceUpdate(u);
11290 // ... draw with buf
11291 rhi->endFrame();
11292 \endcode
11293
11294 \warning The maximum number of batches per QRhi is 64. When this limit is
11295 reached, the function will return null until a batch is returned to the
11296 pool.
11297 */
11298QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
11299{
11300 // By default we prefer spreading out the utilization of the worst case 64
11301 // (but typically 4) batches as much as possible, meaning we won't pick the
11302 // first one even if it's free, but prefer picking one after the last picked
11303 // one. Relevant due to implicit sharing (the backend may hold on to the
11304 // QRhiBufferData until frame no. current+FramesInFlight-1, but
11305 // implementations may vary), combined with the desire to reuse container
11306 // and QRhiBufferData allocations in bufferOps instead of flooding every
11307 // frame with allocs. See free(). In typical Qt Quick scenes this leads to
11308 // eventually seeding all 4 (or more) resource batches with buffer operation
11309 // data allocations which may (*) then be reused in subsequent frames. This
11310 // comes at the expense of using more memory, but has proven good results
11311 // when (CPU) profiling typical Quick/Quick3D apps.
11312 //
11313 // (*) Due to implicit sharing(ish), the exact behavior is unpredictable. If
11314 // a backend holds on to the QRhiBufferData for, e.g., a dynamic buffer
11315 // update, and then there is a new assign() for that same QRhiBufferData
11316 // while the refcount is still 2, it will "detach" (without contents) and
11317 // there is no reuse of the alloc. This is mitigated by the 'choose the one
11318 // afer the last picked one' logic when handing out batches.
11319
11320 auto nextFreeBatch = [this]() -> QRhiResourceUpdateBatch * {
11321 auto isFree = [this](int i) -> QRhiResourceUpdateBatch * {
11322 const quint64 mask = 1ULL << quint64(i);
11323 if (!(d->resUpdPoolMap & mask)) {
11324 d->resUpdPoolMap |= mask;
11325 QRhiResourceUpdateBatch *u = d->resUpdPool[i];
11326 QRhiResourceUpdateBatchPrivate::get(u)->poolIndex = i;
11327 d->lastResUpdIdx = i;
11328 return u;
11329 }
11330 return nullptr;
11331 };
11332 const int poolSize = d->resUpdPool.size();
11333 for (int i = d->lastResUpdIdx + 1; i < poolSize; ++i) {
11334 if (QRhiResourceUpdateBatch *u = isFree(i))
11335 return u;
11336 }
11337 for (int i = 0; i <= d->lastResUpdIdx; ++i) {
11338 if (QRhiResourceUpdateBatch *u = isFree(i))
11339 return u;
11340 }
11341 return nullptr;
11342 };
11343
11344 QRhiResourceUpdateBatch *u = nextFreeBatch();
11345 if (!u) {
11346 const int oldSize = d->resUpdPool.size();
11347 // 4, 8, 12, ..., up to 64
11348 const int newSize = oldSize + qMin(4, qMax(0, 64 - oldSize));
11349 d->resUpdPool.resize(newSize);
11350 for (int i = oldSize; i < newSize; ++i)
11351 d->resUpdPool[i] = new QRhiResourceUpdateBatch(d);
11352 u = nextFreeBatch();
11353 if (!u)
11354 qWarning("Resource update batch pool exhausted (max is 64)");
11355 }
11356
11357 return u;
11358}
11359
11361{
11362 Q_ASSERT(poolIndex >= 0 && rhi->resUpdPool[poolIndex] == q);
11363
11364 quint32 bufferDataTotal = 0;
11365 quint32 bufferLargeAllocTotal = 0;
11366 for (const BufferOp &op : std::as_const(bufferOps)) {
11367 bufferDataTotal += op.data.size();
11368 bufferLargeAllocTotal += op.data.largeAlloc(); // alloc when > 1 KB
11369 }
11370
11371 if (QRHI_LOG_RUB().isDebugEnabled()) {
11372 qDebug() << "[rub] release to pool upd.batch #" << poolIndex
11373 << "/ bufferOps active" << activeBufferOpCount
11374 << "of" << bufferOps.count()
11375 << "data" << bufferDataTotal
11376 << "largeAlloc" << bufferLargeAllocTotal
11377 << "textureOps active" << activeTextureOpCount
11378 << "of" << textureOps.count();
11379 }
11380
11383
11384 const quint64 mask = 1ULL << quint64(poolIndex);
11385 rhi->resUpdPoolMap &= ~mask;
11386 poolIndex = -1;
11387
11388 // textureOps is cleared, to not keep the potentially large image pixel
11389 // data alive, but it is expected that the container keeps the list alloc
11390 // at least. Only trimOpList() goes for the more aggressive route with squeeze.
11391 textureOps.clear();
11392
11393 // bufferOps is not touched in many cases, to allow reusing allocations
11394 // (incl. in the elements' QRhiBufferData) as much as possible when this
11395 // batch is used again in the future, which is important for performance, in
11396 // particular with Qt Quick where it is easy for scenes to produce lots of,
11397 // typically small buffer changes on every frame.
11398 //
11399 // However, ensure that even in the unlikely case of having the max number
11400 // of batches (64) created in resUpdPool, no more than 64 MB in total is
11401 // used up by buffer data just to help future reuse. For simplicity, if
11402 // there is more than 1 MB data -> clear. Applications with frequent, huge
11403 // buffer updates probably have other bottlenecks anyway.
11404 if (bufferLargeAllocTotal > 1024 * 1024)
11405 bufferOps.clear();
11406}
11407
11409{
11410 int combinedSize = activeBufferOpCount + other->activeBufferOpCount;
11411 if (bufferOps.size() < combinedSize)
11412 bufferOps.resize(combinedSize);
11413 for (int i = activeBufferOpCount; i < combinedSize; ++i)
11414 bufferOps[i] = std::move(other->bufferOps[i - activeBufferOpCount]);
11416
11417 combinedSize = activeTextureOpCount + other->activeTextureOpCount;
11418 if (textureOps.size() < combinedSize)
11419 textureOps.resize(combinedSize);
11420 for (int i = activeTextureOpCount; i < combinedSize; ++i)
11421 textureOps[i] = std::move(other->textureOps[i - activeTextureOpCount]);
11423}
11424
11430
11432{
11433 // Unlike free(), this is expected to aggressively deallocate all memory
11434 // used by both the buffer and texture operation lists. (i.e. using
11435 // squeeze() to only keep the stack prealloc of the QVLAs)
11436 //
11437 // This (e.g. just the destruction of bufferOps elements) may have a
11438 // non-negligible performance impact e.g. with Qt Quick with scenes where
11439 // there are lots of buffer operations per frame.
11440
11442 bufferOps.clear();
11443 bufferOps.squeeze();
11444
11446 textureOps.clear();
11447 textureOps.squeeze();
11448}
11449
11450/*!
11451 Sometimes committing resource updates is necessary or just more convenient
11452 without starting a render pass. Calling this function with \a
11453 resourceUpdates is an alternative to passing \a resourceUpdates to a
11454 beginPass() call (or endPass(), which would be typical in case of readbacks).
11455
11456 \note Cannot be called inside a pass.
11457 */
11458void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
11459{
11460 if (resourceUpdates)
11461 m_rhi->resourceUpdate(this, resourceUpdates);
11462}
11463
11464/*!
11465 Records starting a new render pass targeting the render target \a rt.
11466
11467 \a resourceUpdates, when not null, specifies a resource update batch that
11468 is to be committed and then released.
11469
11470 The color and depth/stencil buffers of the render target are normally
11471 cleared. The clear values are specified in \a colorClearValue and \a
11472 depthStencilClearValue. The exception is when the render target was created
11473 with QRhiTextureRenderTarget::PreserveColorContents and/or
11474 QRhiTextureRenderTarget::PreserveDepthStencilContents. The clear values are
11475 ignored then.
11476
11477 \note Enabling preserved color or depth contents leads to decreased
11478 performance depending on the underlying hardware. Mobile GPUs with tiled
11479 architecture benefit from not having to reload the previous contents into
11480 the tile buffer. Similarly, a QRhiTextureRenderTarget with a QRhiTexture as
11481 the depth buffer is less efficient than a QRhiRenderBuffer since using a
11482 depth texture triggers requiring writing the data out to it, while with
11483 renderbuffers this is not needed (as the API does not allow sampling or
11484 reading from a renderbuffer).
11485
11486 \note Do not assume that any state or resource bindings persist between
11487 passes.
11488
11489 \note The QRhiCommandBuffer's \c set and \c draw functions can only be
11490 called inside a pass. Also, with the exception of setGraphicsPipeline(),
11491 they expect to have a pipeline set already on the command buffer.
11492 Unspecified issues may arise otherwise, depending on the backend.
11493
11494 If \a rt is a QRhiTextureRenderTarget, beginPass() performs a check to see
11495 if the texture and renderbuffer objects referenced from the render target
11496 are up-to-date. This is similar to what setShaderResources() does for
11497 QRhiShaderResourceBindings. If any of the attachments had been rebuilt
11498 since QRhiTextureRenderTarget::create(), an implicit call to create() is
11499 made on \a rt. Therefore, if \a rt has a QRhiTexture color attachment \c
11500 texture, and one needs to make the texture a different size, the following
11501 is then valid:
11502 \code
11503 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ { texture } });
11504 rt->create();
11505 // ...
11506 texture->setPixelSize(new_size);
11507 texture->create();
11508 cb->beginPass(rt, colorClear, dsClear); // this is ok, no explicit rt->create() is required before
11509 \endcode
11510
11511 \a flags allow controlling certain advanced functionality. One commonly used
11512 flag is \c ExternalContents. This should be specified whenever
11513 beginExternal() will be called within the pass started by this function.
11514
11515 \sa endPass(), BeginPassFlags
11516 */
11517void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
11518 const QColor &colorClearValue,
11519 const QRhiDepthStencilClearValue &depthStencilClearValue,
11520 QRhiResourceUpdateBatch *resourceUpdates,
11521 BeginPassFlags flags)
11522{
11523 m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates, flags);
11524}
11525
11526/*!
11527 Records ending the current render pass.
11528
11529 \a resourceUpdates, when not null, specifies a resource update batch that
11530 is to be committed and then released.
11531
11532 \sa beginPass()
11533 */
11534void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates)
11535{
11536 m_rhi->endPass(this, resourceUpdates);
11537}
11538
11539/*!
11540 Records setting a new graphics pipeline \a ps.
11541
11542 \note This function must be called before recording other \c set or \c draw
11543 commands on the command buffer.
11544
11545 \note QRhi will optimize out unnecessary invocations within a pass, so
11546 therefore overoptimizing to avoid calls to this function is not necessary
11547 on the applications' side.
11548
11549 \note This function can only be called inside a render pass, meaning
11550 between a beginPass() and endPass() call.
11551
11552 \note The new graphics pipeline \a ps must be a valid pointer.
11553
11554 Setting a graphics pipeline that does not have the
11555 \l{QRhiGraphicsPipeline::}{UsesScissor} flag will either disable scissoring,
11556 with graphics APIs where that is applicable, or set the scissor rectangle to
11557 match the viewport that was last set (with graphics APIs where scissoring is
11558 effectively always active), in order to ensure a uniform behavior across QRhi
11559 backends.
11560 */
11561void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)
11562{
11563 Q_ASSERT(ps != nullptr);
11564 m_rhi->setGraphicsPipeline(this, ps);
11565}
11566
11567/*!
11568 Records binding a set of shader resources, such as, uniform buffers or
11569 textures, that are made visible to one or more shader stages.
11570
11571 \a srb can be null in which case the current graphics or compute pipeline's
11572 associated QRhiShaderResourceBindings is used. When \a srb is non-null, it
11573 must be
11574 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible},
11575 meaning the layout (number of bindings, the type and binding number of each
11576 binding) must fully match the QRhiShaderResourceBindings that was
11577 associated with the pipeline at the time of calling the pipeline's create().
11578
11579 There are cases when a seemingly unnecessary setShaderResources() call is
11580 mandatory: when rebuilding a resource referenced from \a srb, for example
11581 changing the size of a QRhiBuffer followed by a QRhiBuffer::create(), this
11582 is the place where associated native objects (such as descriptor sets in
11583 case of Vulkan) are updated to refer to the current native resources that
11584 back the QRhiBuffer, QRhiTexture, QRhiSampler objects referenced from \a
11585 srb. In this case setShaderResources() must be called even if \a srb is
11586 the same as in the last call.
11587
11588 When \a srb is not null, the QRhiShaderResourceBindings object the pipeline
11589 was built with in create() is guaranteed to be not accessed in any form. In
11590 fact, it does not need to be valid even at this point: destroying the
11591 pipeline's associated srb after create() and instead explicitly specifying
11592 another, \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout
11593 compatible} one in every setShaderResources() call is valid.
11594
11595 \a dynamicOffsets allows specifying buffer offsets for uniform buffers that
11596 were associated with \a srb via
11597 QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(). This is
11598 different from providing the offset in the \a srb itself: dynamic offsets
11599 do not require building a new QRhiShaderResourceBindings for every
11600 different offset, can avoid writing the underlying descriptors (with
11601 backends where applicable), and so they may be more efficient. Each element
11602 of \a dynamicOffsets is a \c binding - \c offset pair.
11603 \a dynamicOffsetCount specifies the number of elements in \a dynamicOffsets.
11604
11605 \note All offsets in \a dynamicOffsets must be byte aligned to the value
11606 returned from QRhi::ubufAlignment().
11607
11608 \note Some backends may limit the number of supported dynamic offsets.
11609 Avoid using a \a dynamicOffsetCount larger than 8.
11610
11611 \note QRhi will optimize out unnecessary invocations within a pass (taking
11612 the conditions described above into account), so therefore overoptimizing
11613 to avoid calls to this function is not necessary on the applications' side.
11614
11615 \note This function can only be called inside a render or compute pass,
11616 meaning between a beginPass() and endPass(), or beginComputePass() and
11617 endComputePass().
11618 */
11619void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb,
11620 int dynamicOffsetCount,
11621 const DynamicOffset *dynamicOffsets)
11622{
11623 m_rhi->setShaderResources(this, srb, dynamicOffsetCount, dynamicOffsets);
11624}
11625
11626/*!
11627 Records vertex input bindings.
11628
11629 The index buffer used by subsequent drawIndexed() commands is specified by
11630 \a indexBuf, \a indexOffset, and \a indexFormat. \a indexBuf can be set to
11631 null when indexed drawing is not needed.
11632
11633 Vertex buffer bindings are batched. \a startBinding specifies the first
11634 binding number. The recorded command then binds each buffer from \a
11635 bindings to the binding point \c{startBinding + i} where \c i is the index
11636 in \a bindings. Each element in \a bindings specifies a QRhiBuffer and an
11637 offset.
11638
11639 \note Some backends may limit the number of vertex buffer bindings. Avoid
11640 using a \a bindingCount larger than 8.
11641
11642 Superfluous vertex input and index changes in the same pass are ignored
11643 automatically with most backends and therefore applications do not need to
11644 overoptimize to avoid calls to this function.
11645
11646 \note This function can only be called inside a render pass, meaning
11647 between a beginPass() and endPass() call.
11648
11649 As a simple example, take a vertex shader with two inputs:
11650
11651 \badcode
11652 layout(location = 0) in vec4 position;
11653 layout(location = 1) in vec3 color;
11654 \endcode
11655
11656 and assume we have the data available in interleaved format, using only 2
11657 floats for position (so 5 floats per vertex: x, y, r, g, b). A QRhiGraphicsPipeline for
11658 this shader can then be created using the input layout:
11659
11660 \code
11661 QRhiVertexInputLayout inputLayout;
11662 inputLayout.setBindings({
11663 { 5 * sizeof(float) }
11664 });
11665 inputLayout.setAttributes({
11666 { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
11667 { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
11668 });
11669 \endcode
11670
11671 Here there is one buffer binding (binding number 0), with two inputs
11672 referencing it. When recording the pass, once the pipeline is set, the
11673 vertex bindings can be specified simply like the following, assuming vbuf
11674 is the QRhiBuffer with all the interleaved position+color data:
11675
11676 \code
11677 const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
11678 cb->setVertexInput(0, 1, &vbufBinding);
11679 \endcode
11680 */
11681void QRhiCommandBuffer::setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
11682 QRhiBuffer *indexBuf, quint32 indexOffset,
11683 IndexFormat indexFormat)
11684{
11685 m_rhi->setVertexInput(this, startBinding, bindingCount, bindings, indexBuf, indexOffset, indexFormat);
11686}
11687
11688/*!
11689 Records setting the active viewport rectangle specified in \a viewport.
11690
11691 With backends where the underlying graphics API has scissoring always
11692 enabled, this function also sets the scissor to match the viewport whenever
11693 the active QRhiGraphicsPipeline does not have
11694 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set.
11695
11696 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
11697 bottom-left.
11698
11699 \note This function can only be called inside a render pass, meaning
11700 between a beginPass() and endPass() call.
11701 */
11702void QRhiCommandBuffer::setViewport(const QRhiViewport &viewport)
11703{
11704 m_rhi->setViewport(this, viewport);
11705}
11706
11707/*!
11708 Records setting the active scissor rectangle specified in \a scissor.
11709
11710 This can only be called when the bound pipeline has
11711 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set. When the flag is
11712 set on the active pipeline, this function must be called because scissor
11713 testing will get enabled and so a scissor rectangle must be provided.
11714
11715 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
11716 bottom-left.
11717
11718 \note This function can only be called inside a render pass, meaning
11719 between a beginPass() and endPass() call.
11720 */
11721void QRhiCommandBuffer::setScissor(const QRhiScissor &scissor)
11722{
11723 m_rhi->setScissor(this, scissor);
11724}
11725
11726/*!
11727 Records setting the active blend constants to \a c.
11728
11729 This can only be called when the bound pipeline has
11730 QRhiGraphicsPipeline::UsesBlendConstants set.
11731
11732 \note This function can only be called inside a render pass, meaning
11733 between a beginPass() and endPass() call.
11734 */
11735void QRhiCommandBuffer::setBlendConstants(const QColor &c)
11736{
11737 m_rhi->setBlendConstants(this, c);
11738}
11739
11740/*!
11741 Records setting the active stencil reference value to \a refValue.
11742
11743 This can only be called when the bound pipeline has
11744 QRhiGraphicsPipeline::UsesStencilRef set.
11745
11746 \note This function can only be called inside a render pass, meaning between
11747 a beginPass() and endPass() call.
11748 */
11749void QRhiCommandBuffer::setStencilRef(quint32 refValue)
11750{
11751 m_rhi->setStencilRef(this, refValue);
11752}
11753
11754/*!
11755 Records setting the push constant data for the currently bound graphics or
11756 compute pipeline. \a size bytes are taken from \a data and placed at byte
11757 offset \a offset within the push constant block. Both \a offset and \a
11758 size must be a multiple of 4.
11759
11760 Push constants are a small, pipeline-layout-resident block of data that can
11761 be updated between draw calls without touching any
11762 QRhiShaderResourceBindings. This makes them suitable for per-draw values
11763 such as an index into a storage buffer, avoiding a setShaderResources()
11764 call per draw.
11765
11766 The shaders declare the block in the usual way, for example:
11767
11768 \badcode
11769 layout(push_constant) uniform PC { uint objectIndex; } pc;
11770 \endcode
11771
11772 \note A push constant block defaults to the std430 layout, unlike a
11773 uniform block. There an array of scalars or of \c vec2 is tightly packed,
11774 and so are the columns of a matrix with two rows (\c mat2, \c mat3x2,
11775 \c mat4x2). Neither can be expressed in a Direct3D constant buffer, so a
11776 block that has such a member has to be declared with
11777 \c{layout(push_constant, std140)} in order to be usable with the D3D
11778 backends. (qsb reports an error when baking such a shader for HLSL) Blocks
11779 with only scalars, vectors, and \c mat3 or \c mat4 matrices, which is what
11780 push constants are mostly used for, are unaffected.
11781
11782 QRhi derives the push constant range from the shader reflection data of the
11783 pipeline's shader stages, so no extra declaration is needed on the
11784 QRhiGraphicsPipeline or QRhiComputePipeline.
11785
11786 \note This is only functional when the PushConstants feature is reported as
11787 supported. The maximum size of the block is reported by the
11788 MaxPushConstantsSize resource limit.
11789
11790 \note With Metal, push constants are not supported with a graphics pipeline
11791 that uses tessellation. Calling this function while such a pipeline is
11792 bound has no effect, apart from a warning.
11793
11794 \note Must be called inside a pass, after setGraphicsPipeline() or
11795 setComputePipeline().
11796
11797 \note The data does not persist. It has to be set again in every pass and
11798 after every change of pipeline. The backends differ in how much they would
11799 otherwise retain, so relying on anything else is not portable.
11800
11801 \since 6.13
11802 */
11803void QRhiCommandBuffer::setPushConstants(quint32 offset, quint32 size, const void *data)
11804{
11805 m_rhi->setPushConstants(this, offset, size, data);
11806}
11807
11808/*!
11809 Sets the shading rate for the following draw calls to \a coarsePixelSize.
11810
11811 The default is 1x1.
11812
11813 Functional only when the \l QRhi::VariableRateShading feature is reported as
11814 supported and the QRhiGraphicsPipeline(s) bound on the command buffer were
11815 declaring \l QRhiGraphicsPipeline::UsesShadingRate when creating them.
11816
11817 Call \l QRhi::supportedShadingRates() to check what shading rates are
11818 supported for a given sample count.
11819
11820 When both a QRhiShadingRateMap and this function are in use, the higher of
11821 the two shading rates is used for each tile. There is currently no control
11822 offered over the combiner behavior.
11823
11824 \since 6.9
11825 */
11826void QRhiCommandBuffer::setShadingRate(const QSize &coarsePixelSize)
11827{
11828 m_rhi->setShadingRate(this, coarsePixelSize);
11829}
11830
11831/*!
11832 Records a non-indexed draw.
11833
11834 The number of vertices is specified in \a vertexCount. For instanced
11835 drawing set \a instanceCount to a value other than 1. \a firstVertex is the
11836 index of the first vertex to draw. When drawing multiple instances, the
11837 first instance ID is specified by \a firstInstance.
11838
11839 \note \a firstInstance may not be supported, and is ignored when the
11840 QRhi::BaseInstance feature is reported as not supported. The first instance
11841 ID is always 0 in that case. QRhi::BaseInstance is never supported with
11842 OpenGL ES, and therefore portable applications should not be designed to
11843 rely on this argument.
11844
11845 \note Shaders that need to access the index of the current vertex or
11846 instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
11847 Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
11848 gl_InstanceID.
11849
11850 \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
11851 include the base value with some of the underlying 3D APIs. This is
11852 indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
11853 on a base instance value cannot be avoided, applications are advised to pass
11854 in the value as a uniform conditionally based on what that feature reports,
11855 and add it to \c gl_InstanceIndex in the shader.
11856
11857 \note This function can only be called inside a render pass, meaning
11858 between a beginPass() and endPass() call.
11859 */
11860void QRhiCommandBuffer::draw(quint32 vertexCount,
11861 quint32 instanceCount,
11862 quint32 firstVertex,
11863 quint32 firstInstance)
11864{
11865 m_rhi->draw(this, vertexCount, instanceCount, firstVertex, firstInstance);
11866}
11867
11868/*!
11869 Records an indexed draw.
11870
11871 The number of vertices is specified in \a indexCount. \a firstIndex is the
11872 base index. The effective offset in the index buffer is given by
11873 \c{indexOffset + firstIndex * n} where \c n is 2 or 4 depending on the
11874 index element type. \c indexOffset is specified in setVertexInput().
11875
11876 \note The effective offset in the index buffer must be 4 byte aligned with
11877 some backends (for example, Metal). With these backends the
11878 \l{QRhi::NonFourAlignedEffectiveIndexBufferOffset}{NonFourAlignedEffectiveIndexBufferOffset}
11879 feature will be reported as not-supported.
11880
11881 \a vertexOffset (also called \c{base vertex}) is a signed value that is
11882 added to the element index before indexing into the vertex buffer. Support
11883 for this is not always available, and the value is ignored when the feature
11884 QRhi::BaseVertex is reported as unsupported.
11885
11886 For instanced drawing set \a instanceCount to a value other than 1. When
11887 drawing multiple instances, the first instance ID is specified by \a
11888 firstInstance.
11889
11890 \note \a firstInstance may not be supported, and is ignored when the
11891 QRhi::BaseInstance feature is reported as not supported. The first instance
11892 ID is always 0 in that case. QRhi::BaseInstance is never supported with
11893 OpenGL ES, and therefore portable applications should not be designed to
11894 rely on this argument.
11895
11896 \note Shaders that need to access the index of the current vertex or
11897 instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
11898 Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
11899 gl_InstanceID.
11900
11901 \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
11902 include the base value with some of the underlying 3D APIs. This is
11903 indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
11904 on a base instance value cannot be avoided, applications are advised to pass
11905 in the value as a uniform conditionally based on what that feature reports,
11906 and add it to \c gl_InstanceIndex in the shader.
11907
11908 \note This function can only be called inside a render pass, meaning
11909 between a beginPass() and endPass() call.
11910 */
11911void QRhiCommandBuffer::drawIndexed(quint32 indexCount,
11912 quint32 instanceCount,
11913 quint32 firstIndex,
11914 qint32 vertexOffset,
11915 quint32 firstInstance)
11916{
11917 m_rhi->drawIndexed(this, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
11918}
11919
11920/*!
11921 Records a non-indexed, indirect draw.
11922
11923 The draw parameters are provided by the buffer specified in \a indirectBuffer,
11924 which must contain an array of elements of type QRhiIndirectDrawCommand.
11925 The parameters in QRhiIndirectDrawCommand have the same meaning as in draw().
11926
11927 The offset, in bytes, from which the parameters are read in the buffer is specified
11928 by \a indirectBufferOffset.
11929
11930 \a drawCount specifies the number of such draw commands to issue.
11931
11932 \a stride indicates the byte size of each individual draw command structure
11933 in the buffer. This allows interleaving custom data between commands if needed.
11934 The value must be a multiple of 4 and greater than or equal to sizeof(QRhiIndirectDrawCommand).
11935
11936 \note A \a drawCount value greater than 1 is only natively supported if the
11937 QRhi::DrawIndirectMulti feature is reported as supported.
11938 Otherwise, this function emulates multi-draw by recording multiple draw calls,
11939 offering no performance benefit over repeated draw() calls.
11940
11941 \note Leaving \a stride at its default is recommended whenever performance
11942 matters. With Direct 3D 12 a non-default stride prevents issuing a single
11943 native multi-draw, forcing the backend to record one command per draw
11944 instead. For a large \a drawCount this can be an order of magnitude slower,
11945 which defeats the purpose of the indirect draw. Vulkan, OpenGL, and Metal
11946 pass the stride on to their native multi-draw entry points and are not
11947 affected. Rather than interleaving custom data between the commands, keep
11948 that data in a separate buffer and index into it.
11949
11950 \note The render pass interruption and the render target consequences and
11951 limitations described for drawIndexedIndirect() apply here as well.
11952
11953 \note Therefore, portable applications should consider always using
11954 QRhiIndirectCommandBuffer and executeIndirect() instead of the
11955 draw*Indirect*() family of functions.
11956
11957 \note This function can only be called inside a render pass, meaning
11958 between a beginPass() and endPass() call.
11959
11960 \since 6.12
11961
11962 \sa drawIndexedIndirect(), drawIndirectCount(), drawIndexedIndirectCount()
11963 */
11964void QRhiCommandBuffer::drawIndirect(QRhiBuffer *indirectBuffer,
11965 quint32 indirectBufferOffset,
11966 quint32 drawCount,
11967 quint32 stride)
11968{
11969 Q_ASSERT(indirectBuffer);
11970 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
11971 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
11972 Q_ASSERT(stride >= sizeof(QRhiIndirectDrawCommand));
11973 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
11974 m_rhi->drawIndirect(this, indirectBuffer, indirectBufferOffset, drawCount, stride);
11975}
11976
11977/*!
11978 Records an indexed, indirect draw.
11979
11980 The draw parameters are provided by the buffer specified in \a indirectBuffer,
11981 which must contain an array of elements of type QRhiIndexedIndirectDrawCommand.
11982 The parameters in QRhiIndexedIndirectDrawCommand have the same meaning as in drawIndexed().
11983
11984 The offset, in bytes, from which the parameters are read in the buffer is specified
11985 by \a indirectBufferOffset.
11986
11987 \a drawCount specifies the number of such draw commands to issue.
11988
11989 \a stride indicates the byte size of each individual draw command structure
11990 in the buffer. This allows interleaving custom data between commands if needed.
11991 The value must be a multiple of 4 and greater than or equal to sizeof(QRhiIndexedIndirectDrawCommand).
11992
11993 \note A \a drawCount value greater than 1 is only natively supported if the
11994 QRhi::DrawIndirectMulti feature is reported as supported.
11995 Otherwise, this function emulates multi-draw by recording multiple draw calls,
11996 offering no performance benefit over repeated drawIndexed() calls.
11997
11998 \note Leaving \a stride at its default is recommended whenever performance
11999 matters. With Direct 3D 12 a non-default stride prevents issuing a single
12000 native multi-draw, forcing the backend to record one command per draw
12001 instead. For a large \a drawCount this can be an order of magnitude slower,
12002 which defeats the purpose of the indirect draw. Vulkan, OpenGL, and Metal
12003 pass the stride on to their native multi-draw entry points and are not
12004 affected. Rather than interleaving custom data between the commands, keep
12005 that data in a separate buffer and index into it.
12006
12007 \note With some backends a large \a drawCount is implemented by interrupting
12008 and then restarting the render pass internally due to launching a compute
12009 kernel to encode commands into an indirect command buffer. With Metal this
12010 happens above a certain \a drawCount (e.g., 128). This has consequences for
12011 the render targets: color attachment contents are preserved automatically,
12012 but a QRhiRenderBuffer serving as the depth-stencil buffer only keeps its
12013 contents if it was created with QRhiRenderBuffer::NoTransientBacking, which
12014 means that, with Metal, rendering errors may occur if the depth-stencil
12015 buffer is a QRhiRenderBuffer without the NoTransientBacking flag and the \a
12016 drawCount is above the threshold. Recording the same commands into a
12017 QRhiIndirectCommandBuffer and issuing them with executeIndirect() avoids
12018 this altogether: that never interrupts the pass.
12019
12020 \note Therefore, portable applications should consider always using
12021 QRhiIndirectCommandBuffer and executeIndirect() instead of the
12022 draw*Indirect*() family of functions.
12023
12024 \note This function can only be called inside a render pass, meaning
12025 between a beginPass() and endPass() call.
12026
12027 \since 6.12
12028
12029 \sa drawIndirect(), drawIndirectCount(), drawIndexedIndirectCount()
12030 */
12031void QRhiCommandBuffer::drawIndexedIndirect(QRhiBuffer *indirectBuffer,
12032 quint32 indirectBufferOffset,
12033 quint32 drawCount,
12034 quint32 stride)
12035{
12036 Q_ASSERT(indirectBuffer);
12037 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12038 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12039 Q_ASSERT(stride >= sizeof(QRhiIndexedIndirectDrawCommand));
12040 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
12041 m_rhi->drawIndexedIndirect(this, indirectBuffer, indirectBufferOffset, drawCount, stride);
12042}
12043
12044/*!
12045 Records a non-indexed, indirect draw, with the draw count itself read
12046 from a buffer at execution time.
12047
12048 Draw parameters are read from \a indirectBuffer at byte offset
12049 \a indirectBufferOffset as an array of QRhiIndirectDrawCommand entries
12050 spaced \a stride bytes apart. The number of draws issued is the 32-bit
12051 unsigned integer stored at \a countBufferOffset in \a countBuffer, clamped
12052 to \a maxDrawCount.
12053
12054 Both buffers must have QRhiBuffer::IndirectBuffer usage. Offsets must be
12055 4-byte aligned; \a stride must be 4-byte aligned and at least
12056 sizeof(QRhiIndirectDrawCommand).
12057
12058 Only available when \l QRhi::DrawIndirectCount is reported as supported.
12059 On other backends this is a no-op and a warning is logged. With Metal there
12060 are additional requirements, see QRhi::DrawIndirectCount.
12061
12062 \note Unlike with drawIndirect(), a non-default \a stride does not prevent
12063 the use of a single native multi-draw here. With Direct 3D 12 it does mean
12064 that an additional command signature is created and cached for each
12065 distinct stride value, so sticking to one stride is still preferable.
12066
12067 \note The value in \a countBuffer is read as a \e signed 32-bit integer by
12068 OpenGL, unlike the other backends. Counts above \c INT_MAX are therefore
12069 not portable, and neither is relying on any particular behavior for a count
12070 that exceeds \a maxDrawCount, beyond the clamping described above.
12071
12072 \note With some backends, Metal in particular, the render pass is always
12073 interrupted and restarted internally because the draw commands have to be
12074 encoded on the GPU. Color attachment contents are preserved automatically,
12075 but a QRhiRenderBuffer serving as the depth-stencil buffer only keeps its
12076 contents if it was created with QRhiRenderBuffer::NoTransientBacking.
12077 Building a QRhiIndirectCommandBuffer with buildIndirect(),
12078 which happens before the pass begins, and issuing it with
12079 executeIndirect() avoids this: that never interrupts the pass, and supports
12080 a device-side count just the same.
12081
12082 \note Therefore, portable applications should consider always using
12083 QRhiIndirectCommandBuffer and executeIndirect() instead of the
12084 draw*Indirect*() family of functions.
12085
12086 \note \a maxDrawCount is not a free upper bound. With Metal it sizes the
12087 indirect command buffer that the draw commands are encoded into, and that
12088 buffer is shared, grows on demand, and is never shrunk again for the
12089 lifetime of the QRhi. It also determines how many encoding threads are
12090 dispatched every time. Passing the capacity of \a indirectBuffer instead of
12091 a realistic upper bound therefore has a real cost.
12092
12093 \note Only valid inside a render pass.
12094
12095 \since 6.13
12096
12097 \sa drawIndirect(), drawIndexedIndirect(), drawIndexedIndirectCount()
12098 */
12099void QRhiCommandBuffer::drawIndirectCount(QRhiBuffer *indirectBuffer,
12100 quint32 indirectBufferOffset,
12101 QRhiBuffer *countBuffer,
12102 quint32 countBufferOffset,
12103 quint32 maxDrawCount,
12104 quint32 stride)
12105{
12106 Q_ASSERT(indirectBuffer);
12107 Q_ASSERT(countBuffer);
12108 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12109 Q_ASSERT(countBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12110 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12111 Q_ASSERT_X((countBufferOffset & 3u) == 0u, Q_FUNC_INFO, "countBufferOffset must be a multiple of 4");
12112 Q_ASSERT(stride >= sizeof(QRhiIndirectDrawCommand));
12113 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
12114 m_rhi->drawIndirectCount(this, indirectBuffer, indirectBufferOffset,
12115 countBuffer, countBufferOffset, maxDrawCount, stride);
12116}
12117
12118/*!
12119 Indexed variant of drawIndirectCount(). \a indirectBuffer contains, at byte
12120 offset \a indirectBufferOffset, QRhiIndexedIndirectDrawCommand entries,
12121 spaced \a stride bytes apart, and \a stride must be at least
12122 sizeof(QRhiIndexedIndirectDrawCommand). All other requirements, including
12123 how \a countBuffer, \a countBufferOffset and \a maxDrawCount are
12124 interpreted, are as described for drawIndirectCount().
12125
12126 \note The render pass interruption described for drawIndirectCount() applies
12127 here as well.
12128
12129 \note Therefore, portable applications should consider always using
12130 QRhiIndirectCommandBuffer and executeIndirect() instead of the
12131 draw*Indirect*() family of functions.
12132
12133 \note Only valid inside a render pass.
12134
12135 \since 6.13
12136
12137 \sa drawIndirect(), drawIndexedIndirect(), drawIndirectCount()
12138 */
12139void QRhiCommandBuffer::drawIndexedIndirectCount(QRhiBuffer *indirectBuffer,
12140 quint32 indirectBufferOffset,
12141 QRhiBuffer *countBuffer,
12142 quint32 countBufferOffset,
12143 quint32 maxDrawCount,
12144 quint32 stride)
12145{
12146 Q_ASSERT(indirectBuffer);
12147 Q_ASSERT(countBuffer);
12148 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12149 Q_ASSERT(countBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12150 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12151 Q_ASSERT_X((countBufferOffset & 3u) == 0u, Q_FUNC_INFO, "countBufferOffset must be a multiple of 4");
12152 Q_ASSERT(stride >= sizeof(QRhiIndexedIndirectDrawCommand));
12153 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
12154 m_rhi->drawIndexedIndirectCount(this, indirectBuffer, indirectBufferOffset,
12155 countBuffer, countBufferOffset, maxDrawCount, stride);
12156}
12157
12158/*!
12159 Records populating the indirect command buffer \a icb from the buffer and
12160 parameters described by \a info.
12161
12162 This is the GPU-driven counterpart of recording draw() or drawIndexed()
12163 calls on the QRhiIndirectCommandBuffer: the commands come from
12164 \c{info.sourceBuffer}, which is typically written by a compute shader
12165 earlier in the frame. Any commands recorded on the CPU side are ignored
12166 from this point on.
12167
12168 \c{info.topology} and, for an indirect command buffer of type
12169 QRhiIndirectCommandBuffer::IndexedDraws, \c{info.indexBuffer} have to be
12170 specified because some backends need them in order to build their native
12171 indirect command buffer object, and neither is available outside of a
12172 render pass. They must match what is set on the command buffer when
12173 executeIndirect() is called.
12174
12175 \c{info.commandCount} is the number of commands to take from
12176 \c{info.sourceBuffer}, and becomes what
12177 QRhiIndirectCommandBuffer::commandCount() reports from here on. Leaving it
12178 at 0 means \a{icb}'s QRhiIndirectCommandBuffer::maxCommandCount(); a larger
12179 value is clamped to that, with a warning. The size of
12180 \c{info.sourceBuffer} is not consulted. When \c{info.countBuffer} is set,
12181 \c{info.commandCount} becomes an upper bound instead, with the device-side
12182 count deciding how many commands are executed.
12183
12184 \note This function must be called outside of any pass. That is the entire
12185 point: it gives backends that need to run a compute shader in order to
12186 build their native indirect command buffer a place to do so without having
12187 to interrupt and restart the render pass.
12188
12189 \sa executeIndirect(), QRhiIndirectCommandBuffer
12190 */
12191void QRhiCommandBuffer::buildIndirect(QRhiIndirectCommandBuffer *icb,
12192 const QRhiIndirectCommandBufferBuildInfo &info)
12193{
12194 Q_ASSERT(icb);
12195 Q_ASSERT(info.sourceBuffer);
12196 Q_ASSERT(info.sourceBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12197 Q_ASSERT_X((info.sourceBufferOffset & 3u) == 0u, Q_FUNC_INFO,
12198 "sourceBufferOffset must be a multiple of 4");
12199 Q_ASSERT_X((info.stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
12200 Q_ASSERT(!info.countBuffer || info.countBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12201 Q_ASSERT_X((info.countBufferOffset & 3u) == 0u, Q_FUNC_INFO,
12202 "countBufferOffset must be a multiple of 4");
12203 m_rhi->buildIndirect(this, icb, info);
12204}
12205
12206/*!
12207 Records executing the commands held by the indirect command buffer \a icb,
12208 starting at \a firstCommand and executing at most \a commandCount of them.
12209 By default all commands are executed.
12210
12211 Everything else - the graphics pipeline, the vertex and index buffers, the
12212 shader resources, the viewport, the scissor - is taken from the current
12213 state of the command buffer, exactly like with drawIndirect().
12214
12215 The number of draws issued is \c{qMin(commandCount, icb->commandCount() -
12216 firstCommand)}, so leaving \a commandCount at its default executes
12217 everything from \a firstCommand onwards. What
12218 QRhiIndirectCommandBuffer::commandCount() means depends on how \a icb was
12219 populated: it is the number of draw() and drawIndexed() calls recorded on
12220 it, or, after a buildIndirect(), the count resolved from
12221 QRhiIndirectCommandBufferBuildInfo::commandCount. Nothing is drawn when \a
12222 firstCommand is at or past that count.
12223
12224 When \a icb was populated by recording draw() or drawIndexed() calls on it,
12225 the recorded contents must have been flushed with
12226 QRhiResourceUpdateBatch::commitIndirectCommandBuffer() beforehand. When it
12227 was populated with buildIndirect(), and a count buffer was specified there,
12228 the device-side count reduces the number of draws further: the number
12229 actually executed is the smallest of that, \a commandCount, and what is
12230 left in \a icb after \a firstCommand.
12231
12232 \warning With a count buffer some backends, Metal in particular, cannot combine
12233 the device-side count with a subrange. \a firstCommand and \a commandCount
12234 are then ignored, printing a warning, and all commands up to the device-side
12235 count are executed.
12236
12237 \note An indirect command buffer that was populated by recording draw() or
12238 drawIndexed() calls on it can be executed any number of times, but within
12239 one frame all those executions must use the same topology, index buffer,
12240 index buffer offset and index format: some backends bake these into their
12241 native indirect command buffer at the first executeIndirect() of the frame.
12242 A mismatch is reported with a warning, and handled by falling back to
12243 ordinary draw calls.
12244
12245 \note Unlike drawIndirect(), drawIndexedIndirect(), drawIndirectCount() and
12246 drawIndexedIndirectCount(), this never causes the render pass to be
12247 interrupted and restarted internally, whatever the number of commands.
12248 Commands built with buildIndirect() were prepared before the pass began, and
12249 CPU-recorded ones need no compute work to encode. The consequences described
12250 for those functions therefore do not apply here. Color attachment contents
12251 are not at risk, and a QRhiRenderBuffer serving as the depth-stencil buffer
12252 keeps its contents without needing QRhiRenderBuffer::NoTransientBacking.
12253
12254 \note The CPU cost of this call is not constant for a CPU-recorded indirect
12255 command buffer. When the recorded contents changed since the last execution,
12256 some backends do their per-command native encoding here rather than in
12257 QRhiResourceUpdateBatch::commitIndirectCommandBuffer(), which for a large
12258 command set re-recorded every frame can dominate the time spent between
12259 beginPass() and endPass(). See \l QRhiIndirectCommandBuffer for how the cost
12260 of CPU recording scales.
12261
12262 \note This function can only be called inside a render pass.
12263
12264 \sa buildIndirect(), drawIndirect(), QRhiIndirectCommandBuffer
12265 */
12266void QRhiCommandBuffer::executeIndirect(QRhiIndirectCommandBuffer *icb,
12267 quint32 firstCommand,
12268 quint32 commandCount)
12269{
12270 Q_ASSERT(icb);
12271 m_rhi->executeIndirect(this, icb, firstCommand, commandCount);
12272}
12273
12274/*!
12275 Records a named debug group on the command buffer with the specified \a
12276 name. This is shown in graphics debugging tools such as
12277 \l{https://renderdoc.org/}{RenderDoc} and
12278 \l{https://developer.apple.com/xcode/}{XCode}. The end of the grouping is
12279 indicated by debugMarkEnd().
12280
12281 \note Ignored when QRhi::DebugMarkers are not supported or
12282 QRhi::EnableDebugMarkers is not set.
12283
12284 \note Can be called anywhere within the frame, both inside and outside of passes.
12285 */
12286void QRhiCommandBuffer::debugMarkBegin(const QByteArray &name)
12287{
12288 m_rhi->debugMarkBegin(this, name);
12289}
12290
12291/*!
12292 Records the end of a debug group.
12293
12294 \note Ignored when QRhi::DebugMarkers are not supported or
12295 QRhi::EnableDebugMarkers is not set.
12296
12297 \note Can be called anywhere within the frame, both inside and outside of passes.
12298 */
12299void QRhiCommandBuffer::debugMarkEnd()
12300{
12301 m_rhi->debugMarkEnd(this);
12302}
12303
12304/*!
12305 Inserts a debug message \a msg into the command stream.
12306
12307 \note Ignored when QRhi::DebugMarkers are not supported or
12308 QRhi::EnableDebugMarkers is not set.
12309
12310 \note With some backends debugMarkMsg() is only supported inside a pass and
12311 is ignored when called outside a pass. With others it is recorded anywhere
12312 within the frame.
12313 */
12314void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)
12315{
12316 m_rhi->debugMarkMsg(this, msg);
12317}
12318
12319/*!
12320 Records starting a new compute pass.
12321
12322 \a resourceUpdates, when not null, specifies a resource update batch that
12323 is to be committed and then released.
12324
12325 \note Do not assume that any state or resource bindings persist between
12326 passes.
12327
12328 \note A compute pass can record setComputePipeline(), setShaderResources(),
12329 and dispatch() calls, not graphics ones. General functionality, such as,
12330 debug markers and beginExternal() is available both in render and compute
12331 passes.
12332
12333 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
12334 is reported as supported.
12335
12336 \a flags is not currently used.
12337 */
12338void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates, BeginPassFlags flags)
12339{
12340 m_rhi->beginComputePass(this, resourceUpdates, flags);
12341}
12342
12343/*!
12344 Records ending the current compute pass.
12345
12346 \a resourceUpdates, when not null, specifies a resource update batch that
12347 is to be committed and then released.
12348 */
12349void QRhiCommandBuffer::endComputePass(QRhiResourceUpdateBatch *resourceUpdates)
12350{
12351 m_rhi->endComputePass(this, resourceUpdates);
12352}
12353
12354/*!
12355 Records setting a new compute pipeline \a ps.
12356
12357 \note This function must be called before recording setShaderResources() or
12358 dispatch() commands on the command buffer.
12359
12360 \note QRhi will optimize out unnecessary invocations within a pass, so
12361 therefore overoptimizing to avoid calls to this function is not necessary
12362 on the applications' side.
12363
12364 \note This function can only be called inside a compute pass, meaning
12365 between a beginComputePass() and endComputePass() call.
12366 */
12367void QRhiCommandBuffer::setComputePipeline(QRhiComputePipeline *ps)
12368{
12369 m_rhi->setComputePipeline(this, ps);
12370}
12371
12372/*!
12373 Records dispatching compute work items, with \a x, \a y, and \a z
12374 specifying the number of local workgroups in the corresponding dimension.
12375
12376 \note This function can only be called inside a compute pass, meaning
12377 between a beginComputePass() and endComputePass() call.
12378
12379 \note \a x, \a y, and \a z must fit the limits from the underlying graphics
12380 API implementation at run time. The maximum values are typically 65535.
12381
12382 \note Watch out for possible limits on the local workgroup size as well.
12383 This is specified in the shader, for example: \c{layout(local_size_x = 16,
12384 local_size_y = 16) in;}. For example, with OpenGL the minimum value mandated
12385 by the specification for the number of invocations in a single local work
12386 group (the product of \c local_size_x, \c local_size_y, and \c local_size_z)
12387 is 1024, while with OpenGL ES (3.1) the value may be as low as 128. This
12388 means that the example given above may be rejected by some OpenGL ES
12389 implementations as the number of invocations is 256.
12390 */
12391void QRhiCommandBuffer::dispatch(int x, int y, int z)
12392{
12393 m_rhi->dispatch(this, x, y, z);
12394}
12395
12396/*!
12397 Records an indirect compute dispatch.
12398
12399 The work group counts are read by the device from \a indirectBuffer at
12400 \a indirectBufferOffset, as a single QRhiDispatchIndirectCommand.
12401 \a indirectBuffer must have QRhiBuffer::IndirectBuffer usage and
12402 \a indirectBufferOffset must be 4-byte aligned.
12403
12404 Only one dispatch per call; no native multi-dispatch variant exists.
12405 Requires \l QRhi::DispatchIndirect.
12406
12407 \note Only valid inside a compute pass.
12408
12409 \since 6.13
12410 */
12411void QRhiCommandBuffer::dispatchIndirect(QRhiBuffer *indirectBuffer,
12412 quint32 indirectBufferOffset)
12413{
12414 Q_ASSERT(indirectBuffer);
12415 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12416 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12417 m_rhi->dispatchIndirect(this, indirectBuffer, indirectBufferOffset);
12418}
12419
12420/*!
12421 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
12422 QRhiVulkanCommandBufferNativeHandles. The returned value is \nullptr when
12423 exposing the underlying native resources is not supported by, or not
12424 applicable to, the backend.
12425
12426 \sa QRhiVulkanCommandBufferNativeHandles,
12427 QRhiMetalCommandBufferNativeHandles, beginExternal(), endExternal()
12428 */
12429const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
12430{
12431 return m_rhi->nativeHandles(this);
12432}
12433
12434/*!
12435 To be called when the application before the application is about to
12436 enqueue commands to the current pass' command buffer by calling graphics
12437 API functions directly.
12438
12439 \note This is only available when the intent was declared upfront in
12440 beginPass() or beginComputePass(). Therefore this function must only be
12441 called when the pass recording was started with specifying
12442 QRhiCommandBuffer::ExternalContent.
12443
12444 With Vulkan, Metal, or Direct3D 12 one can query the native command buffer
12445 or encoder objects via nativeHandles() and enqueue commands to them. With
12446 OpenGL or Direct3D 11 the (device) context can be retrieved from
12447 QRhi::nativeHandles(). However, this must never be done without ensuring
12448 the QRhiCommandBuffer's state stays up-to-date. Hence the requirement for
12449 wrapping any externally added command recording between beginExternal() and
12450 endExternal(). Conceptually this is the same as QPainter's
12451 \l{QPainter::beginNativePainting()}{beginNativePainting()} and
12452 \l{QPainter::endNativePainting()}{endNativePainting()} functions.
12453
12454 For OpenGL in particular, this function has an additional task: it makes
12455 sure the context is made current on the current thread.
12456
12457 \note Once beginExternal() is called, no other render pass specific
12458 functions (\c set* or \c draw*) must be called on the
12459 QRhiCommandBuffer until endExternal().
12460
12461 \warning Some backends may return a native command buffer object from
12462 QRhiCommandBuffer::nativeHandles() that is different from the primary one
12463 when inside a beginExternal() - endExternal() block. Therefore it is
12464 important to (re)query the native command buffer object after calling
12465 beginExternal(). In practical terms this means that with Vulkan for example
12466 the externally recorded Vulkan commands are placed onto a secondary command
12467 buffer (with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT).
12468 nativeHandles() returns this secondary command buffer when called between
12469 begin/endExternal.
12470
12471 \sa endExternal(), nativeHandles()
12472 */
12473void QRhiCommandBuffer::beginExternal()
12474{
12475 m_rhi->beginExternal(this);
12476}
12477
12478/*!
12479 To be called once the externally added commands are recorded to the command
12480 buffer or context.
12481
12482 \note All QRhiCommandBuffer state must be assumed as invalid after calling
12483 this function. Pipelines, vertex and index buffers, and other state must be
12484 set again if more draw calls are recorded after the external commands.
12485
12486 \sa beginExternal(), nativeHandles()
12487 */
12488void QRhiCommandBuffer::endExternal()
12489{
12490 m_rhi->endExternal(this);
12491}
12492
12493/*!
12494 \return the last available timestamp, in seconds, when
12495 \l QRhi::EnableTimestamps was enabled when creating the QRhi. The value
12496 indicates the elapsed time on the GPU during the last completed frame.
12497
12498 \note Do not expect results other than 0 when the QRhi::Timestamps feature
12499 is not reported as supported, or when QRhi::EnableTimestamps was not passed
12500 to QRhi::create(). There are exceptions to this, because with some graphics
12501 APIs (Metal) timings are available without having to perform extra
12502 operations (timestamp queries), but portable applications should always
12503 consciously opt-in to timestamp collection when they know it is needed, and
12504 call this function accordingly.
12505
12506 Care must be exercised with the interpretation of the value, as its
12507 precision and granularity is often not controlled by Qt, and depends on the
12508 underlying graphics API and its implementation. In particular, comparing
12509 the values between different graphics APIs and hardware is discouraged and
12510 may be meaningless.
12511
12512 The timing values will likely become available asynchronously. The returned
12513 value may therefore be 0 (e.g., for the first 1-2 frames) or the last known
12514 value referring to some previous frame. The value my also become 0 again
12515 under certain conditions, such as when resizing the window. It can be
12516 expected that the most up-to-date available value is retrieved in
12517 beginFrame() and becomes queriable via this function once beginFrame()
12518 returns.
12519
12520 \note Do not assume that the value refers to the previous
12521 (\c{currently_recorded - 1}) frame. It may refer to \c{currently_recorded -
12522 2} or \c{currently_recorded - 3} as well. The exact behavior may depend on
12523 the graphics API and its implementation.
12524
12525 Watch out for the consequences of GPU frequency scaling and GPU clock
12526 changes, depending on the platform. For example, on Windows the returned
12527 timing may vary in a quite wide range between frames with modern graphics
12528 cards, even when submitting frames with a similar, or the same workload.
12529 This is out of scope for Qt to control and solve, generally speaking.
12530 However, the D3D12 backend automatically calls
12531 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-setstablepowerstate}{ID3D12Device::SetStablePowerState()}
12532 whenever the environment variable \c QT_D3D_STABLE_POWER_STATE is set to a
12533 non-zero value. This can greatly stabilize the result. It can also have a
12534 non-insignificant effect on the CPU-side timings measured via QElapsedTimer
12535 for example, especially when offscreen frames are involved.
12536
12537 \note Do not and never ship applications to production with
12538 \c QT_D3D_STABLE_POWER_STATE set. See the Windows API documentation for details.
12539
12540 \sa QRhi::Timestamps, QRhi::EnableTimestamps
12541 */
12542double QRhiCommandBuffer::lastCompletedGpuTime()
12543{
12544 return m_rhi->lastCompletedGpuTime(this);
12545}
12546
12547/*!
12548 \return the value (typically an offset) \a v aligned to the uniform buffer
12549 alignment given by ubufAlignment().
12550 */
12551int QRhi::ubufAligned(int v) const
12552{
12553 const int byteAlign = ubufAlignment();
12554 return (v + byteAlign - 1) & ~(byteAlign - 1);
12555}
12556
12557/*!
12558 \return the number of mip levels for a given \a size.
12559 */
12560int QRhi::mipLevelsForSize(const QSize &size)
12561{
12562 return qFloor(std::log2(qMax(size.width(), size.height()))) + 1;
12563}
12564
12565/*!
12566 \return the texture image size for a given \a mipLevel, calculated based on
12567 the level 0 size given in \a baseLevelSize.
12568 */
12569QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)
12570{
12571 const int w = qMax(1, baseLevelSize.width() >> mipLevel);
12572 const int h = qMax(1, baseLevelSize.height() >> mipLevel);
12573 return QSize(w, h);
12574}
12575
12576/*!
12577 \return \c true if the underlying graphics API has the Y axis pointing up
12578 in framebuffers and images.
12579
12580 In practice this is \c true for OpenGL only.
12581 */
12582bool QRhi::isYUpInFramebuffer() const
12583{
12584 return d->isYUpInFramebuffer();
12585}
12586
12587/*!
12588 \return \c true if the underlying graphics API has the Y axis pointing up
12589 in its normalized device coordinate system.
12590
12591 In practice this is \c false for Vulkan only.
12592
12593 \note clipSpaceCorrMatrix() includes the corresponding adjustment (to make
12594 Y point up) in its returned matrix.
12595 */
12596bool QRhi::isYUpInNDC() const
12597{
12598 return d->isYUpInNDC();
12599}
12600
12601/*!
12602 \return \c true if the underlying graphics API uses depth range [0, 1] in
12603 clip space.
12604
12605 In practice this is \c false for OpenGL only, because OpenGL uses a
12606 post-projection depth range of [-1, 1]. (not to be confused with the
12607 NDC-to-window mapping controlled by glDepthRange(), which uses a range of
12608 [0, 1], unless overridden by the QRhiViewport) In some OpenGL versions
12609 glClipControl() could be used to change this, but the OpenGL backend of
12610 QRhi does not use that function as it is not available in OpenGL ES or
12611 OpenGL versions lower than 4.5.
12612
12613 \note clipSpaceCorrMatrix() includes the corresponding adjustment in its
12614 returned matrix. Therefore, many users of QRhi do not need to take any
12615 further measures apart from pre-multiplying their projection matrices with
12616 clipSpaceCorrMatrix(). However, some graphics techniques, such as, some
12617 types of shadow mapping, involve working with and outputting depth values
12618 in the shaders. These will need to query and take the value of this
12619 function into account as appropriate.
12620 */
12621bool QRhi::isClipDepthZeroToOne() const
12622{
12623 return d->isClipDepthZeroToOne();
12624}
12625
12626/*!
12627 \return a matrix that can be used to allow applications keep using
12628 OpenGL-targeted vertex data and perspective projection matrices (such as,
12629 the ones generated by QMatrix4x4::perspective()), regardless of the active
12630 QRhi backend.
12631
12632 In a typical renderer, once \c{this_matrix * mvp} is used instead of just
12633 \c mvp, vertex data with Y up and viewports with depth range 0 - 1 can be
12634 used without considering what backend (and so graphics API) is going to be
12635 used at run time. This way branching based on isYUpInNDC() and
12636 isClipDepthZeroToOne() can be avoided (although such logic may still become
12637 required when implementing certain advanced graphics techniques).
12638
12639 See
12640 \l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this
12641 page} for a discussion of the topic from Vulkan perspective.
12642 */
12643QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
12644{
12645 return d->clipSpaceCorrMatrix();
12646}
12647
12648/*!
12649 \return \c true if the specified texture \a format modified by \a flags is
12650 supported.
12651
12652 The query is supported both for uncompressed and compressed formats.
12653 */
12654bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
12655{
12656 return d->isTextureFormatSupported(format, flags);
12657}
12658
12659/*!
12660 \return \c true if the specified \a feature is supported
12661 */
12662bool QRhi::isFeatureSupported(QRhi::Feature feature) const
12663{
12664 return d->isFeatureSupported(feature);
12665}
12666
12667/*!
12668 \return the value for the specified resource \a limit.
12669
12670 The values are expected to be queried by the backends upon initialization,
12671 meaning calling this function is a light operation.
12672 */
12673int QRhi::resourceLimit(ResourceLimit limit) const
12674{
12675 return d->resourceLimit(limit);
12676}
12677
12678/*!
12679 \return a pointer to the backend-specific collection of native objects
12680 for the device, context, and similar concepts used by the backend.
12681
12682 Cast to QRhiVulkanNativeHandles, QRhiD3D11NativeHandles,
12683 QRhiD3D12NativeHandles, QRhiGles2NativeHandles, or QRhiMetalNativeHandles
12684 as appropriate.
12685
12686 \note No ownership is transferred, neither for the returned pointer nor for
12687 any native objects.
12688 */
12689const QRhiNativeHandles *QRhi::nativeHandles()
12690{
12691 return d->nativeHandles();
12692}
12693
12694/*!
12695 With OpenGL this makes the OpenGL context current on the current thread.
12696 The function has no effect with other backends.
12697
12698 Calling this function is relevant typically in Qt framework code, when one
12699 has to ensure external OpenGL code provided by the application can still
12700 run like it did before with direct usage of OpenGL, as long as the QRhi is
12701 using the OpenGL backend.
12702
12703 \return false when failed, similarly to QOpenGLContext::makeCurrent(). When
12704 the operation failed, isDeviceLost() can be called to determine if there
12705 was a loss of context situation. Such a check is equivalent to checking via
12706 QOpenGLContext::isValid().
12707
12708 \sa QOpenGLContext::makeCurrent(), QOpenGLContext::isValid()
12709 */
12710bool QRhi::makeThreadLocalNativeContextCurrent()
12711{
12712 return d->makeThreadLocalNativeContextCurrent();
12713}
12714
12715/*!
12716 With backends and graphics APIs where applicable, this function allows to
12717 provide additional arguments to the \b next submission of commands to the
12718 graphics command queue.
12719
12720 In particular, with Vulkan this allows passing in a list of Vulkan semaphore
12721 objects for \c vkQueueSubmit() to signal and wait on. \a params must then be
12722 a \l QRhiVulkanQueueSubmitParams. This becomes essential in certain advanced
12723 use cases, such as when performing native Vulkan calls that involve having
12724 to wait on and signal VkSemaphores that the application's custom Vulkan
12725 rendering or compute code manages. In addition, this also allows specifying
12726 additional semaphores to wait on in the next \c vkQueuePresentKHR().
12727
12728 \note This function affects the next queue submission only, which will
12729 happen in endFrame(), endOffscreenFrame(), or finish(). The enqueuing of
12730 present happens in endFrame().
12731
12732 With many other backends the implementation of this function is a no-op.
12733
12734 \since 6.9
12735 */
12736void QRhi::setQueueSubmitParams(QRhiNativeHandles *params)
12737{
12738 d->setQueueSubmitParams(params);
12739}
12740
12741/*!
12742 Attempts to release resources in the backend's caches. This can include both
12743 CPU and GPU resources. Only memory and resources that can be recreated
12744 automatically are in scope. As an example, if the backend's
12745 QRhiGraphicsPipeline implementation maintains a cache of shader compilation
12746 results, calling this function leads to emptying that cache, thus
12747 potentially freeing up memory and graphics resources.
12748
12749 Calling this function makes sense in resource constrained environments,
12750 where at a certain point there is a need to ensure minimal resource usage,
12751 at the expense of performance.
12752 */
12753void QRhi::releaseCachedResources()
12754{
12755 d->releaseCachedResources();
12756
12757 for (QRhiResourceUpdateBatch *u : d->resUpdPool) {
12758 if (u->d->poolIndex < 0)
12759 u->d->trimOpLists();
12760 }
12761}
12762
12763/*!
12764 \return true if the graphics device was lost.
12765
12766 The loss of the device is typically detected in beginFrame(), endFrame() or
12767 QRhiSwapChain::createOrResize(), depending on the backend and the underlying
12768 native APIs. The most common is endFrame() because that is where presenting
12769 happens. With some backends QRhiSwapChain::createOrResize() can also fail
12770 due to a device loss. Therefore this function is provided as a generic way
12771 to check if a device loss was detected by a previous operation.
12772
12773 When the device is lost, no further operations should be done via the QRhi.
12774 Rather, all QRhi resources should be released, followed by destroying the
12775 QRhi. A new QRhi can then be attempted to be created. If successful, all
12776 graphics resources must be reinitialized. If not, try again later,
12777 repeatedly.
12778
12779 While simple applications may decide to not care about device loss,
12780 on the commonly used desktop platforms a device loss can happen
12781 due to a variety of reasons, including physically disconnecting the
12782 graphics adapter, disabling the device or driver, uninstalling or upgrading
12783 the graphics driver, or due to errors that lead to a graphics device reset.
12784 Some of these can happen under perfectly normal circumstances as well, for
12785 example the upgrade of the graphics driver to a newer version is a common
12786 task that can happen at any time while a Qt application is running. Users
12787 may very well expect applications to be able to survive this, even when the
12788 application is actively using an API like OpenGL or Direct3D.
12789
12790 Qt's own frameworks built on top of QRhi, such as, Qt Quick, can be
12791 expected to handle and take appropriate measures when a device loss occurs.
12792 If the data for graphics resources, such as textures and buffers, are still
12793 available on the CPU side, such an event may not be noticeable on the
12794 application level at all since graphics resources can seamlessly be
12795 reinitialized then. However, applications and libraries working directly
12796 with QRhi are expected to be prepared to check and handle device loss
12797 situations themselves.
12798
12799 \note With OpenGL, applications may need to opt-in to context reset
12800 notifications by setting QSurfaceFormat::ResetNotification on the
12801 QOpenGLContext. This is typically done by enabling the flag in
12802 QRhiGles2InitParams::format. Keep in mind however that some systems may
12803 generate context resets situations even when this flag is not set.
12804 */
12805bool QRhi::isDeviceLost() const
12806{
12807 return d->isDeviceLost();
12808}
12809
12810/*!
12811 \return a binary data blob with data collected from the
12812 QRhiGraphicsPipeline and QRhiComputePipeline successfully created during
12813 the lifetime of this QRhi.
12814
12815 By saving and then, in subsequent runs of the same application, reloading
12816 the cache data, pipeline and shader creation times can potentially be
12817 reduced. What exactly the cache and its serialized version includes is not
12818 specified, is always specific to the backend used, and in some cases also
12819 dependent on the particular implementation of the graphics API.
12820
12821 When the PipelineCacheDataLoadSave is reported as unsupported, the returned
12822 QByteArray is empty.
12823
12824 When the EnablePipelineCacheDataSave flag was not specified when calling
12825 create(), the returned QByteArray may be empty, even when the
12826 PipelineCacheDataLoadSave feature is supported.
12827
12828 When the returned data is non-empty, it is always specific to the Qt
12829 version and QRhi backend. In addition, in some cases there is a strong
12830 dependency to the graphics device and the exact driver version used. QRhi
12831 takes care of adding the appropriate header and safeguards that ensure that
12832 the data can always be passed safely to setPipelineCacheData(), therefore
12833 attempting to load data from a run on another version of a driver will be
12834 handled safely and gracefully.
12835
12836 \note Calling releaseCachedResources() may, depending on the backend, clear
12837 the pipeline data collected. A subsequent call to this function may then
12838 not return any data.
12839
12840 See EnablePipelineCacheDataSave for further details about this feature.
12841
12842 \note Minimize the number of calls to this function. Retrieving the blob is
12843 not always a cheap operation, and therefore this function should only be
12844 called at a low frequency, ideally only once e.g. when closing the
12845 application.
12846
12847 \sa setPipelineCacheData(), create(), isFeatureSupported()
12848 */
12849QByteArray QRhi::pipelineCacheData()
12850{
12851 return d->pipelineCacheData();
12852}
12853
12854/*!
12855 Loads \a data into the pipeline cache, when applicable.
12856
12857 When the PipelineCacheDataLoadSave is reported as unsupported, the function
12858 is safe to call, but has no effect.
12859
12860 The blob returned by pipelineCacheData() is always specific to the Qt
12861 version, the QRhi backend, and, in some cases, also to the graphics device,
12862 and a given version of the graphics driver. QRhi takes care of adding the
12863 appropriate header and safeguards that ensure that the data can always be
12864 passed safely to this function. If there is a mismatch, e.g. because the
12865 driver has been upgraded to a newer version, or because the data was
12866 generated from a different QRhi backend, a warning is printed and \a data
12867 is safely ignored.
12868
12869 With Vulkan, this maps directly to VkPipelineCache. Calling this function
12870 creates a new Vulkan pipeline cache object, with its initial data sourced
12871 from \a data. The pipeline cache object is then used by all subsequently
12872 created QRhiGraphicsPipeline and QRhiComputePipeline objects, thus
12873 accelerating, potentially, the pipeline creation.
12874
12875 With other APIs there is no real pipeline cache, but they may provide a
12876 cache with bytecode from shader compilations (D3D) or program binaries
12877 (OpenGL). In applications that perform a lot of shader compilation from
12878 source at run time this can provide a significant boost in subsequent runs
12879 if the "pipeline cache" is pre-seeded from an earlier run using this
12880 function.
12881
12882 \note QRhi cannot give any guarantees that \a data has an effect on the
12883 pipeline and shader creation performance. With APIs like Vulkan, it is up
12884 to the driver to decide if \a data is used for some purpose, or if it is
12885 ignored.
12886
12887 See EnablePipelineCacheDataSave for further details about this feature.
12888
12889 \note This mechanism offered by QRhi is independent of the drivers' own
12890 internal caching mechanism, if any. This means that, depending on the
12891 graphics API and its implementation, the exact effects of retrieving and
12892 then reloading \a data are not predictable. Improved performance may not be
12893 visible at all in case other caching mechanisms outside of Qt's control are
12894 already active.
12895
12896 \note Minimize the number of calls to this function. Loading the blob is
12897 not always a cheap operation, and therefore this function should only be
12898 called at a low frequency, ideally only once e.g. when starting the
12899 application.
12900
12901 \warning Serialized pipeline cache data is assumed to be trusted content. Qt
12902 performs robust parsing of the header and metadata included in \a data,
12903 application developers are however advised to never pass in data from
12904 untrusted sources.
12905
12906 \sa pipelineCacheData(), isFeatureSupported()
12907 */
12908void QRhi::setPipelineCacheData(const QByteArray &data)
12909{
12910 d->setPipelineCacheData(data);
12911}
12912
12913/*!
12914 \struct QRhiStats
12915 \inmodule QtGuiPrivate
12916 \inheaderfile rhi/qrhi.h
12917 \since 6.6
12918
12919 \brief Statistics provided from the underlying memory allocator.
12920
12921 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
12922 for details.
12923 */
12924
12925/*!
12926 \variable QRhiStats::totalPipelineCreationTime
12927
12928 The total time in milliseconds spent in graphics and compute pipeline
12929 creation, which usually involves shader compilation or cache lookups, and
12930 potentially expensive processing.
12931
12932 \note The value should not be compared between different backends since the
12933 concept of "pipelines" and what exactly happens under the hood during, for
12934 instance, a call to QRhiGraphicsPipeline::create(), differ greatly between
12935 graphics APIs and their implementations.
12936
12937 \sa QRhi::statistics()
12938*/
12939
12940/*!
12941 \variable QRhiStats::blockCount
12942
12943 Statistic reported from the Vulkan or D3D12 memory allocator.
12944
12945 \sa QRhi::statistics()
12946*/
12947
12948/*!
12949 \variable QRhiStats::allocCount
12950
12951 Statistic reported from the Vulkan or D3D12 memory allocator.
12952
12953 \sa QRhi::statistics()
12954*/
12955
12956/*!
12957 \variable QRhiStats::usedBytes
12958
12959 Statistic reported from the Vulkan or D3D12 memory allocator.
12960
12961 \sa QRhi::statistics()
12962*/
12963
12964/*!
12965 \variable QRhiStats::unusedBytes
12966
12967 Statistic reported from the Vulkan or D3D12 memory allocator.
12968
12969 \sa QRhi::statistics()
12970*/
12971
12972/*!
12973 \variable QRhiStats::totalUsageBytes
12974
12975 Valid only with D3D12 currently. Matches IDXGIAdapter3::QueryVideoMemoryInfo().
12976
12977 \sa QRhi::statistics()
12978*/
12979
12980#ifndef QT_NO_DEBUG_STREAM
12981QDebug operator<<(QDebug dbg, const QRhiStats &info)
12982{
12983 QDebugStateSaver saver(dbg);
12984 dbg.nospace() << "QRhiStats("
12985 << "totalPipelineCreationTime=" << info.totalPipelineCreationTime
12986 << " blockCount=" << info.blockCount
12987 << " allocCount=" << info.allocCount
12988 << " usedBytes=" << info.usedBytes
12989 << " unusedBytes=" << info.unusedBytes
12990 << " totalUsageBytes=" << info.totalUsageBytes
12991 << ')';
12992 return dbg;
12993}
12994#endif
12995
12996/*!
12997 Gathers and returns statistics about the timings and allocations of
12998 graphics resources.
12999
13000 Data about memory allocations is only available with some backends, where
13001 such operations are under Qt's control. With graphics APIs where there is
13002 no lower level control over resource memory allocations, this will never be
13003 supported and all relevant fields in the results are 0.
13004
13005 With Vulkan in particular, the values are valid always, and are queried
13006 from the underlying memory allocator library. This gives an insight into
13007 the memory requirements of the active buffers and textures.
13008
13009 The same is true for Direct 3D 12. In addition to the memory allocator
13010 library's statistics, here the result also includes a \c totalUsageBytes
13011 field which reports the total size including additional resources that are
13012 not under the memory allocator library's control (swapchain buffers,
13013 descriptor heaps, etc.), as reported by DXGI.
13014
13015 The values correspond to all types of memory used, combined. (i.e. video +
13016 system in case of a discreet GPU)
13017
13018 Additional data, such as the total time in milliseconds spent in graphics
13019 and compute pipeline creation (which usually involves shader compilation or
13020 cache lookups, and potentially expensive processing) is available with most
13021 backends.
13022
13023 \note The elapsed times for operations such as pipeline creation may be
13024 affected by various factors. The results should not be compared between
13025 different backends since the concept of "pipelines" and what exactly
13026 happens under the hood during, for instance, a call to
13027 QRhiGraphicsPipeline::create(), differ greatly between graphics APIs and
13028 their implementations.
13029
13030 \note Additionally, many drivers will likely employ various caching
13031 strategies for shaders, programs, pipelines. (independently of Qt's own
13032 similar facilities, such as setPipelineCacheData() or the OpenGL-specific
13033 program binary disk cache). Because such internal behavior is transparent
13034 to the API client, Qt and QRhi have no knowledge or control over the exact
13035 caching strategy, persistency, invalidation of the cached data, etc. When
13036 reading timings, such as the time spent on pipeline creation, the potential
13037 presence and unspecified behavior of driver-level caching mechanisms should
13038 be kept in mind.
13039 */
13040QRhiStats QRhi::statistics() const
13041{
13042 return d->statistics();
13043}
13044
13045/*!
13046 \return a new graphics pipeline resource.
13047
13048 \sa QRhiResource::destroy()
13049 */
13050QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
13051{
13052 return d->createGraphicsPipeline();
13053}
13054
13055/*!
13056 \return a new compute pipeline resource.
13057
13058 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
13059 is reported as supported.
13060
13061 \sa QRhiResource::destroy()
13062 */
13063QRhiComputePipeline *QRhi::newComputePipeline()
13064{
13065 return d->createComputePipeline();
13066}
13067
13068/*!
13069 \return a new shader resource binding collection resource.
13070
13071 \sa QRhiResource::destroy()
13072 */
13073QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
13074{
13075 return d->createShaderResourceBindings();
13076}
13077
13078/*!
13079 \return a new buffer with the specified \a type, \a usage, and \a size.
13080
13081 \note Some \a usage and \a type combinations may not be supported by all
13082 backends. See \l{QRhiBuffer::UsageFlag}{UsageFlags} and
13083 \l{QRhi::NonDynamicUniformBuffers}{the feature flags}.
13084
13085 \note Backends may choose to allocate buffers bigger than \a size. This is
13086 done transparently to applications, so there are no special restrictions on
13087 the value of \a size. QRhiBuffer::size() will always report back the value
13088 that was requested in \a size.
13089
13090 \sa QRhiResource::destroy()
13091 */
13092QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type,
13093 QRhiBuffer::UsageFlags usage,
13094 quint32 size)
13095{
13096 return d->createBuffer(type, usage, size);
13097}
13098
13099/*!
13100 \return a new renderbuffer with the specified \a type, \a pixelSize, \a
13101 sampleCount, and \a flags.
13102
13103 When \a backingFormatHint is set to a texture format other than
13104 QRhiTexture::UnknownFormat, it may be used by the backend to decide what
13105 format to use for the storage backing the renderbuffer.
13106
13107 \note \a backingFormatHint becomes relevant typically when multisampling
13108 and floating point texture formats are involved: rendering into a
13109 multisample QRhiRenderBuffer and then resolving into a non-RGBA8
13110 QRhiTexture implies (with some graphics APIs) that the storage backing the
13111 QRhiRenderBuffer uses the matching non-RGBA8 format. That means that
13112 passing a format like QRhiTexture::RGBA32F is important, because backends
13113 will typically opt for QRhiTexture::RGBA8 by default, which would then
13114 break later on due to attempting to set up RGBA8->RGBA32F multisample
13115 resolve in the color attachment(s) of the QRhiTextureRenderTarget.
13116
13117 \sa QRhiResource::destroy()
13118 */
13119QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type,
13120 const QSize &pixelSize,
13121 int sampleCount,
13122 QRhiRenderBuffer::Flags flags,
13123 QRhiTexture::Format backingFormatHint)
13124{
13125 return d->createRenderBuffer(type, pixelSize, sampleCount, flags, backingFormatHint);
13126}
13127
13128/*!
13129 \return a new 1D or 2D texture with the specified \a format, \a pixelSize, \a
13130 sampleCount, and \a flags.
13131
13132 A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This
13133 function will implicitly set this flag if the \a pixelSize height is 0.
13134
13135 \note \a format specifies the requested internal and external format,
13136 meaning the data to be uploaded to the texture will need to be in a
13137 compatible format, while the native texture may (but is not guaranteed to,
13138 in case of OpenGL at least) use this format internally.
13139
13140 \note 1D textures are only functional when the OneDimensionalTextures feature is
13141 reported as supported at run time. Further, mipmaps on 1D textures are only
13142 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
13143
13144 \sa QRhiResource::destroy()
13145 */
13146QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
13147 const QSize &pixelSize,
13148 int sampleCount,
13149 QRhiTexture::Flags flags)
13150{
13151 if (pixelSize.height() == 0)
13152 flags |= QRhiTexture::OneDimensional;
13153
13154 return d->createTexture(format, pixelSize, 1, 0, sampleCount, flags);
13155}
13156
13157/*!
13158 \return a new 1D, 2D or 3D texture with the specified \a format, \a width, \a
13159 height, \a depth, \a sampleCount, and \a flags.
13160
13161 This overload is suitable for 3D textures because it allows specifying \a
13162 depth. A 3D texture must have QRhiTexture::ThreeDimensional set in \a
13163 flags, but using this overload that can be omitted because the flag is set
13164 implicitly whenever \a depth is greater than 0. For 1D, 2D and cube textures \a
13165 depth should be set to 0.
13166
13167 A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This overload
13168 will implicitly set this flag if both \a height and \a depth are 0.
13169
13170 \note 3D textures are only functional when the ThreeDimensionalTextures
13171 feature is reported as supported at run time.
13172
13173 \note 1D textures are only functional when the OneDimensionalTextures feature is
13174 reported as supported at run time. Further, mipmaps on 1D textures are only
13175 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
13176
13177 \overload
13178 */
13179QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
13180 int width, int height, int depth,
13181 int sampleCount,
13182 QRhiTexture::Flags flags)
13183{
13184 if (depth > 0)
13185 flags |= QRhiTexture::ThreeDimensional;
13186
13187 if (height == 0 && depth == 0)
13188 flags |= QRhiTexture::OneDimensional;
13189
13190 return d->createTexture(format, QSize(width, height), depth, 0, sampleCount, flags);
13191}
13192
13193/*!
13194 \return a new 1D or 2D texture array with the specified \a format, \a arraySize,
13195 \a pixelSize, \a sampleCount, and \a flags.
13196
13197 This function implicitly sets QRhiTexture::TextureArray in \a flags.
13198
13199 A 1D texture array must have QRhiTexture::OneDimensional set in \a flags. This
13200 function will implicitly set this flag if the \a pixelSize height is 0.
13201
13202 \note Do not confuse texture arrays with arrays of textures. A QRhiTexture
13203 created by this function is usable with 1D or 2D array samplers in the shader, for
13204 example: \c{layout(binding = 1) uniform sampler2DArray texArr;}. Arrays of
13205 textures refers to a list of textures that are exposed to the shader via
13206 QRhiShaderResourceBinding::sampledTextures() and a count > 1, and declared
13207 in the shader for example like this: \c{layout(binding = 1) uniform
13208 sampler2D textures[4];}
13209
13210 \note This is only functional when the TextureArrays feature is reported as
13211 supported at run time.
13212
13213 \note 1D textures are only functional when the OneDimensionalTextures feature is
13214 reported as supported at run time. Further, mipmaps on 1D textures are only
13215 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
13216
13217
13218 \sa newTexture()
13219 */
13220QRhiTexture *QRhi::newTextureArray(QRhiTexture::Format format,
13221 int arraySize,
13222 const QSize &pixelSize,
13223 int sampleCount,
13224 QRhiTexture::Flags flags)
13225{
13226 flags |= QRhiTexture::TextureArray;
13227
13228 if (pixelSize.height() == 0)
13229 flags |= QRhiTexture::OneDimensional;
13230
13231 return d->createTexture(format, pixelSize, 1, arraySize, sampleCount, flags);
13232}
13233
13234/*!
13235 \return a new sampler with the specified magnification filter \a magFilter,
13236 minification filter \a minFilter, mipmapping mode \a mipmapMode, and the
13237 addressing (wrap) modes \a addressU, \a addressV, and \a addressW.
13238
13239 \note Setting \a mipmapMode to a value other than \c None implies that
13240 images for all relevant mip levels will be provided either via
13241 \l{QRhiResourceUpdateBatch::uploadTexture()}{texture uploads} or by calling
13242 \l{QRhiResourceUpdateBatch::generateMips()}{generateMips()} on the texture
13243 that is used with this sampler. Attempting to use the sampler with a
13244 texture that has no data for all relevant mip levels will lead to rendering
13245 errors, with the exact behavior dependent on the underlying graphics API.
13246
13247 \sa QRhiResource::destroy()
13248 */
13249QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter,
13250 QRhiSampler::Filter minFilter,
13251 QRhiSampler::Filter mipmapMode,
13252 QRhiSampler::AddressMode addressU,
13253 QRhiSampler::AddressMode addressV,
13254 QRhiSampler::AddressMode addressW)
13255{
13256 return d->createSampler(magFilter, minFilter, mipmapMode, addressU, addressV, addressW);
13257}
13258
13259/*!
13260 \return a new shading rate map object.
13261
13262 \since 6.9
13263 */
13264QRhiShadingRateMap *QRhi::newShadingRateMap()
13265{
13266 return d->createShadingRateMap();
13267}
13268
13269/*!
13270 \return a new indirect command buffer that holds commands of the specified
13271 \a type, with room for \a maxCommandCount of them.
13272
13273 \a maxCommandCount cannot be 0, otherwise create() fails. It is the upper
13274 bound for both ways of providing commands: recording them with
13275 QRhiIndirectCommandBuffer::draw() or
13276 QRhiIndirectCommandBuffer::drawIndexed(), and generating them on the GPU
13277 and calling QRhiCommandBuffer::buildIndirect(). Backends allocate their
13278 native objects, and the QRhiBuffer holding the recorded commands, based on
13279 it, which is why it is fixed up front instead of growing on demand.
13280
13281 \sa QRhiIndirectCommandBuffer::setMaxCommandCount(), QRhiIndirectCommandBuffer
13282
13283 \since 6.13
13284 */
13285QRhiIndirectCommandBuffer *QRhi::newIndirectCommandBuffer(QRhiIndirectCommandBuffer::Type type,
13286 quint32 maxCommandCount)
13287{
13288 return d->createIndirectCommandBuffer(type, maxCommandCount);
13289}
13290
13291/*!
13292 \return a new texture render target with color and depth/stencil
13293 attachments given in \a desc, and with the specified \a flags.
13294
13295 \sa QRhiResource::destroy()
13296 */
13297
13298QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
13299 QRhiTextureRenderTarget::Flags flags)
13300{
13301 return d->createTextureRenderTarget(desc, flags);
13302}
13303
13304/*!
13305 \return a new swapchain.
13306
13307 \sa QRhiResource::destroy(), QRhiSwapChain::createOrResize()
13308 */
13309QRhiSwapChain *QRhi::newSwapChain()
13310{
13311 return d->createSwapChain();
13312}
13313
13314/*!
13315 Starts a new frame targeting the next available buffer of \a swapChain.
13316
13317 A frame consists of resource updates and one or more render and compute
13318 passes.
13319
13320 \a flags can indicate certain special cases.
13321
13322 The high level pattern of rendering into a QWindow using a swapchain:
13323
13324 \list
13325
13326 \li Create a swapchain.
13327
13328 \li Call QRhiSwapChain::createOrResize() whenever the surface size is
13329 different than before.
13330
13331 \li Call QRhiSwapChain::destroy() on
13332 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed.
13333
13334 \li Then on every frame:
13335 \badcode
13336 beginFrame(sc);
13337 updates = nextResourceUpdateBatch();
13338 updates->...
13339 QRhiCommandBuffer *cb = sc->currentFrameCommandBuffer();
13340 cb->beginPass(sc->currentFrameRenderTarget(), colorClear, dsClear, updates);
13341 ...
13342 cb->endPass();
13343 ... // more passes as necessary
13344 endFrame(sc);
13345 \endcode
13346
13347 \endlist
13348
13349 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
13350 value on failure. Some of these should be treated as soft, "try again
13351 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
13352 the swapchain is to be resized or updated by calling
13353 QRhiSwapChain::createOrResize(). The application should then attempt to
13354 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
13355 lost but this may also be recoverable by releasing all resources, including
13356 the QRhi itself, and then recreating all resources. See isDeviceLost() for
13357 further discussion.
13358
13359 \sa endFrame(), beginOffscreenFrame(), isDeviceLost()
13360 */
13361QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
13362{
13363 if (d->inFrame)
13364 qWarning("Attempted to call beginFrame() within a still active frame; ignored");
13365
13366 qCDebug(QRHI_LOG_RUB) << "[rub] new frame";
13367
13368 QRhi::FrameOpResult r = !d->inFrame ? d->beginFrame(swapChain, flags) : FrameOpSuccess;
13369 if (r == FrameOpSuccess)
13370 d->inFrame = true;
13371
13372 return r;
13373}
13374
13375/*!
13376 Ends, commits, and presents a frame that was started in the last
13377 beginFrame() on \a swapChain.
13378
13379 Double (or triple) buffering is managed internally by the QRhiSwapChain and
13380 QRhi.
13381
13382 \a flags can optionally be used to change the behavior in certain ways.
13383 Passing QRhi::SkipPresent skips queuing the Present command or calling
13384 swapBuffers.
13385
13386 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
13387 value on failure. Some of these should be treated as soft, "try again
13388 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
13389 the swapchain is to be resized or updated by calling
13390 QRhiSwapChain::createOrResize(). The application should then attempt to
13391 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
13392 lost but this may also be recoverable by releasing all resources, including
13393 the QRhi itself, and then recreating all resources. See isDeviceLost() for
13394 further discussion.
13395
13396 \sa beginFrame(), isDeviceLost()
13397 */
13398QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags)
13399{
13400 const bool wasInFrame = d->inFrame;
13401 if (!wasInFrame)
13402 qWarning("Attempted to call endFrame() without an active frame; ignored");
13403
13404 QRhi::FrameOpResult r = wasInFrame ? d->endFrame(swapChain, flags) : FrameOpSuccess;
13405 d->inFrame = false;
13406 // deleteLater is a high level QRhi concept the backends know
13407 // nothing about - handle it here.
13408 qDeleteAll(d->pendingDeleteResources);
13409 d->pendingDeleteResources.clear();
13410
13411 if (wasInFrame && qrhiDebugHooks.frameEnd) {
13412 QRhiCommandBuffer *cb = (r == FrameOpSuccess && swapChain)
13413 ? swapChain->currentFrameCommandBuffer() : nullptr;
13414 qrhiDebugHooks.frameEnd(d, swapChain, cb);
13415 }
13416
13417 return r;
13418}
13419
13420/*!
13421 \return true when there is an active frame, meaning there was a
13422 beginFrame() (or beginOffscreenFrame()) with no corresponding endFrame()
13423 (or endOffscreenFrame()) yet.
13424
13425 \sa currentFrameSlot(), beginFrame(), endFrame()
13426 */
13427bool QRhi::isRecordingFrame() const
13428{
13429 return d->inFrame;
13430}
13431
13432/*!
13433 \return the current frame slot index while recording a frame. Unspecified
13434 when called outside an active frame (that is, when isRecordingFrame() is \c
13435 false).
13436
13437 With backends like Vulkan or Metal, it is the responsibility of the QRhi
13438 backend to block whenever starting a new frame and finding the CPU is
13439 already \c{FramesInFlight - 1} frames ahead of the GPU (because the command
13440 buffer submitted in frame no. \c{current} - \c{FramesInFlight} has not yet
13441 completed).
13442
13443 Resources that tend to change between frames (such as, the native buffer
13444 object backing a QRhiBuffer with type QRhiBuffer::Dynamic) exist in
13445 multiple versions, so that each frame, that can be submitted while a
13446 previous one is still being processed, works with its own copy, thus
13447 avoiding the need to stall the pipeline when preparing the frame. (The
13448 contents of a resource that may still be in use in the GPU should not be
13449 touched, but simply always waiting for the previous frame to finish would
13450 reduce GPU utilization and ultimately, performance and efficiency.)
13451
13452 Conceptually this is somewhat similar to copy-on-write schemes used by some
13453 C++ containers and other types. It may also be similar to what an OpenGL or
13454 Direct 3D 11 implementation performs internally for certain type of objects.
13455
13456 In practice, such double (or triple) buffering resources is realized in
13457 the Vulkan, Metal, and similar QRhi backends by having a fixed number of
13458 native resource (such as, VkBuffer) \c slots behind a QRhiResource. That
13459 can then be indexed by a frame slot index running 0, 1, ..,
13460 FramesInFlight-1, and then wrapping around.
13461
13462 All this is managed transparently to the users of QRhi. However,
13463 applications that integrate rendering done directly with the graphics API
13464 may want to perform a similar double or triple buffering of their own
13465 graphics resources. That is then most easily achieved by knowing the values
13466 of the maximum number of in-flight frames (retrievable via resourceLimit())
13467 and the current frame (slot) index (returned by this function).
13468
13469 \sa isRecordingFrame(), beginFrame(), endFrame()
13470 */
13471int QRhi::currentFrameSlot() const
13472{
13473 return d->currentFrameSlot;
13474}
13475
13476/*!
13477 Starts a new offscreen frame. Provides a command buffer suitable for
13478 recording rendering commands in \a cb. \a flags is used to indicate
13479 certain special cases, just like with beginFrame().
13480
13481 \note The QRhiCommandBuffer stored to *cb is not owned by the caller.
13482
13483 Rendering without a swapchain is possible as well. The typical use case is
13484 to use it in completely offscreen applications, e.g. to generate image
13485 sequences by rendering and reading back without ever showing a window.
13486
13487 Usage in on-screen applications (so beginFrame, endFrame,
13488 beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) is possible too.
13489
13490 When a \l{QRhiResourceUpdateBatch::readBackTexture()}{texture} or
13491 \l{QRhiResourceUpdateBatch::readBackBuffer()}{buffer} readback was
13492 scheduled, offscreen frames do not let the CPU potentially generate another
13493 frame while the GPU is still processing the previous one. This has the side
13494 effect that if readbacks are scheduled, the results are guaranteed to be
13495 available once endOffscreenFrame() returns. That is not the case with frames
13496 targeting a swapchain: there the GPU is potentially better utilized, but
13497 working with readback operations needs more care from the application
13498 because endFrame(), unlike endOffscreenFrame(), does not guarantee that the
13499 results from the readback are available at that point.
13500
13501 The skeleton of rendering a frame without a swapchain and then reading the
13502 frame contents back could look like the following:
13503
13504 \code
13505 QRhiReadbackResult rbResult;
13506 QRhiCommandBuffer *cb;
13507 rhi->beginOffscreenFrame(&cb);
13508 cb->beginPass(rt, colorClear, dsClear);
13509 // ...
13510 u = nextResourceUpdateBatch();
13511 u->readBackTexture(rb, &rbResult);
13512 cb->endPass(u);
13513 rhi->endOffscreenFrame();
13514 // image data available in rbResult
13515 \endcode
13516
13517 \sa endOffscreenFrame(), beginFrame()
13518 */
13519QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags)
13520{
13521 const bool wasInFrame = d->inFrame;
13522 if (wasInFrame)
13523 qWarning("Attempted to call beginOffscreenFrame() within a still active frame; ignored");
13524
13525 qCDebug(QRHI_LOG_RUB) << "[rub] new offscreen frame";
13526
13527 QRhi::FrameOpResult r = !wasInFrame ? d->beginOffscreenFrame(cb, flags) : FrameOpSuccess;
13528 if (r == FrameOpSuccess) {
13529 d->inFrame = true;
13530 if (!wasInFrame)
13531 d->currentOffscreenCb = *cb;
13532 }
13533
13534 return r;
13535}
13536
13537/*!
13538 Ends, submits, and potentially waits for the offscreen frame.
13539
13540 Unlike endFrame(), this function will block and wait for completion of the
13541 GPU-side work when there are active buffer or texture readbacks.
13542
13543 \a flags is not currently used.
13544
13545 \sa beginOffscreenFrame()
13546 */
13547QRhi::FrameOpResult QRhi::endOffscreenFrame(EndFrameFlags flags)
13548{
13549 const bool wasInFrame = d->inFrame;
13550 if (!wasInFrame)
13551 qWarning("Attempted to call endOffscreenFrame() without an active frame; ignored");
13552
13553 QRhi::FrameOpResult r = wasInFrame ? d->endOffscreenFrame(flags) : FrameOpSuccess;
13554 d->inFrame = false;
13555 qDeleteAll(d->pendingDeleteResources);
13556 d->pendingDeleteResources.clear();
13557
13558 if (wasInFrame && qrhiDebugHooks.frameEnd) {
13559 QRhiCommandBuffer *cb = r == FrameOpSuccess ? d->currentOffscreenCb : nullptr;
13560 qrhiDebugHooks.frameEnd(d, nullptr, cb);
13561 }
13562 d->currentOffscreenCb = nullptr;
13563
13564 return r;
13565}
13566
13567/*!
13568 Waits for any work on the graphics queue (where applicable) to complete,
13569 then executes all deferred operations, like completing readbacks and
13570 resource releases. Can be called inside and outside of a frame, but not
13571 inside a pass. Inside a frame it implies submitting any work on the
13572 command buffer.
13573
13574 \note Avoid this function. One case where it may be needed is when the
13575 results of an enqueued readback in a swapchain-based frame are needed at a
13576 fixed given point and so waiting for the results is desired.
13577 */
13578QRhi::FrameOpResult QRhi::finish()
13579{
13580 return d->finish();
13581}
13582
13583/*!
13584 \return the list of supported sample counts.
13585
13586 A typical example would be (1, 2, 4, 8).
13587
13588 With some backend this list of supported values is fixed in advance, while
13589 with some others the (physical) device properties indicate what is
13590 supported at run time.
13591
13592 \sa QRhiRenderBuffer::setSampleCount(), QRhiTexture::setSampleCount(),
13593 QRhiGraphicsPipeline::setSampleCount(), QRhiSwapChain::setSampleCount()
13594 */
13595QList<int> QRhi::supportedSampleCounts() const
13596{
13597 return d->supportedSampleCounts();
13598}
13599
13600/*!
13601 \return the minimum uniform buffer offset alignment in bytes. This is
13602 typically 256.
13603
13604 Attempting to bind a uniform buffer region with an offset not aligned to
13605 this value will lead to failures depending on the backend and the
13606 underlying graphics API.
13607
13608 \sa ubufAligned()
13609 */
13610int QRhi::ubufAlignment() const
13611{
13612 return d->ubufAlignment();
13613}
13614
13615/*!
13616 \return The list of supported variable shading rates for the specified \a sampleCount.
13617
13618 1x1 is always supported.
13619
13620 \since 6.9
13621 */
13622QList<QSize> QRhi::supportedShadingRates(int sampleCount) const
13623{
13624 return d->supportedShadingRates(sampleCount);
13625}
13626
13627Q_CONSTINIT static QBasicAtomicInteger<QRhiGlobalObjectIdGenerator::Type> counter = Q_BASIC_ATOMIC_INITIALIZER(0);
13628
13629QRhiGlobalObjectIdGenerator::Type QRhiGlobalObjectIdGenerator::newId()
13630{
13631 return counter.fetchAndAddRelaxed(1) + 1;
13632}
13633
13635{
13636 return m_buffers.isEmpty() && m_textures.isEmpty();
13637}
13638
13640{
13641 m_buffers.clear();
13642 m_textures.clear();
13643}
13644
13650
13651void QRhiPassResourceTracker::registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
13652 const UsageState &state)
13653{
13654 auto it = m_buffers.find(buf);
13655 if (it != m_buffers.end()) {
13656 Buffer &b = it->second;
13657 if (Q_UNLIKELY(b.access != *access)) {
13658 const QByteArray name = buf->name();
13659 qWarning("Buffer %p (%s) used with different accesses within the same pass, this is not allowed.",
13660 buf, name.constData());
13661 return;
13662 }
13663 if (b.stage != *stage) {
13664 b.stage = earlierStage(b.stage, *stage);
13665 *stage = b.stage;
13666 }
13667 return;
13668 }
13669
13670 Buffer b;
13671 b.slot = slot;
13672 b.access = *access;
13673 b.stage = *stage;
13674 b.stateAtPassBegin = state; // first use -> initial state
13675 m_buffers.append(buf, b);
13676}
13677
13683
13690
13692 const UsageState &state)
13693{
13694 auto it = m_textures.find(tex);
13695 if (it != m_textures.end()) {
13696 Texture &t = it->second;
13697 if (t.access != *access) {
13698 // Different subresources of a texture may be used for both load
13699 // and store in the same pass. (think reading from one mip level
13700 // and writing to another one in a compute shader) This we can
13701 // handle by treating the entire resource as read-write.
13702 if (Q_LIKELY(isImageLoadStore(t.access) && isImageLoadStore(*access))) {
13704 *access = t.access;
13705 } else {
13706 const QByteArray name = tex->name();
13707 qWarning("Texture %p (%s) used with different accesses within the same pass, this is not allowed.",
13708 tex, name.constData());
13709 }
13710 }
13711 if (t.stage != *stage) {
13712 t.stage = earlierStage(t.stage, *stage);
13713 *stage = t.stage;
13714 }
13715 return;
13716 }
13717
13718 Texture t;
13719 t.access = *access;
13720 t.stage = *stage;
13721 t.stateAtPassBegin = state; // first use -> initial state
13722 m_textures.append(tex, t);
13723}
13724
13725QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
13726{
13727 // pick the earlier stage (as this is going to be dstAccessMask)
13728 if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
13730 if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
13732 if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
13734 if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
13736 if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
13738 if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
13740
13741 Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::BufVertexStage);
13742}
13743
13744QRhiPassResourceTracker::TextureStage QRhiPassResourceTracker::toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
13745{
13746 // pick the earlier stage (as this is going to be dstAccessMask)
13747 if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
13749 if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
13751 if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
13753 if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
13755 if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
13757 if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
13759
13760 Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::TexVertexStage);
13761}
13762
13763QSize QRhiImplementation::clampedSubResourceUploadSize(QSize size, QPoint dstPos, int level, QSize textureSizeAtLevelZero, bool warn)
13764{
13765 const QSize subResSize = q->sizeForMipLevel(level, textureSizeAtLevelZero);
13766 const bool outOfBoundsHoriz = dstPos.x() + size.width() > subResSize.width();
13767 const bool outOfBoundsVert = dstPos.y() + size.height() > subResSize.height();
13768 if (Q_UNLIKELY(outOfBoundsHoriz || outOfBoundsVert)) {
13769 if (warn) {
13770 qWarning("Invalid texture upload issued; size %dx%d dst.position %d,%d dst.subresource size %dx%d; size will be clamped",
13771 size.width(), size.height(), dstPos.x(), dstPos.y(), subResSize.width(), subResSize.height());
13772 }
13773 if (outOfBoundsHoriz)
13774 size.setWidth(subResSize.width() - dstPos.x());
13775 if (outOfBoundsVert)
13776 size.setHeight(subResSize.height() - dstPos.y());
13777 }
13778 return size;
13779}
13780
13781// Clamps size so that reading the image with a source row stride of bpl does
13782// not go past dataSize bytes. bpl may be 0, meaning the data is tightly packed.
13783// Returns a size with a height of 0 when not even a single row can be
13784// satisfied, in which case the caller is expected to skip the copy.
13785QSize QRhiImplementation::clampedSubResourceUploadSizeForSourceData(QSize size, quint32 bpl,
13786 quint32 bytesPerPixel,
13787 qsizetype dataSize, bool warn)
13788{
13789 if (size.isEmpty() || !bytesPerPixel)
13790 return size;
13791
13792 const quint64 rowBytes = quint64(bytesPerPixel) * quint64(size.width());
13793 if (!bpl)
13794 bpl = quint32(qMin(rowBytes, quint64(std::numeric_limits<quint32>::max())));
13795
13796 if (quint64(bpl) < rowBytes) {
13797 if (warn) {
13798 qWarning("Invalid texture upload issued; source row stride %u is smaller than the %llu "
13799 "bytes a row of %d pixels needs; upload will be skipped",
13800 bpl, rowBytes, size.width());
13801 }
13802 return QSize(size.width(), 0);
13803 }
13804
13805 // Row y is read from y * bpl and needs rowBytes bytes, so the last row ends
13806 // at (height - 1) * bpl + rowBytes.
13807 const quint64 needed = quint64(bpl) * quint64(size.height() - 1) + rowBytes;
13808 if (quint64(dataSize) >= needed)
13809 return size;
13810
13811 int rows = 0;
13812 if (quint64(dataSize) >= rowBytes)
13813 rows = int((quint64(dataSize) - rowBytes) / quint64(bpl)) + 1;
13814
13815 if (warn) {
13816 qWarning("Invalid texture upload issued; %lld bytes of data cannot back a %dx%d upload with "
13817 "source row stride %u (needs %llu bytes); height will be clamped to %d",
13818 qint64(dataSize), size.width(), size.height(), bpl, needed, rows);
13819 }
13820
13821 return QSize(size.width(), rows);
13822}
13823
13824QT_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:9337
QRhiBufferBackedIndirectCommandBuffer(QRhiImplementation *rhi, Type type, quint32 maxCommandCount)
\variable QRhiIndirectCommandBufferBuildInfo::topology
Definition qrhi.cpp:9247
void enqueueUpload(QRhiResourceUpdateBatch *u)
Definition qrhi.cpp:9301
void build(const QRhiIndirectCommandBufferBuildInfo &info)
Definition qrhi.cpp:9324
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
Definition qrhi.cpp:9259
bool create() override
Creates the corresponding native objects.
Definition qrhi.cpp:9282
bool isEmpty() const
Definition qrhi.cpp:13634
void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage, const UsageState &state)
Definition qrhi.cpp:13651
void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage, const UsageState &state)
Definition qrhi.cpp:13691
QRhiImplementation * rhi
Definition qrhi_p.h:737
static const int BUFFER_OPS_STATIC_ALLOC
Definition qrhi_p.h:729
void merge(QRhiResourceUpdateBatchPrivate *other)
Definition qrhi.cpp:11408
QRhiResourceUpdateBatch * q
Definition qrhi_p.h:736
static const int TEXTURE_OPS_STATIC_ALLOC
Definition qrhi_p.h:733
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
static const char * resourceTypeStr(const QRhiResource *res)
Definition qrhi.cpp:9498
static QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a, QRhiPassResourceTracker::BufferStage b)
Definition qrhi.cpp:13645
QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
Definition qrhi.cpp:8550
static bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess access)
Definition qrhi.cpp:13684
static const char * deviceTypeStr(QRhiDriverInfo::DeviceType type)
\variable QRhiDriverInfo::deviceName
Definition qrhi.cpp:10481
static QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a, QRhiPassResourceTracker::TextureStage b)
Definition qrhi.cpp:13678
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:1588
LimitsType limitsType
Definition qrhi.h:1599
float maxPotentialColorComponentValue
Definition qrhi.h:1607
LuminanceBehavior luminanceBehavior
Definition qrhi.h:1610
float maxColorComponentValue
Definition qrhi.h:1606