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, and so are the depth and
899 depth-stencil formats QRhiTexture::D16, D24, D24S8, D32F and D32FS8, as long
900 as the format is supported in the first place. Reading back floating
901 point formats QRhiTexture::RGBA16F and RGBA32F may work too with OpenGL, as
902 long as the implementation provides support for these, but QRhi can give no
903 guarantees, as indicated by this flag.
904
905 \value PipelineCacheDataLoadSave Indicates that the pipelineCacheData() and
906 setPipelineCacheData() functions are functional. When not supported, the
907 functions will not perform any action, the retrieved blob is always empty,
908 and thus no benefits can be expected from retrieving and, during a
909 subsequent run of the application, reloading the pipeline cache content.
910
911 \value ImageDataStride Indicates that specifying a custom stride (row
912 length) for raw image data in texture uploads is supported. When not
913 supported (which can happen when the underlying API is OpenGL ES 2.0 without
914 support for GL_UNPACK_ROW_LENGTH),
915 QRhiTextureSubresourceUploadDescription::setDataStride() must not be used.
916
917 \value RenderBufferImport Indicates that QRhiRenderBuffer::createFrom() is
918 supported. For most graphics APIs this is not sensible because
919 QRhiRenderBuffer encapsulates texture objects internally, just like
920 QRhiTexture. With OpenGL however, renderbuffer object exist as a separate
921 object type in the API, and in certain environments (for example, where one
922 may want to associated a renderbuffer object with an EGLImage object) it is
923 important to allow wrapping an existing OpenGL renderbuffer object with a
924 QRhiRenderBuffer.
925
926 \value ThreeDimensionalTextures Indicates that 3D textures are supported.
927 In practice this feature will be unsupported with OpenGL and OpenGL ES
928 versions lower than 3.0.
929
930 \value RenderTo3DTextureSlice Indicates that rendering to a slice in a 3D
931 texture is supported. This can be unsupported with Vulkan 1.0 due to
932 relying on VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT which is a Vulkan 1.1
933 feature.
934
935 \value TextureArrays Indicates that texture arrays are supported and
936 QRhi::newTextureArray() is functional. Note that even when texture arrays
937 are not supported, arrays of textures are still available as those are two
938 independent features.
939
940 \value Tessellation Indicates that the tessellation control and evaluation
941 stages are supported. When reported as supported, the topology of a
942 QRhiGraphicsPipeline can be set to
943 \l{QRhiGraphicsPipeline::Patches}{Patches}, the number of control points
944 can be set via
945 \l{QRhiGraphicsPipeline::setPatchControlPointCount()}{setPatchControlPointCount()},
946 and shaders for tessellation control and evaluation can be specified in the
947 QRhiShaderStage list. Tessellation shaders have portability issues between
948 APIs (for example, translating GLSL/SPIR-V to HLSL is problematic due to
949 the way hull shaders are structured, whereas Metal uses a somewhat
950 different tessellation pipeline than others), and therefore unexpected
951 issues may still arise, even though basic functionality is implemented
952 across all the underlying APIs. For Direct 3D in particular, handwritten
953 HLSL hull and domain shaders must be injected into each QShader for the
954 tessellation control and evaluation stages, respectively, since qsb cannot
955 generate these from SPIR-V. Note that isoline tessellation should be
956 avoided as it will not be supported by all backends. The maximum patch
957 control point count portable between backends is 32.
958
959 \value GeometryShader Indicates that the geometry shader stage is supported.
960 When supported, a geometry shader can be specified in the QRhiShaderStage
961 list. Geometry Shaders are considered an experimental feature in QRhi and
962 can only be expected to be supported with Vulkan, Direct 3D 11 and 12,
963 OpenGL (3.2+) and OpenGL ES (3.2+), assuming the implementation reports it
964 as supported at run time. Starting with Qt 6.11 geometry shaders are
965 automatically translated to HLSL, and therefore no injection of handwritten
966 HLSL geometry shaders is necessary anymore (but note that gl_in and
967 expressions such as gl_in[0].gl_Position are not supported; rather, pass the
968 position as an output variable from the vertex shader). Geometry shaders are
969 not supported with Metal.
970
971 \value TextureArrayRange Indicates that for
972 \l{QRhi::newTextureArray()}{texture arrays} it is possible to specify a
973 range that is exposed to the shaders. Normally all array layers are exposed
974 and it is up to the shader to select the layer (via the third coordinate
975 passed to texture() when sampling the \c sampler2DArray). When supported,
976 calling QRhiTexture::setArrayRangeStart() and
977 QRhiTexture::setArrayRangeLength() before
978 \l{QRhiTexture::create()}{building} or
979 \l{QRhiTexture::createFrom()}{importing} the native texture has an effect,
980 and leads to selecting only the specified range from the array. This will
981 be necessary in special cases, such as when working with accelerated video
982 decoding and Direct 3D 11, because a texture array with both
983 \c{D3D11_BIND_DECODER} and \c{D3D11_BIND_SHADER_RESOURCE} on it is only
984 usable as a shader resource if a single array layer is selected. Note that
985 all this is applicable only when the texture is used as a
986 QRhiShaderResourceBinding::SampledTexture or
987 QRhiShaderResourceBinding::Texture shader resource, and is not compatible
988 with image load/store. This feature is only available with some backends as
989 it does not map well to all graphics APIs, and it is only meant to provide
990 support for special cases anyhow. In practice the feature can be expected to
991 be supported with Direct3D 11/12, Vulkan and Metal.
992
993 \value NonFillPolygonMode Indicates that setting a PolygonMode other than
994 the default Fill is supported for QRhiGraphicsPipeline. A common use case
995 for changing the mode to Line is to get wireframe rendering. This however
996 is not available as a core OpenGL ES feature, and is optional with Vulkan
997 as well as some mobile GPUs may not offer the feature.
998
999 \value OneDimensionalTextures Indicates that 1D textures are supported.
1000 In practice this feature will be unsupported on OpenGL ES.
1001
1002 \value OneDimensionalTextureMipmaps Indicates that generating 1D texture
1003 mipmaps is supported. In practice this feature will be unsupported on
1004 backends that do not report support for
1005 \l{OneDimensionalTextures}, Metal, and Direct 3D 12.
1006
1007 \value HalfAttributes Indicates that specifying input attributes with half
1008 precision (16bit) floating point types for a shader pipeline is supported.
1009 When not supported,
1010 \l{QRhiGraphicsPipeline::create()}{QRhiGraphicsPipeline::create()} will
1011 succeed but show a warning message and the values of the target attributes
1012 will be broken. In practice this feature will be unsupported in some OpenGL
1013 ES 2.0 and OpenGL 2.x
1014 implementations. Note that while Direct3D 11/12 does support half precision
1015 input attributes, it does not support the half3 type. The D3D backends pass
1016 half3 attributes as half4. To ensure cross platform compatibility, half3
1017 inputs should be padded to 8 bytes.
1018
1019 \value RenderToOneDimensionalTexture Indicates that 1D texture render
1020 targets are supported. In practice this feature will be unsupported on
1021 backends that do not report support for
1022 \l{OneDimensionalTextures}, and Metal.
1023
1024 \value ThreeDimensionalTextureMipmaps Indicates that generating 3D texture
1025 mipmaps is supported. This is typically supported with all backends starting
1026 with Qt 6.10.
1027
1028 \value MultiView Indicates that multiview, see e.g.
1029 \l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_multiview.html}{VK_KHR_multiview}
1030 is supported. With OpenGL ES 2.0, Direct 3D 11, and OpenGL (ES)
1031 implementations without \c{GL_OVR_multiview2} this feature will not be
1032 supported. With Vulkan 1.1 and newer, and Direct 3D 12 multiview is
1033 typically supported. When reported as supported, creating a
1034 QRhiTextureRenderTarget with a QRhiColorAttachment that references a texture
1035 array and has \l{QRhiColorAttachment::setMultiViewCount()}{multiViewCount}
1036 set enables recording a render pass that uses multiview rendering. In addition,
1037 any QRhiGraphicsPipeline used in that render pass must have
1038 \l{QRhiGraphicsPipeline::setMultiViewCount()}{the same view count set}. Note that
1039 multiview is only available in combination with 2D texture arrays. It cannot
1040 be used to optimize the rendering into individual textures (e.g. two, for
1041 the left and right eyes). Rather, the target of a multiview render pass is
1042 always a texture array, automatically rendering to the layer (array element)
1043 corresponding to each view. Therefore this feature implies \l TextureArrays
1044 as well. Multiview rendering is not supported in combination with
1045 tessellation or geometry shaders. See QRhiColorAttachment::setMultiViewCount()
1046 for further details on multiview rendering. This enum value has been introduced in Qt 6.7.
1047
1048 \value TextureViewFormat Indicates that setting a
1049 \l{QRhiTexture::setWriteViewFormat()}{view format} on a QRhiTexture is
1050 effective. When reported as supported, setting the read (sampling) or write
1051 (render target / image load-store) view mode changes the texture's viewing
1052 format. When unsupported, setting a view format has no effect. Note that Qt
1053 has no knowledge or control over format compatibility or resource view rules
1054 in the underlying 3D API and its implementation. Passing in unsuitable,
1055 incompatible formats may lead to errors and unspecified behavior. This is
1056 provided mainly to allow "casting" rendering into a texture created with an
1057 sRGB format to non-sRGB to avoid the unwanted linear->sRGB conversion on
1058 shader writes. Other types of casting may or may not be functional,
1059 depending on the underlying API. Currently implemented for Vulkan and Direct
1060 3D 12 and Metal. With D3D12 the feature is available only if
1061 \c CastingFullyTypedFormatSupported is supported, see
1062 \l{https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html} (and
1063 note that QRhi always uses fully typed formats for textures.) This enum
1064 value has been introduced in Qt 6.8.
1065
1066 \value ResolveDepthStencil Indicates that resolving a multisample depth or
1067 depth-stencil texture is supported. Otherwise,
1068 \l{QRhiTextureRenderTargetDescription::setDepthResolveTexture()}{setting a
1069 depth resolve texture} is not functional and must be avoided. Direct 3D 11
1070 and 12 have no support for resolving depth/depth-stencil formats, and
1071 therefore this feature will never be supported with those. Vulkan 1.0 has no
1072 API to request resolving a depth-stencil attachment. Therefore, with Vulkan
1073 this feature will only be supported with Vulkan 1.2 and up, and on 1.1
1074 implementations with the appropriate extensions present. This feature is
1075 provided for the rare case when resolving into a non-multisample depth
1076 texture becomes necessary, for example when rendering into an
1077 OpenXR-provided depth texture (XR_KHR_composition_layer_depth). This enum
1078 value has been introduced in Qt 6.8.
1079
1080 \value VariableRateShading Indicates that per-draw (per-pipeline) variable
1081 rate shading is supported. When reported as supported, \l
1082 QRhiCommandBuffer::setShadingRate() is functional and has an effect for
1083 QRhiGraphicsPipeline objects that declared \l
1084 QRhiGraphicsPipeline::UsesShadingRate in their flags. Call \l
1085 QRhi::supportedShadingRates() to check which rates are supported. (1x1 is
1086 always supported, other typical values are 2x2, 1x2, 2x1, 2x4, 4x2, 4x4).
1087 This feature can be expected to be supported with Direct 3D 12 and Vulkan,
1088 assuming the implementation and GPU used at run time supports VRS. This enum
1089 value has been introduced in Qt 6.9.
1090
1091 \value VariableRateShadingMap Indicates that image-based specification of
1092 the shading rate is possible. The "image" is not necessarily a texture, it
1093 may be a native 3D API object, depending on the underlying backend and
1094 graphics API at run time. In practice this feature can be expected to be
1095 supported with Direct 3D 12, Vulkan, and Metal, assuming the GPU is modern
1096 enough to support VRS. To check if D3D12/Vulkan-style image-based VRS is
1097 supported, use VariableRateShadingMapWithTexture instead. When this feature
1098 is reported as supported, there are two possibilities: when
1099 VariableRateShadingMapWithTexture is also true, then QRhiShadingRateMap
1100 consumes QRhiTexture objects via the createFrom() overload taking a
1101 QRhiTexture argument. When VariableRateShadingMapWithTexture is false, then
1102 QRhiShadingRateMap consumes some other type of native objects, for example
1103 an MTLRasterizationRateMap in case of Metal. Use the createFrom() overload
1104 taking a NativeShadingRateMap in this case. This enum value has been
1105 introduced in Qt 6.9.
1106
1107 \value VariableRateShadingMapWithTexture Indicates that image-based
1108 specification of the shading rate is supported via regular textures. In
1109 practice this may be supported with Direct 3D 12 and Vulkan. This enum value
1110 has been introduced in Qt 6.9.
1111
1112 \value PerRenderTargetBlending Indicates that per rendertarget blending is
1113 supported i.e. different render targets in MRT framebuffer can have different
1114 blending modes. In practice this can be expected to be supported everywhere
1115 except OpenGL ES, where it is only available with GLES 3.2 implementations.
1116 This enum value has been introduced in Qt 6.9.
1117
1118 \value SampleVariables Indicates that gl_SampleID, gl_SamplePosition,
1119 gl_SampleMaskIn and gl_SampleMask variables are available in fragment shaders.
1120 In practice this can be expected to be supported everywhere except OpenGL ES,
1121 where it is only available with GLES 3.2 implementations.
1122 This enum value has been introduced in Qt 6.9.
1123
1124 \value InstanceIndexIncludesBaseInstance Indicates that \c gl_InstanceIndex
1125 includes the base instance (the \c firstInstance argument in draw calls) in
1126 its value. When this feature is unsupported, but BaseInstance is, it
1127 indicates that \c gl_InstanceIndex always starts at 0, not the base value.
1128 In practice this will be the case for Direct 3D 11 and 12 at the moment.
1129 With Vulkan and Metal this feature is expected to be reported as supported
1130 always. This enum value has been introduced in Qt 6.11.
1131
1132 \value [since 6.11] DepthClamp Indicates that enabling depth clamping is
1133 supported. When reported as unsupported, which will be the case with OpenGL
1134 ES, OpenGL versions before 3.2 without the relevant extension present, and
1135 Metal on the iOS Simulator, calling \l{QRhiGraphicsPipeline::setDepthClamp()}
1136 with an argument of \c true has no effect.
1137
1138 \value [since 6.12] DrawIndirect Indicates that the
1139 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
1140 and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}
1141 functions are available.
1142 In practice this can be expected to be supported everywhere except on
1143 OpenGL ES < 3.1.
1144
1145 \value [since 6.12] DrawIndirectMulti Indicates that a drawCount > 1 is natively
1146 supported by the backend in \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
1147 and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}.
1148 Otherwise, multiple draw calls are issued on the CPU by the RHI.
1149 In practice this can be expected to be supported on Vulkan 1.1+, OpenGL
1150 4.3+, D3D12, and Metal.
1151
1152 \value [since 6.12] ShaderDrawParameters Indicates that the \c{gl_BaseInstance},
1153 \c{gl_BaseVertex} and \c{gl_DrawID} built-in variables are available in shaders.
1154 In practice this can be expected to be supported on Vulkan 1.1+ and with desktop OpenGL
1155 4.6 or \c{GL_ARB_shader_draw_parameters}.
1156
1157 \value [since 6.13] DispatchIndirect Indicates that the
1158 \l{QRhiCommandBuffer::dispatchIndirect()}{dispatchIndirect()} function is
1159 available, allowing compute work group counts to be sourced from a
1160 \l QRhiBuffer at execution time. In practice this can be expected to be
1161 supported wherever the \l Compute feature is reported as supported, that is,
1162 on Vulkan, OpenGL 4.3+ / OpenGL ES 3.1+, Direct3D 11/12, and Metal.
1163
1164 \value [since 6.13] DrawIndirectCount Indicates that the
1165 \l{QRhiCommandBuffer::drawIndirectCount()}{drawIndirectCount()} and
1166 \l{QRhiCommandBuffer::drawIndexedIndirectCount()}{drawIndexedIndirectCount()}
1167 functions are available. These are GPU-driven multi-draw variants where the
1168 actual draw count is read from a buffer at execution time, capped to a
1169 CPU-supplied \c maxDrawCount. In practice this can be expected to be
1170 supported with Vulkan 1.2 and newer, when both the \c drawIndirectCount and
1171 \c multiDrawIndirect device features are present, with OpenGL 4.6 or when
1172 \c GL_ARB_indirect_parameters is available, with Direct3D 12, and with Metal
1173 on devices supporting Metal 3 and indirect command buffers. Direct3D 11 does
1174 not expose an equivalent entry point. Note that with Vulkan the two device
1175 features are queried from the physical device. When importing an existing
1176 VkDevice, the application must make sure the features were enabled when that
1177 device was created, because this cannot be queried afterwards. With Metal
1178 there is a further requirement that this feature flag cannot reflect: the
1179 graphics pipeline must have
1180 \l{QRhiGraphicsPipeline::UsesIndirectDraws}{UsesIndirectDraws} set, without
1181 which the draw is skipped with a warning.
1182
1183 \value [since 6.13] BufferToBufferCopy Indicates that the
1184 \l{QRhiResourceUpdateBatch::copyBuffer()}{copyBuffer()} function is
1185 available, allowing the contents of a QRhiBuffer to be copied into another
1186 QRhiBuffer on the GPU, without a readback to the CPU. In practice this can
1187 be expected to be supported everywhere except with OpenGL ES 2.0 and
1188 desktop OpenGL versions before 3.1 without \c GL_ARB_copy_buffer, which
1189 have no \c glCopyBufferSubData. There is no fallback on such systems
1190 because OpenGL ES 2.0 provides no way of reading back the contents of a
1191 buffer either.
1192
1193 \value [since 6.13] PushConstants Indicates that
1194 \l{QRhiCommandBuffer::setPushConstants()}{setPushConstants()} is
1195 functional, meaning shaders can declare a \c{layout(push_constant)} block
1196 and the data for it can be updated between draw calls without involving a
1197 QRhiShaderResourceBindings. The maximum size of the block is reported by
1198 the \l{QRhi::MaxPushConstantsSize}{MaxPushConstantsSize} resource limit.
1199 Vulkan, Metal and Direct3D 12 have a native equivalent. OpenGL and
1200 Direct3D 11 emulate it, with plain uniforms and with a small dynamic
1201 constant buffer, respectively, so there an update costs about as much as
1202 updating a small uniform buffer; what is gained is not having to have a
1203 QRhiShaderResourceBindings per draw call. There is one case where the
1204 feature is reported as supported but does not apply: with Metal, push
1205 constants are not supported with a graphics pipeline that uses
1206 tessellation.
1207
1208 \value [since 6.13] StaticBuffersOnGpuTimeline Indicates that updates of
1209 QRhiBuffer objects with a type of QRhiBuffer::Immutable or
1210 QRhiBuffer::Static are recorded into the command stream, and so are
1211 executed on the GPU timeline, in the order they were recorded in. In
1212 particular this means that
1213 \l{QRhiResourceUpdateBatch::uploadStaticBuffer()}{uploadStaticBuffer()} and
1214 \l{QRhiResourceUpdateBatch::copyBuffer()}{copyBuffer()} targeting the same
1215 buffer within one \l QRhiResourceUpdateBatch take effect in the recorded
1216 order. When this is reported as not supported, uploads are implemented by
1217 writing to host visible memory on an unrelated timeline, and the ordering
1218 between the two kinds of updates is undefined. In practice this is only
1219 relevant with Metal: the feature is not supported there when the Metal
1220 device does not report an Apple GPU, which is the case on Intel-based Macs,
1221 and also in virtual machines where the paravirtualized device does not
1222 advertise an Apple GPU family. Note that this says nothing about when the
1223 contents become visible to the CPU or to subsequent draw calls, which is
1224 always taken care of by QRhi.
1225 */
1226
1227/*!
1228 \enum QRhi::BeginFrameFlag
1229 Flag values for QRhi::beginFrame()
1230 */
1231
1232/*!
1233 \enum QRhi::EndFrameFlag
1234 Flag values for QRhi::endFrame()
1235
1236 \value SkipPresent Specifies that no present command is to be queued or no
1237 swapBuffers call is to be made. This way no image is presented. Generating
1238 multiple frames with all having this flag set is not recommended (except,
1239 for example, for benchmarking purposes - but keep in mind that backends may
1240 behave differently when it comes to waiting for command completion without
1241 presenting so the results are not comparable between them)
1242 */
1243
1244/*!
1245 \enum QRhi::ResourceLimit
1246 Describes the resource limit to query.
1247
1248 \value TextureSizeMin Minimum texture width and height. This is typically
1249 1. The minimum texture size is handled gracefully, meaning attempting to
1250 create a texture with an empty size will instead create a texture with the
1251 minimum size.
1252
1253 \value TextureSizeMax Maximum texture width and height. This depends on the
1254 graphics API and sometimes the platform or implementation as well.
1255 Typically the value is in the range 4096 - 16384. Attempting to create
1256 textures larger than this is expected to fail.
1257
1258 \value MaxColorAttachments The maximum number of color attachments for a
1259 QRhiTextureRenderTarget, in case multiple render targets are supported. When
1260 MRT is not supported, the value is 1. Otherwise this is typically 8, but
1261 watch out for the fact that OpenGL only mandates 4 as the minimum, and that
1262 is what some OpenGL ES implementations provide.
1263
1264 \value FramesInFlight The number of frames the backend may keep "in
1265 flight": with backends like Vulkan or Metal, it is the responsibility of
1266 QRhi to block whenever starting a new frame and finding the CPU is already
1267 \c{N - 1} frames ahead of the GPU (because the command buffer submitted in
1268 frame no. \c{current} - \c{N} has not yet completed). The value N is what
1269 is returned from here, and is typically 2. This can be relevant to
1270 applications that integrate rendering done directly with the graphics API,
1271 as such rendering code may want to perform double (if the value is 2)
1272 buffering for resources, such as, buffers, similarly to the QRhi backends
1273 themselves. The current frame slot index (a value running 0, 1, .., N-1,
1274 then wrapping around) is retrievable from QRhi::currentFrameSlot(). The
1275 value is 1 for backends where the graphics API offers no such low level
1276 control over the command submission process. Note that pipelining may still
1277 happen even when this value is 1 (some backends, such as D3D11, are
1278 designed to attempt to enable this, for instance, by using an update
1279 strategy for uniform buffers that does not stall the pipeline), but that is
1280 then not controlled by QRhi and so not reflected here in the API.
1281
1282 \value MaxAsyncReadbackFrames The number of \l{QRhi::endFrame()}{submitted}
1283 frames (including the one that contains the readback) after which an
1284 asynchronous texture or buffer readback is guaranteed to complete upon
1285 \l{QRhi::beginFrame()}{starting a new frame}.
1286
1287 \value MaxThreadGroupsPerDimension The maximum number of compute
1288 work/thread groups that can be dispatched. Effectively the maximum value
1289 for the arguments of QRhiCommandBuffer::dispatch(). Typically 65535.
1290
1291 \value MaxThreadsPerThreadGroup The maximum number of invocations in a
1292 single local work group, or in other terminology, the maximum number of
1293 threads in a thread group. Effectively the maximum value for the product of
1294 \c local_size_x, \c local_size_y, and \c local_size_z in the compute
1295 shader. Typical values are 128, 256, 512, 1024, or 1536. Watch out that
1296 both OpenGL ES and Vulkan specify only 128 as the minimum required limit
1297 for implementations. While uncommon for Vulkan, some OpenGL ES 3.1
1298 implementations for mobile/embedded devices only support the spec-mandated
1299 minimum value.
1300
1301 \value MaxThreadGroupX The maximum size of a work/thread group in the X
1302 dimension. Effectively the maximum value of \c local_size_x in the compute
1303 shader. Typically 256 or 1024.
1304
1305 \value MaxThreadGroupY The maximum size of a work/thread group in the Y
1306 dimension. Effectively the maximum value of \c local_size_y in the compute
1307 shader. Typically 256 or 1024.
1308
1309 \value MaxThreadGroupZ The maximum size of a work/thread group in the Z
1310 dimension. Effectively the maximum value of \c local_size_z in the compute
1311 shader. Typically 64 or 256.
1312
1313 \value TextureArraySizeMax Maximum texture array size. Typically in range
1314 256 - 2048. Attempting to \l{QRhi::newTextureArray()}{create a texture
1315 array} with more elements will likely fail.
1316
1317 \value MaxUniformBufferRange The number of bytes that can be exposed from a
1318 uniform buffer to the shaders at once. On OpenGL ES 2.0 and 3.0
1319 implementations this may be as low as 3584 bytes (224 four component, 32
1320 bits per component vectors). Elsewhere the value is typically 16384 (1024
1321 vec4s) or 65536 (4096 vec4s).
1322
1323 \value MaxVertexInputs The number of input attributes to the vertex shader.
1324 The location in a QRhiVertexInputAttribute must be in range \c{[0,
1325 MaxVertexInputs-1]}. The value may be as low as 8 with OpenGL ES 2.0.
1326 Elsewhere, typical values are 16, 31, or 32.
1327
1328 \value MaxVertexOutputs The maximum number of outputs (4 component vector
1329 \c out variables) from the vertex shader. The value may be as low as 8 with
1330 OpenGL ES 2.0, and 15 with OpenGL ES 3.0 and some Metal devices. Elsewhere,
1331 a typical value is 32.
1332
1333 \value ShadingRateImageTileSize The tile size for shading rate textures. 0
1334 if the QRhi::VariableRateShadingMapWithTexture feature is not supported.
1335 Otherwise a value such as 16, indicating, for example, a tile size of 16x16.
1336 Each byte in the (R8UI) shading rate texture defines then the shading rate
1337 for a tile of 16x16 pixels. See \l QRhiShadingRateMap for details.
1338
1339 \value [since 6.13] MaxVertexStorageBuffers The maximum number of
1340 storage buffers that can be bound for reading (bufferLoad) in the
1341 vertex stage. Can legitimately be 0: OpenGL ES makes vertex-stage
1342 storage blocks optional even on 3.1 and newer, and many mobile
1343 drivers report 0 while supporting them via Vulkan on the same GPU;
1344 Direct 3D 11 has no vertex-stage storage buffer support at all.
1345 Clients reading storage buffers in the vertex shader must therefore
1346 check this even when QRhi::Compute is supported. Write access can be
1347 more restricted than this value suggests: with Vulkan it additionally
1348 requires the vertexPipelineStoresAndAtomics device feature, and with
1349 Direct 3D 12 unordered access has lower, resource-binding-tier
1350 dependent limits. With Metal the value is the size of the buffer
1351 argument table, which is shared with vertex inputs and uniform
1352 buffers, so the full count is not available in combination with them.
1353
1354 \value [since 6.13] MaxFragmentStorageBuffers The maximum number of
1355 storage buffers that can be bound for reading (bufferLoad) in the
1356 fragment stage. Like the vertex stage, this is optional in OpenGL ES
1357 (only compute-stage storage blocks are mandatory), so 0 is a
1358 legitimate value. The write access and Metal argument table notes
1359 from MaxVertexStorageBuffers apply here as well; with Direct 3D 11
1360 the value reflects the unordered access view slots, which are shared
1361 with render target outputs.
1362
1363 \value [since 6.13] MaxPushConstantsSize The maximum size in bytes of the
1364 push constant block a shader can declare. 0 when the
1365 \l{QRhi::PushConstants}{PushConstants} feature is not supported.
1366 Portable code should stay within 128 bytes: that is what Direct3D 11 and
1367 12 and OpenGL report and what Vulkan guarantees, whereas Metal reports
1368 4096. Note that with Direct3D 12 even 128 is optimistic, because a block
1369 that size takes 32 of the 64 root signature DWORDs, so with a
1370 sufficiently large QRhiShaderResourceBindings the root signature can
1371 still fail to build. With OpenGL the block competes for the uniform
1372 budget with everything else in the shader.
1373 */
1374
1375/*!
1376 \class QRhiInitParams
1377 \inmodule QtGuiPrivate
1378 \inheaderfile rhi/qrhi.h
1379 \since 6.6
1380 \brief Base class for backend-specific initialization parameters.
1381
1382 Contains fields that are relevant to all backends.
1383
1384 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1385 for details.
1386 */
1387
1388/*!
1389 \class QRhiDepthStencilClearValue
1390 \inmodule QtGuiPrivate
1391 \inheaderfile rhi/qrhi.h
1392 \since 6.6
1393 \brief Specifies clear values for a depth or stencil buffer.
1394
1395 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1396 for details.
1397 */
1398
1399/*!
1400 \fn QRhiDepthStencilClearValue::QRhiDepthStencilClearValue() = default
1401
1402 Constructs a depth/stencil clear value with depth clear value 1.0f and
1403 stencil clear value 0.
1404 */
1405
1406/*!
1407 Constructs a depth/stencil clear value with depth clear value \a d and
1408 stencil clear value \a s.
1409 */
1410QRhiDepthStencilClearValue::QRhiDepthStencilClearValue(float d, quint32 s)
1411 : m_d(d),
1412 m_s(s)
1413{
1414}
1415
1416/*!
1417 \fn float QRhiDepthStencilClearValue::depthClearValue() const
1418 \return the depth clear value. In most cases this is 1.0f.
1419 */
1420
1421/*!
1422 \fn void QRhiDepthStencilClearValue::setDepthClearValue(float d)
1423 Sets the depth clear value to \a d.
1424 */
1425
1426/*!
1427 \fn quint32 QRhiDepthStencilClearValue::stencilClearValue() const
1428 \return the stencil clear value. In most cases this is 0.
1429 */
1430
1431/*!
1432 \fn void QRhiDepthStencilClearValue::setStencilClearValue(quint32 s)
1433 Sets the stencil clear value to \a s.
1434 */
1435
1436/*!
1437 \fn bool QRhiDepthStencilClearValue::operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1438
1439 \return \c true if the values in the two QRhiDepthStencilClearValue objects
1440 \a a and \a b are equal.
1441 */
1442
1443/*!
1444 \fn bool QRhiDepthStencilClearValue::operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1445
1446 \return \c false if the values in the two QRhiDepthStencilClearValue
1447 objects \a a and \a b are equal; otherwise returns \c true.
1448
1449*/
1450
1451/*!
1452 \fn size_t QRhiDepthStencilClearValue::qHash(const QRhiDepthStencilClearValue &key, size_t seed)
1453 \qhash{QRhiDepthStencilClearValue}
1454 */
1455
1456#ifndef QT_NO_DEBUG_STREAM
1457QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
1458{
1459 QDebugStateSaver saver(dbg);
1460 dbg.nospace() << "QRhiDepthStencilClearValue(depth-clear=" << v.depthClearValue()
1461 << " stencil-clear=" << v.stencilClearValue()
1462 << ')';
1463 return dbg;
1464}
1465#endif
1466
1467/*!
1468 \class QRhiViewport
1469 \inmodule QtGuiPrivate
1470 \inheaderfile rhi/qrhi.h
1471 \since 6.6
1472 \brief Specifies a viewport rectangle.
1473
1474 Used with QRhiCommandBuffer::setViewport().
1475
1476 QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
1477 bottom-left. Negative width or height are not allowed.
1478
1479 Typical usage is like the following:
1480
1481 \code
1482 const QSize outputSizeInPixels = swapchain->currentPixelSize();
1483 const QRhiViewport viewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height());
1484 cb->beginPass(swapchain->currentFrameRenderTarget(), Qt::black, { 1.0f, 0 });
1485 cb->setGraphicsPipeline(ps);
1486 cb->setViewport(viewport);
1487 // ...
1488 \endcode
1489
1490 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1491 for details.
1492
1493 \sa QRhiCommandBuffer::setViewport(), QRhi::clipSpaceCorrMatrix(), QRhiScissor
1494 */
1495
1496/*!
1497 \fn QRhiViewport::QRhiViewport() = default
1498
1499 Constructs a viewport description with an empty rectangle and a depth range
1500 of 0.0f - 1.0f.
1501
1502 \sa QRhi::clipSpaceCorrMatrix()
1503 */
1504
1505/*!
1506 Constructs a viewport description with the rectangle specified by \a x, \a
1507 y, \a w, \a h and the depth range \a minDepth and \a maxDepth.
1508
1509 \note \a x and \a y are assumed to be the bottom-left position. \a w and \a
1510 h should not be negative, the viewport will be ignored by
1511 QRhiCommandBuffer::setViewport() otherwise.
1512
1513 \sa QRhi::clipSpaceCorrMatrix()
1514 */
1515QRhiViewport::QRhiViewport(float x, float y, float w, float h, float minDepth, float maxDepth)
1516 : m_rect { { x, y, w, h } },
1517 m_minDepth(minDepth),
1518 m_maxDepth(maxDepth)
1519{
1520}
1521
1522/*!
1523 \fn std::array<float, 4> QRhiViewport::viewport() const
1524 \return the viewport x, y, width, and height.
1525 */
1526
1527/*!
1528 \fn void QRhiViewport::setViewport(float x, float y, float w, float h)
1529 Sets the viewport's position and size to \a x, \a y, \a w, and \a h.
1530
1531 \note Viewports are specified in a coordinate system that has its origin in
1532 the bottom-left.
1533 */
1534
1535/*!
1536 \fn float QRhiViewport::minDepth() const
1537 \return the minDepth value of the depth range of the viewport.
1538 */
1539
1540/*!
1541 \fn void QRhiViewport::setMinDepth(float minDepth)
1542 Sets the \a minDepth of the depth range of the viewport.
1543 By default this is set to 0.0f.
1544 */
1545
1546/*!
1547 \fn float QRhiViewport::maxDepth() const
1548 \return the maxDepth value of the depth range of the viewport.
1549 */
1550
1551/*!
1552 \fn void QRhiViewport::setMaxDepth(float maxDepth)
1553 Sets the \a maxDepth of the depth range of the viewport.
1554 By default this is set to 1.0f.
1555 */
1556
1557/*!
1558 \fn bool QRhiViewport::operator==(const QRhiViewport &a, const QRhiViewport &b) noexcept
1559
1560 \return \c true if the values in the two QRhiViewport objects
1561 \a a and \a b are equal.
1562 */
1563
1564/*!
1565 \fn bool QRhiViewport::operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept
1566
1567 \return \c false if the values in the two QRhiViewport
1568 objects \a a and \a b are equal; otherwise returns \c true.
1569*/
1570
1571/*!
1572 \fn size_t QRhiViewport::qHash(const QRhiViewport &key, size_t seed)
1573 \qhash{QRhiViewport}
1574 */
1575
1576#ifndef QT_NO_DEBUG_STREAM
1577QDebug operator<<(QDebug dbg, const QRhiViewport &v)
1578{
1579 QDebugStateSaver saver(dbg);
1580 const std::array<float, 4> r = v.viewport();
1581 dbg.nospace() << "QRhiViewport(bottom-left-x=" << r[0]
1582 << " bottom-left-y=" << r[1]
1583 << " width=" << r[2]
1584 << " height=" << r[3]
1585 << " minDepth=" << v.minDepth()
1586 << " maxDepth=" << v.maxDepth()
1587 << ')';
1588 return dbg;
1589}
1590#endif
1591
1592/*!
1593 \class QRhiScissor
1594 \inmodule QtGuiPrivate
1595 \inheaderfile rhi/qrhi.h
1596 \since 6.6
1597 \brief Specifies a scissor rectangle.
1598
1599 Used with QRhiCommandBuffer::setScissor(). Setting a scissor rectangle is
1600 only possible with a QRhiGraphicsPipeline that has
1601 QRhiGraphicsPipeline::UsesScissor set.
1602
1603 QRhi assumes OpenGL-style scissor coordinates, meaning x and y are
1604 bottom-left. Negative width or height are not allowed. However, apart from
1605 that, the flexible OpenGL semantics apply: negative x and y, partially out
1606 of bounds rectangles, etc. will be handled gracefully, clamping as
1607 appropriate. Therefore, any rendering logic targeting OpenGL can feed
1608 scissor rectangles into QRhiScissor as-is, without any adaptation.
1609
1610 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1611 for details.
1612
1613 \sa QRhiCommandBuffer::setScissor(), QRhiViewport
1614 */
1615
1616/*!
1617 \fn QRhiScissor::QRhiScissor() = default
1618
1619 Constructs an empty scissor.
1620 */
1621
1622/*!
1623 Constructs a scissor with the rectangle specified by \a x, \a y, \a w, and
1624 \a h.
1625
1626 \note \a x and \a y are assumed to be the bottom-left position. Negative \a w
1627 or \a h are not allowed, such scissor rectangles will be ignored by
1628 QRhiCommandBuffer. Other than that, the flexible OpenGL semantics apply:
1629 negative x and y, partially out of bounds rectangles, etc. will be handled
1630 gracefully, clamping as appropriate.
1631 */
1632QRhiScissor::QRhiScissor(int x, int y, int w, int h)
1633 : m_rect { { x, y, w, h } }
1634{
1635}
1636
1637/*!
1638 \fn std::array<int, 4> QRhiScissor::scissor() const
1639 \return the scissor position and size.
1640 */
1641
1642/*!
1643 \fn void QRhiScissor::setScissor(int x, int y, int w, int h)
1644 Sets the scissor position and size to \a x, \a y, \a w, \a h.
1645
1646 \note The position is always expected to be specified in a coordinate
1647 system that has its origin in the bottom-left corner, like OpenGL.
1648 */
1649
1650/*!
1651 \fn bool QRhiScissor::operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept
1652
1653 \return \c true if the values in the two QRhiScissor objects
1654 \a a and \a b are equal.
1655 */
1656
1657/*!
1658 \fn bool QRhiScissor::operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept
1659
1660 \return \c false if the values in the two QRhiScissor
1661 objects \a a and \a b are equal; otherwise returns \c true.
1662*/
1663
1664/*!
1665 \fn size_t QRhiScissor::qHash(const QRhiScissor &key, size_t seed)
1666 \qhash{QRhiScissor}
1667 */
1668
1669#ifndef QT_NO_DEBUG_STREAM
1670QDebug operator<<(QDebug dbg, const QRhiScissor &s)
1671{
1672 QDebugStateSaver saver(dbg);
1673 const std::array<int, 4> r = s.scissor();
1674 dbg.nospace() << "QRhiScissor(bottom-left-x=" << r[0]
1675 << " bottom-left-y=" << r[1]
1676 << " width=" << r[2]
1677 << " height=" << r[3]
1678 << ')';
1679 return dbg;
1680}
1681#endif
1682
1683/*!
1684 \class QRhiVertexInputBinding
1685 \inmodule QtGuiPrivate
1686 \inheaderfile rhi/qrhi.h
1687 \since 6.6
1688 \brief Describes a vertex input binding.
1689
1690 Specifies the stride (in bytes, must be a multiple of 4), the
1691 classification and optionally the instance step rate.
1692
1693 As an example, assume a vertex shader with the following inputs:
1694
1695 \badcode
1696 layout(location = 0) in vec4 position;
1697 layout(location = 1) in vec2 texcoord;
1698 \endcode
1699
1700 Now let's assume also that 3 component vertex positions \c{(x, y, z)} and 2
1701 component texture coordinates \c{(u, v)} are provided in a non-interleaved
1702 format in a buffer (or separate buffers even). Defining two bindings
1703 could then be done like this:
1704
1705 \code
1706 QRhiVertexInputLayout inputLayout;
1707 inputLayout.setBindings({
1708 { 3 * sizeof(float) },
1709 { 2 * sizeof(float) }
1710 });
1711 \endcode
1712
1713 Only the stride is interesting here since instancing is not used. The
1714 binding number is given by the index of the QRhiVertexInputBinding
1715 element in the bindings vector of the QRhiVertexInputLayout.
1716
1717 Once a graphics pipeline with this vertex input layout is bound, the vertex
1718 inputs could be set up like the following for drawing a cube with 36
1719 vertices, assuming we have a single buffer with first the positions and
1720 then the texture coordinates:
1721
1722 \code
1723 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1724 { cubeBuf, 0 },
1725 { cubeBuf, 36 * 3 * sizeof(float) }
1726 };
1727 cb->setVertexInput(0, 2, vbufBindings);
1728 \endcode
1729
1730 Note how the index defined by \c {startBinding + i}, where \c i is the
1731 index in the second argument of
1732 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}, matches the
1733 index of the corresponding entry in the \c bindings vector of the
1734 QRhiVertexInputLayout.
1735
1736 \note the stride must always be a multiple of 4.
1737
1738 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1739 for details.
1740
1741 \sa QRhiCommandBuffer::setVertexInput()
1742 */
1743
1744/*!
1745 \enum QRhiVertexInputBinding::Classification
1746 Describes the input data classification.
1747
1748 \value PerVertex Data is per-vertex
1749 \value PerInstance Data is per-instance
1750 */
1751
1752/*!
1753 \fn QRhiVertexInputBinding::QRhiVertexInputBinding() = default
1754
1755 Constructs a default vertex input binding description.
1756 */
1757
1758/*!
1759 Constructs a vertex input binding description with the specified \a stride,
1760 classification \a cls, and instance step rate \a stepRate.
1761
1762 \note \a stepRate other than 1 is only supported when
1763 QRhi::CustomInstanceStepRate is reported to be supported.
1764 */
1765QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cls, quint32 stepRate)
1766 : m_stride(stride),
1767 m_classification(cls),
1768 m_instanceStepRate(stepRate)
1769{
1770}
1771
1772/*!
1773 \fn quint32 QRhiVertexInputBinding::stride() const
1774 \return the stride in bytes.
1775 */
1776
1777/*!
1778 \fn void QRhiVertexInputBinding::setStride(quint32 s)
1779 Sets the stride to \a s.
1780 */
1781
1782/*!
1783 \fn QRhiVertexInputBinding::Classification QRhiVertexInputBinding::classification() const
1784 \return the input data classification.
1785 */
1786
1787/*!
1788 \fn void QRhiVertexInputBinding::setClassification(Classification c)
1789 Sets the input data classification \a c. By default this is set to PerVertex.
1790 */
1791
1792/*!
1793 \fn quint32 QRhiVertexInputBinding::instanceStepRate() const
1794 \return the instance step rate.
1795 */
1796
1797/*!
1798 \fn void QRhiVertexInputBinding::setInstanceStepRate(quint32 rate)
1799 Sets the instance step \a rate. By default this is set to 1.
1800 */
1801
1802/*!
1803 \fn bool QRhiVertexInputBinding::operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1804
1805 \return \c true if the values in the two QRhiVertexInputBinding objects
1806 \a a and \a b are equal.
1807 */
1808
1809/*!
1810 \fn bool QRhiVertexInputBinding::operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1811
1812 \return \c false if the values in the two QRhiVertexInputBinding
1813 objects \a a and \a b are equal; otherwise returns \c true.
1814*/
1815
1816/*!
1817 \fn size_t QRhiVertexInputBinding::qHash(const QRhiVertexInputBinding &key, size_t seed)
1818 \qhash{QRhiVertexInputBinding}
1819 */
1820
1821#ifndef QT_NO_DEBUG_STREAM
1822QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
1823{
1824 QDebugStateSaver saver(dbg);
1825 dbg.nospace() << "QRhiVertexInputBinding(stride=" << b.stride()
1826 << " cls=" << b.classification()
1827 << " step-rate=" << b.instanceStepRate()
1828 << ')';
1829 return dbg;
1830}
1831#endif
1832
1833/*!
1834 \class QRhiVertexInputAttribute
1835 \inmodule QtGuiPrivate
1836 \inheaderfile rhi/qrhi.h
1837 \since 6.6
1838 \brief Describes a single vertex input element.
1839
1840 The members specify the binding number, location, format, and offset for a
1841 single vertex input element.
1842
1843 \note For HLSL it is assumed that the vertex shader translated from SPIR-V
1844 uses
1845 \c{TEXCOORD<location>} as the semantic for each input. Hence no separate
1846 semantic name and index.
1847
1848 As an example, assume a vertex shader with the following inputs:
1849
1850 \badcode
1851 layout(location = 0) in vec4 position;
1852 layout(location = 1) in vec2 texcoord;
1853 \endcode
1854
1855 Now let's assume that we have 3 component vertex positions \c{(x, y, z)}
1856 and 2 component texture coordinates \c{(u, v)} are provided in a
1857 non-interleaved format in a buffer (or separate buffers even). Once two
1858 bindings are defined, the attributes could be specified as:
1859
1860 \code
1861 QRhiVertexInputLayout inputLayout;
1862 inputLayout.setBindings({
1863 { 3 * sizeof(float) },
1864 { 2 * sizeof(float) }
1865 });
1866 inputLayout.setAttributes({
1867 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1868 { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
1869 });
1870 \endcode
1871
1872 Once a graphics pipeline with this vertex input layout is bound, the vertex
1873 inputs could be set up like the following for drawing a cube with 36
1874 vertices, assuming we have a single buffer with first the positions and
1875 then the texture coordinates:
1876
1877 \code
1878 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1879 { cubeBuf, 0 },
1880 { cubeBuf, 36 * 3 * sizeof(float) }
1881 };
1882 cb->setVertexInput(0, 2, vbufBindings);
1883 \endcode
1884
1885 When working with interleaved data, there will typically be just one
1886 binding, with multiple attributes referring to that same buffer binding
1887 point:
1888
1889 \code
1890 QRhiVertexInputLayout inputLayout;
1891 inputLayout.setBindings({
1892 { 5 * sizeof(float) }
1893 });
1894 inputLayout.setAttributes({
1895 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1896 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
1897 });
1898 \endcode
1899
1900 and then:
1901
1902 \code
1903 const QRhiCommandBuffer::VertexInput vbufBinding(interleavedCubeBuf, 0);
1904 cb->setVertexInput(0, 1, &vbufBinding);
1905 \endcode
1906
1907 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1908 for details.
1909
1910 \sa QRhiCommandBuffer::setVertexInput()
1911 */
1912
1913/*!
1914 \enum QRhiVertexInputAttribute::Format
1915 Specifies the type of the element data.
1916
1917 \value Float4 Four component float vector
1918 \value Float3 Three component float vector
1919 \value Float2 Two component float vector
1920 \value Float Float
1921 \value UNormByte4 Four component normalized unsigned byte vector
1922 \value UNormByte2 Two component normalized unsigned byte vector
1923 \value UNormByte Normalized unsigned byte
1924 \value UInt4 Four component unsigned integer vector
1925 \value UInt3 Three component unsigned integer vector
1926 \value UInt2 Two component unsigned integer vector
1927 \value UInt Unsigned integer
1928 \value SInt4 Four component signed integer vector
1929 \value SInt3 Three component signed integer vector
1930 \value SInt2 Two component signed integer vector
1931 \value SInt Signed integer
1932 \value Half4 Four component half precision (16 bit) float vector
1933 \value Half3 Three component half precision (16 bit) float vector
1934 \value Half2 Two component half precision (16 bit) float vector
1935 \value Half Half precision (16 bit) float
1936 \value UShort4 Four component unsigned short (16 bit) integer vector
1937 \value UShort3 Three component unsigned short (16 bit) integer vector
1938 \value UShort2 Two component unsigned short (16 bit) integer vector
1939 \value UShort Unsigned short (16 bit) integer
1940 \value SShort4 Four component signed short (16 bit) integer vector
1941 \value SShort3 Three component signed short (16 bit) integer vector
1942 \value SShort2 Two component signed short (16 bit) integer vector
1943 \value SShort Signed short (16 bit) integer
1944
1945 \note Support for half precision floating point attributes is indicated at
1946 run time by the QRhi::Feature::HalfAttributes feature flag.
1947
1948 \note Direct3D 11/12 supports 16 bit input attributes, but does not support
1949 the Half3, UShort3 or SShort3 types. The D3D backends pass through Half3 as
1950 Half4, UShort3 as UShort4, and SShort3 as SShort4. To ensure cross platform
1951 compatibility, 16 bit inputs should be padded to 8 bytes.
1952 */
1953
1954/*!
1955 \fn QRhiVertexInputAttribute::QRhiVertexInputAttribute() = default
1956
1957 Constructs a default vertex input attribute description.
1958 */
1959
1960/*!
1961 Constructs a vertex input attribute description with the specified \a
1962 binding number, \a location, \a format, and \a offset.
1963
1964 \a matrixSlice should be -1 except when this attribute corresponds to a row
1965 or column of a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming
1966 4 consecutive vertex input locations), in which case it is the index of the
1967 row or column. \c{location - matrixSlice} must always be equal to the \c
1968 location for the first row or column of the unrolled matrix.
1969 */
1970QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset, int matrixSlice)
1971 : m_binding(binding),
1972 m_location(location),
1973 m_format(format),
1974 m_offset(offset),
1975 m_matrixSlice(matrixSlice)
1976{
1977}
1978
1979/*!
1980 \fn int QRhiVertexInputAttribute::binding() const
1981 \return the binding point index.
1982 */
1983
1984/*!
1985 \fn void QRhiVertexInputAttribute::setBinding(int b)
1986 Sets the binding point index to \a b.
1987 By default this is set to 0.
1988 */
1989
1990/*!
1991 \fn int QRhiVertexInputAttribute::location() const
1992 \return the location of the vertex input element.
1993 */
1994
1995/*!
1996 \fn void QRhiVertexInputAttribute::setLocation(int loc)
1997 Sets the location of the vertex input element to \a loc.
1998 By default this is set to 0.
1999 */
2000
2001/*!
2002 \fn QRhiVertexInputAttribute::Format QRhiVertexInputAttribute::format() const
2003 \return the format of the vertex input element.
2004 */
2005
2006/*!
2007 \fn void QRhiVertexInputAttribute::setFormat(Format f)
2008 Sets the format of the vertex input element to \a f.
2009 By default this is set to Float4.
2010 */
2011
2012/*!
2013 \fn quint32 QRhiVertexInputAttribute::offset() const
2014 \return the byte offset for the input element.
2015 */
2016
2017/*!
2018 \fn void QRhiVertexInputAttribute::setOffset(quint32 ofs)
2019 Sets the byte offset for the input element to \a ofs.
2020 */
2021
2022/*!
2023 \fn int QRhiVertexInputAttribute::matrixSlice() const
2024
2025 \return the matrix slice if the input element corresponds to a row or
2026 column of a matrix, or -1 if not relevant.
2027 */
2028
2029/*!
2030 \fn void QRhiVertexInputAttribute::setMatrixSlice(int slice)
2031
2032 Sets the matrix \a slice. By default this is set to -1, and should be set
2033 to a >= 0 value only when this attribute corresponds to a row or column of
2034 a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming 4
2035 consecutive vertex input locations), in which case it is the index of the
2036 row or column. \c{location - matrixSlice} must always be equal to the \c
2037 location for the first row or column of the unrolled matrix.
2038 */
2039
2040/*!
2041 \fn bool QRhiVertexInputAttribute::operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
2042
2043 \return \c true if the values in the two QRhiVertexInputAttribute objects
2044 \a a and \a b are equal.
2045 */
2046
2047/*!
2048 \fn bool QRhiVertexInputAttribute::operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
2049
2050 \return \c false if the values in the two QRhiVertexInputAttribute
2051 objects \a a and \a b are equal; otherwise returns \c true.
2052*/
2053
2054/*!
2055 \fn size_t QRhiVertexInputAttribute::qHash(const QRhiVertexInputAttribute &key, size_t seed)
2056 \qhash{QRhiVertexInputAttribute}
2057 */
2058
2059#ifndef QT_NO_DEBUG_STREAM
2060QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a)
2061{
2062 QDebugStateSaver saver(dbg);
2063 dbg.nospace() << "QRhiVertexInputAttribute(binding=" << a.binding()
2064 << " location=" << a.location()
2065 << " format=" << a.format()
2066 << " offset=" << a.offset()
2067 << ')';
2068 return dbg;
2069}
2070#endif
2071
2072QRhiVertexInputAttribute::Format QRhiImplementation::shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const
2073{
2074 switch (type) {
2075 case QShaderDescription::Vec4:
2076 return QRhiVertexInputAttribute::Float4;
2077 case QShaderDescription::Vec3:
2078 return QRhiVertexInputAttribute::Float3;
2079 case QShaderDescription::Vec2:
2080 return QRhiVertexInputAttribute::Float2;
2081 case QShaderDescription::Float:
2082 return QRhiVertexInputAttribute::Float;
2083
2084 case QShaderDescription::Int4:
2085 return QRhiVertexInputAttribute::SInt4;
2086 case QShaderDescription::Int3:
2087 return QRhiVertexInputAttribute::SInt3;
2088 case QShaderDescription::Int2:
2089 return QRhiVertexInputAttribute::SInt2;
2090 case QShaderDescription::Int:
2091 return QRhiVertexInputAttribute::SInt;
2092
2093 case QShaderDescription::Uint4:
2094 return QRhiVertexInputAttribute::UInt4;
2095 case QShaderDescription::Uint3:
2096 return QRhiVertexInputAttribute::UInt3;
2097 case QShaderDescription::Uint2:
2098 return QRhiVertexInputAttribute::UInt2;
2099 case QShaderDescription::Uint:
2100 return QRhiVertexInputAttribute::UInt;
2101
2102 case QShaderDescription::Half4:
2103 return QRhiVertexInputAttribute::Half4;
2104 case QShaderDescription::Half3:
2105 return QRhiVertexInputAttribute::Half3;
2106 case QShaderDescription::Half2:
2107 return QRhiVertexInputAttribute::Half2;
2108 case QShaderDescription::Half:
2109 return QRhiVertexInputAttribute::Half;
2110
2111 default:
2112 Q_UNREACHABLE_RETURN(QRhiVertexInputAttribute::Float);
2113 }
2114}
2115
2116quint32 QRhiImplementation::byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const
2117{
2118 switch (format) {
2119 case QRhiVertexInputAttribute::Float4:
2120 return 4 * sizeof(float);
2121 case QRhiVertexInputAttribute::Float3:
2122 return 4 * sizeof(float); // vec3 still takes 16 bytes
2123 case QRhiVertexInputAttribute::Float2:
2124 return 2 * sizeof(float);
2125 case QRhiVertexInputAttribute::Float:
2126 return sizeof(float);
2127
2128 case QRhiVertexInputAttribute::UNormByte4:
2129 return 4 * sizeof(quint8);
2130 case QRhiVertexInputAttribute::UNormByte2:
2131 return 2 * sizeof(quint8);
2132 case QRhiVertexInputAttribute::UNormByte:
2133 return sizeof(quint8);
2134
2135 case QRhiVertexInputAttribute::UInt4:
2136 return 4 * sizeof(quint32);
2137 case QRhiVertexInputAttribute::UInt3:
2138 return 4 * sizeof(quint32); // ivec3 still takes 16 bytes
2139 case QRhiVertexInputAttribute::UInt2:
2140 return 2 * sizeof(quint32);
2141 case QRhiVertexInputAttribute::UInt:
2142 return sizeof(quint32);
2143
2144 case QRhiVertexInputAttribute::SInt4:
2145 return 4 * sizeof(qint32);
2146 case QRhiVertexInputAttribute::SInt3:
2147 return 4 * sizeof(qint32); // uvec3 still takes 16 bytes
2148 case QRhiVertexInputAttribute::SInt2:
2149 return 2 * sizeof(qint32);
2150 case QRhiVertexInputAttribute::SInt:
2151 return sizeof(qint32);
2152
2153 case QRhiVertexInputAttribute::Half4:
2154 return 4 * sizeof(qfloat16);
2155 case QRhiVertexInputAttribute::Half3:
2156 return 4 * sizeof(qfloat16); // half3 still takes 8 bytes
2157 case QRhiVertexInputAttribute::Half2:
2158 return 2 * sizeof(qfloat16);
2159 case QRhiVertexInputAttribute::Half:
2160 return sizeof(qfloat16);
2161
2162 case QRhiVertexInputAttribute::UShort4:
2163 return 4 * sizeof(quint16);
2164 case QRhiVertexInputAttribute::UShort3:
2165 return 4 * sizeof(quint16); // ivec3 still takes 8 bytes
2166 case QRhiVertexInputAttribute::UShort2:
2167 return 2 * sizeof(quint16);
2168 case QRhiVertexInputAttribute::UShort:
2169 return sizeof(quint16);
2170
2171 case QRhiVertexInputAttribute::SShort4:
2172 return 4 * sizeof(qint16);
2173 case QRhiVertexInputAttribute::SShort3:
2174 return 4 * sizeof(qint16); // uvec3 still takes 8 bytes
2175 case QRhiVertexInputAttribute::SShort2:
2176 return 2 * sizeof(qint16);
2177 case QRhiVertexInputAttribute::SShort:
2178 return sizeof(qint16);
2179
2180 default:
2181 Q_UNREACHABLE_RETURN(1);
2182 }
2183}
2184
2185/*!
2186 \class QRhiVertexInputLayout
2187 \inmodule QtGuiPrivate
2188 \inheaderfile rhi/qrhi.h
2189 \since 6.6
2190 \brief Describes the layout of vertex inputs consumed by a vertex shader.
2191
2192 The vertex input layout is defined by the collections of
2193 QRhiVertexInputBinding and QRhiVertexInputAttribute.
2194
2195 As an example, let's assume that we have a single buffer with 3 component
2196 vertex positions and 2 component UV coordinates interleaved (\c x, \c y, \c
2197 z, \c u, \c v), that the position and UV are expected at input locations 0
2198 and 1 by the vertex shader, and that the vertex buffer will be bound at
2199 binding point 0 using
2200 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()} later on:
2201
2202 \code
2203 QRhiVertexInputLayout inputLayout;
2204 inputLayout.setBindings({
2205 { 5 * sizeof(float) }
2206 });
2207 inputLayout.setAttributes({
2208 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
2209 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
2210 });
2211 \endcode
2212
2213 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2214 for details.
2215 */
2216
2217/*!
2218 \fn QRhiVertexInputLayout::QRhiVertexInputLayout() = default
2219
2220 Constructs an empty vertex input layout description.
2221 */
2222
2223/*!
2224 \fn void QRhiVertexInputLayout::setBindings(std::initializer_list<QRhiVertexInputBinding> list)
2225 Sets the bindings from the specified \a list.
2226 */
2227
2228/*!
2229 \fn template<typename InputIterator> void QRhiVertexInputLayout::setBindings(InputIterator first, InputIterator last)
2230 Sets the bindings using the iterators \a first and \a last.
2231 */
2232
2233/*!
2234 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cbeginBindings() const
2235 \return a const iterator pointing to the first item in the binding list.
2236 */
2237
2238/*!
2239 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cendBindings() const
2240 \return a const iterator pointing just after the last item in the binding list.
2241 */
2242
2243/*!
2244 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::bindingAt(qsizetype index) const
2245 \return the binding at the given \a index.
2246 */
2247
2248/*!
2249 \fn qsizetype QRhiVertexInputLayout::bindingCount() const
2250 \return the number of bindings.
2251 */
2252
2253/*!
2254 \fn void QRhiVertexInputLayout::setAttributes(std::initializer_list<QRhiVertexInputAttribute> list)
2255 Sets the attributes from the specified \a list.
2256 */
2257
2258/*!
2259 \fn template<typename InputIterator> void QRhiVertexInputLayout::setAttributes(InputIterator first, InputIterator last)
2260 Sets the attributes using the iterators \a first and \a last.
2261 */
2262
2263/*!
2264 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cbeginAttributes() const
2265 \return a const iterator pointing to the first item in the attribute list.
2266 */
2267
2268/*!
2269 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cendAttributes() const
2270 \return a const iterator pointing just after the last item in the attribute list.
2271 */
2272
2273/*!
2274 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::attributeAt(qsizetype index) const
2275 \return the attribute at the given \a index.
2276 */
2277
2278/*!
2279 \fn qsizetype QRhiVertexInputLayout::attributeCount() const
2280 \return the number of attributes.
2281 */
2282
2283/*!
2284 \fn bool QRhiVertexInputLayout::operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2285
2286 \return \c true if the values in the two QRhiVertexInputLayout objects
2287 \a a and \a b are equal.
2288 */
2289
2290/*!
2291 \fn bool QRhiVertexInputLayout::operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2292
2293 \return \c false if the values in the two QRhiVertexInputLayout
2294 objects \a a and \a b are equal; otherwise returns \c true.
2295*/
2296
2297/*!
2298 \fn size_t QRhiVertexInputLayout::qHash(const QRhiVertexInputLayout &key, size_t seed)
2299 \qhash{QRhiVertexInputLayout}
2300 */
2301
2302#ifndef QT_NO_DEBUG_STREAM
2303QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
2304{
2305 QDebugStateSaver saver(dbg);
2306 dbg.nospace() << "QRhiVertexInputLayout(bindings=" << v.m_bindings
2307 << " attributes=" << v.m_attributes
2308 << ')';
2309 return dbg;
2310}
2311#endif
2312
2313/*!
2314 \class QRhiShaderStage
2315 \inmodule QtGuiPrivate
2316 \inheaderfile rhi/qrhi.h
2317 \since 6.6
2318 \brief Specifies the type and the shader code for a shader stage in the pipeline.
2319
2320 When setting up a QRhiGraphicsPipeline, a collection of shader stages are
2321 specified. The QRhiShaderStage contains a QShader and some associated
2322 metadata, such as the graphics pipeline stage, and the
2323 \l{QShader::Variant}{shader variant} to select. There is no need to specify
2324 the shader language or version because the QRhi backend in use at runtime
2325 will take care of choosing the appropriate shader version from the
2326 collection within the QShader.
2327
2328 The typical usage is in combination with
2329 QRhiGraphicsPipeline::setShaderStages(), shown here with a simple approach
2330 to load the QShader from \c{.qsb} files generated offline or at build time:
2331
2332 \code
2333 QShader getShader(const QString &name)
2334 {
2335 QFile f(name);
2336 return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
2337 }
2338
2339 QShader vs = getShader("material.vert.qsb");
2340 QShader fs = getShader("material.frag.qsb");
2341 pipeline->setShaderStages({
2342 { QRhiShaderStage::Vertex, vs },
2343 { QRhiShaderStage::Fragment, fs }
2344 });
2345 \endcode
2346
2347 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2348 for details.
2349 */
2350
2351/*!
2352 \enum QRhiShaderStage::Type
2353 Specifies the type of the shader stage.
2354
2355 \value Vertex Vertex stage
2356
2357 \value TessellationControl Tessellation control (hull shader) stage. Must
2358 be used only when the QRhi::Tessellation feature is supported.
2359
2360 \value TessellationEvaluation Tessellation evaluation (domain shader)
2361 stage. Must be used only when the QRhi::Tessellation feature is supported.
2362
2363 \value Fragment Fragment (pixel shader) stage
2364
2365 \value Compute Compute stage. Must be used only when the QRhi::Compute
2366 feature is supported.
2367
2368 \value Geometry Geometry stage. Must be used only when the
2369 QRhi::GeometryShader feature is supported.
2370 */
2371
2372/*!
2373 \fn QRhiShaderStage::QRhiShaderStage() = default
2374
2375 Constructs a shader stage description for the vertex stage with an empty
2376 QShader.
2377 */
2378
2379/*!
2380 \fn QRhiShaderStage::Type QRhiShaderStage::type() const
2381 \return the type of the stage.
2382 */
2383
2384/*!
2385 \fn void QRhiShaderStage::setType(Type t)
2386
2387 Sets the type of the stage to \a t. Setters should rarely be needed in
2388 pratice. Most applications will likely use the QRhiShaderStage constructor
2389 in most cases.
2390 */
2391
2392/*!
2393 \fn QShader QRhiShaderStage::shader() const
2394 \return the QShader to be used for this stage in the graphics pipeline.
2395 */
2396
2397/*!
2398 \fn void QRhiShaderStage::setShader(const QShader &s)
2399 Sets the shader collection \a s.
2400 */
2401
2402/*!
2403 \fn QShader::Variant QRhiShaderStage::shaderVariant() const
2404 \return the requested shader variant.
2405 */
2406
2407/*!
2408 \fn void QRhiShaderStage::setShaderVariant(QShader::Variant v)
2409 Sets the requested shader variant \a v.
2410 */
2411
2412/*!
2413 Constructs a shader stage description with the \a type of the stage and the
2414 \a shader.
2415
2416 The shader variant \a v defaults to QShader::StandardShader. A
2417 QShader contains multiple source and binary versions of a shader.
2418 In addition, it can also contain variants of the shader with slightly
2419 modified code. \a v can then be used to select the desired variant.
2420 */
2421QRhiShaderStage::QRhiShaderStage(Type type, const QShader &shader, QShader::Variant v)
2422 : m_type(type),
2423 m_shader(shader),
2424 m_shaderVariant(v)
2425{
2426}
2427
2428/*!
2429 \fn bool QRhiShaderStage::operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2430
2431 \return \c true if the values in the two QRhiShaderStage objects
2432 \a a and \a b are equal.
2433 */
2434
2435/*!
2436 \fn bool QRhiShaderStage::operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2437
2438 \return \c false if the values in the two QRhiShaderStage
2439 objects \a a and \a b are equal; otherwise returns \c true.
2440*/
2441
2442/*!
2443 \fn size_t QRhiShaderStage::qHash(const QRhiShaderStage &key, size_t seed)
2444 \qhash{QRhiShaderStage}
2445 */
2446
2447#ifndef QT_NO_DEBUG_STREAM
2448QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
2449{
2450 QDebugStateSaver saver(dbg);
2451 dbg.nospace() << "QRhiShaderStage(type=" << s.type()
2452 << " shader=" << s.shader()
2453 << " variant=" << s.shaderVariant()
2454 << ')';
2455 return dbg;
2456}
2457#endif
2458
2459/*!
2460 \class QRhiColorAttachment
2461 \inmodule QtGuiPrivate
2462 \inheaderfile rhi/qrhi.h
2463 \since 6.6
2464 \brief Describes the a single color attachment of a render target.
2465
2466 A color attachment is either a QRhiTexture or a QRhiRenderBuffer. The
2467 former, i.e. when texture() is set, is used in most cases.
2468 QRhiColorAttachment is commonly used in combination with
2469 QRhiTextureRenderTargetDescription.
2470
2471 \note texture() and renderBuffer() cannot be both set (be non-null at the
2472 same time).
2473
2474 Setting renderBuffer instead is recommended only when multisampling is
2475 needed. Relying on QRhi::MultisampleRenderBuffer is a better choice than
2476 QRhi::MultisampleTexture in practice since the former is available in more
2477 run time configurations (e.g. when running on OpenGL ES 3.0 which has no
2478 support for multisample textures, but does support multisample
2479 renderbuffers).
2480
2481 When targeting a non-multisample texture, the layer() and level() indicate
2482 the targeted layer (face index \c{0-5} for cubemaps) and mip level. For 3D
2483 textures layer() specifies the slice (one 2D image within the 3D texture)
2484 to render to. For texture arrays layer() is the array index.
2485
2486 When texture() or renderBuffer() is multisample, resolveTexture() can be
2487 set optionally. When set, samples are resolved automatically into that
2488 (non-multisample) texture at the end of the render pass. When rendering
2489 into a multisample renderbuffers, this is the only way to get resolved,
2490 non-multisample content out of them. Multisample textures allow sampling in
2491 shaders so for them this is just one option.
2492
2493 \note when resolving is enabled, the multisample data may not be written
2494 out at all. This means that the multisample texture() must not be used
2495 afterwards with shaders for sampling when resolveTexture() is set.
2496
2497 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2498 for details.
2499
2500 \sa QRhiTextureRenderTargetDescription
2501 */
2502
2503/*!
2504 \fn QRhiColorAttachment::QRhiColorAttachment() = default
2505
2506 Constructs an empty color attachment description.
2507 */
2508
2509/*!
2510 Constructs a color attachment description that specifies \a texture as the
2511 associated color buffer.
2512 */
2513QRhiColorAttachment::QRhiColorAttachment(QRhiTexture *texture)
2514 : m_texture(texture)
2515{
2516}
2517
2518/*!
2519 Constructs a color attachment description that specifies \a renderBuffer as
2520 the associated color buffer.
2521 */
2522QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
2523 : m_renderBuffer(renderBuffer)
2524{
2525}
2526
2527/*!
2528 \fn QRhiTexture *QRhiColorAttachment::texture() const
2529
2530 \return the texture this attachment description references, or \nullptr if
2531 there is none.
2532 */
2533
2534/*!
2535 \fn void QRhiColorAttachment::setTexture(QRhiTexture *tex)
2536
2537 Sets the texture \a tex.
2538
2539 \note texture() and renderBuffer() cannot be both set (be non-null at the
2540 same time).
2541 */
2542
2543/*!
2544 \fn QRhiRenderBuffer *QRhiColorAttachment::renderBuffer() const
2545
2546 \return the renderbuffer this attachment description references, or
2547 \nullptr if there is none.
2548
2549 In practice associating a QRhiRenderBuffer with a QRhiColorAttachment makes
2550 the most sense when setting up multisample rendering via a multisample
2551 \l{QRhiRenderBuffer::Type}{color} renderbuffer that is then resolved into a
2552 non-multisample texture at the end of the render pass.
2553 */
2554
2555/*!
2556 \fn void QRhiColorAttachment::setRenderBuffer(QRhiRenderBuffer *rb)
2557
2558 Sets the renderbuffer \a rb.
2559
2560 \note texture() and renderBuffer() cannot be both set (be non-null at the
2561 same time).
2562 */
2563
2564/*!
2565 \fn int QRhiColorAttachment::layer() const
2566 \return the layer index (cubemap face or array layer). 0 by default.
2567 */
2568
2569/*!
2570 \fn void QRhiColorAttachment::setLayer(int layer)
2571 Sets the \a layer index.
2572 */
2573
2574/*!
2575 \fn int QRhiColorAttachment::level() const
2576 \return the mip level. 0 by default.
2577 */
2578
2579/*!
2580 \fn void QRhiColorAttachment::setLevel(int level)
2581 Sets the mip \a level.
2582 */
2583
2584/*!
2585 \fn QRhiTexture *QRhiColorAttachment::resolveTexture() const
2586
2587 \return the resolve texture this attachment description references, or
2588 \nullptr if there is none.
2589
2590 Setting a non-null resolve texture is applicable when the attachment
2591 references a multisample texture or renderbuffer. The QRhiTexture in the
2592 resolveTexture() is then a non-multisample 2D texture (or texture array)
2593 with the same size (but a sample count of 1). The multisample content is
2594 automatically resolved into this texture at the end of each render pass.
2595 */
2596
2597/*!
2598 \fn void QRhiColorAttachment::setResolveTexture(QRhiTexture *tex)
2599
2600 Sets the resolve texture \a tex.
2601
2602 \a tex is expected to be a 2D texture or a 2D texture array. In either
2603 case, resolving targets a single mip level of a single layer (array
2604 element) of \a tex. The mip level and array layer are specified by
2605 resolveLevel() and resolveLayer().
2606
2607 An exception is \l{setMultiViewCount()}{multiview}: when the color
2608 attachment is associated with a texture array and multiview is enabled, the
2609 resolve texture must also be a texture array with sufficient elements for
2610 all views. In this case all elements that correspond to views are resolved
2611 automatically; the behavior is similar to the following pseudo-code:
2612 \badcode
2613 for (i = 0; i < multiViewCount(); ++i)
2614 resolve texture's layer() + i into resolveTexture's resolveLayer() + i
2615 \endcode
2616
2617 Setting a non-multisample texture to resolve a multisample texture or
2618 renderbuffer automatically at the end of the render pass is often
2619 preferable to working with multisample textures (and not setting a resolve
2620 texture), because it avoids the need for writing dedicated fragment shaders
2621 that work exclusively with multisample textures (\c sampler2DMS, \c
2622 texelFetch, etc.), and rather allows using the same shader as one would if
2623 the attachment's texture was not multisampled to begin with. This comes at
2624 the expense of an additional resource (the non-multisample \a tex).
2625 */
2626
2627/*!
2628 \fn int QRhiColorAttachment::resolveLayer() const
2629 \return the currently set resolve texture layer. Defaults to 0.
2630 */
2631
2632/*!
2633 \fn void QRhiColorAttachment::setResolveLayer(int layer)
2634 Sets the resolve texture \a layer to use.
2635 */
2636
2637/*!
2638 \fn int QRhiColorAttachment::resolveLevel() const
2639 \return the currently set resolve texture mip level. Defaults to 0.
2640 */
2641
2642/*!
2643 \fn void QRhiColorAttachment::setResolveLevel(int level)
2644 Sets the resolve texture mip \a level to use.
2645 */
2646
2647/*!
2648 \fn int QRhiColorAttachment::multiViewCount() const
2649
2650 \return the currently set number of views. Defaults to 0 which indicates
2651 the render target with this color attachment is not going to be used with
2652 multiview rendering.
2653
2654 \since 6.7
2655 */
2656
2657/*!
2658 \fn void QRhiColorAttachment::setMultiViewCount(int count)
2659
2660 Sets the view \a count. Setting a value larger than 1 indicates that the
2661 render target with this color attachment is going to be used with multiview
2662 rendering. The default value is 0. Values smaller than 2 indicate no
2663 multiview rendering.
2664
2665 When \a count is set to \c 2 or greater, the color attachment must be
2666 associated with a 2D texture array. layer() and multiViewCount() together
2667 define the range of texture array elements that are targeted during
2668 multiview rendering.
2669
2670 For example, if \c layer is \c 0 and \c multiViewCount is \c 2, the texture
2671 array must have 2 (or more) elements, and the multiview rendering will
2672 target elements 0 and 1. The \c{gl_ViewIndex} variable in the shaders has a
2673 value of \c 0 or \c 1 then, where view \c 0 corresponds to the texture array
2674 element \c 0, and view \c 1 to the array element \c 1.
2675
2676 \note Setting a \a count larger than 1, using a texture array as texture(),
2677 and calling \l{QRhiCommandBuffer::beginPass()}{beginPass()} on a
2678 QRhiTextureRenderTarget with this color attachment implies multiview
2679 rendering for the entire render pass. multiViewCount() should not be set
2680 unless multiview rendering is wanted. Multiview cannot be used with texture
2681 types other than 2D texture arrays. (although 3D textures may work,
2682 depending on the graphics API and backend; applications are nonetheless
2683 advised not to rely on that and only use 2D texture arrays as the render
2684 targets of multiview rendering)
2685
2686 See
2687 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2688 for more details regarding multiview rendering. Do note that Qt requires
2689 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview2.txt}{GL_OVR_multiview2}
2690 as well, when running on OpenGL (ES).
2691
2692 Multiview rendering is available only when the
2693 \l{QRhi::MultiView}{MultiView} feature is reported as supported from
2694 \l{QRhi::isFeatureSupported()}{isFeatureSupported()}.
2695
2696 \note For portability, be aware of limitations that exist for multiview
2697 rendering with some of the graphics APIs. It is recommended that multiview
2698 render passes do not rely on any of the features that
2699 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2700 declares as unsupported. The one exception is shader stage outputs other
2701 than \c{gl_Position} depending on \c{gl_ViewIndex}: that can be relied on
2702 (even with OpenGL) because QRhi never reports multiview as supported without
2703 \c{GL_OVR_multiview2} also being present.
2704
2705 \note Multiview rendering is not supported in combination with tessellation
2706 or geometry shaders, even though some implementations of some graphics APIs
2707 may allow this.
2708
2709 \since 6.7
2710 */
2711
2712/*!
2713 \class QRhiTextureRenderTargetDescription
2714 \inmodule QtGuiPrivate
2715 \inheaderfile rhi/qrhi.h
2716 \since 6.6
2717 \brief Describes the color and depth or depth/stencil attachments of a render target.
2718
2719 A texture render target has zero or more textures as color attachments,
2720 zero or one renderbuffer as combined depth/stencil buffer or zero or one
2721 texture as depth buffer.
2722
2723 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2724 non-null at the same time).
2725
2726 Let's look at some example usages in combination with
2727 QRhiTextureRenderTarget.
2728
2729 Due to the constructors, the targeting a texture (and no depth/stencil
2730 buffer) is simple:
2731
2732 \code
2733 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256), 1, QRhiTexture::RenderTarget);
2734 texture->create();
2735 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture }));
2736 \endcode
2737
2738 The following creates a texture render target that is set up to target mip
2739 level #2 of a texture:
2740
2741 \code
2742 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget | QRhiTexture::MipMapped);
2743 texture->create();
2744 QRhiColorAttachment colorAtt(texture);
2745 colorAtt.setLevel(2);
2746 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt });
2747 \endcode
2748
2749 Another example, this time to render into a depth texture:
2750
2751 \code
2752 QRhiTexture *shadowMap = rhi->newTexture(QRhiTexture::D32F, QSize(1024, 1024), 1, QRhiTexture::RenderTarget);
2753 shadowMap->create();
2754 QRhiTextureRenderTargetDescription rtDesc;
2755 rtDesc.setDepthTexture(shadowMap);
2756 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2757 \endcode
2758
2759 A very common case, having a texture as the color attachment and a
2760 renderbuffer as depth/stencil to enable depth testing:
2761
2762 \code
2763 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2764 texture->create();
2765 QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512));
2766 depthStencil->create();
2767 QRhiTextureRenderTargetDescription rtDesc({ texture }, depthStencil);
2768 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2769 \endcode
2770
2771 Finally, to enable multisample rendering in a portable manner (so also
2772 supporting OpenGL ES 3.0), using a QRhiRenderBuffer as the (multisample)
2773 color buffer and then resolving into a regular (non-multisample) 2D
2774 texture. To enable depth testing, a depth-stencil buffer, which also must
2775 use the same sample count, is used as well:
2776
2777 \code
2778 QRhiRenderBuffer *colorBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4); // 4x MSAA
2779 colorBuffer->create();
2780 QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512), 4);
2781 depthStencil->create();
2782 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2783 texture->create();
2784 QRhiColorAttachment colorAtt(colorBuffer);
2785 colorAtt.setResolveTexture(texture);
2786 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt, depthStencil });
2787 \endcode
2788
2789 \note when multisample resolving is enabled, the multisample data may not be
2790 written out at all. This means that the multisample texture in a color
2791 attachment must not be used afterwards with shaders for sampling (or other
2792 purposes) whenever a resolve texture is set, since the multisample color
2793 buffer is merely an intermediate storage then that gets no data written back
2794 on some GPU architectures at all. See
2795 \l{QRhiTextureRenderTarget::Flag}{PreserveColorContents} for more details.
2796
2797 \note When using setDepthTexture(), not setDepthStencilBuffer(), and the
2798 depth (stencil) data is not of interest afterwards, set the
2799 DoNotStoreDepthStencilContents flag on the QRhiTextureRenderTarget. This
2800 allows indicating to the underlying 3D API that the depth/stencil data can
2801 be discarded, leading potentially to better performance with tiled GPU
2802 architectures. When the depth-stencil buffer is a QRhiRenderBuffer (and also
2803 for the multisample color texture, see previous note) this is implicit, but
2804 with a depth (stencil) QRhiTexture the intention needs to be declared
2805 explicitly. By default QRhi assumes that the data is of interest (e.g., the
2806 depth texture is sampled in a shader afterwards).
2807
2808 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2809 for details.
2810
2811 \sa QRhiColorAttachment, QRhiTextureRenderTarget
2812 */
2813
2814/*!
2815 \fn QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription() = default
2816
2817 Constructs an empty texture render target description.
2818 */
2819
2820/*!
2821 Constructs a texture render target description with one attachment
2822 described by \a colorAttachment.
2823 */
2824QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment)
2825{
2826 m_colorAttachments.append(colorAttachment);
2827}
2828
2829/*!
2830 Constructs a texture render target description with two attachments, a
2831 color attachment described by \a colorAttachment, and a depth/stencil
2832 attachment with \a depthStencilBuffer.
2833 */
2834QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2835 QRhiRenderBuffer *depthStencilBuffer)
2836 : m_depthStencilBuffer(depthStencilBuffer)
2837{
2838 m_colorAttachments.append(colorAttachment);
2839}
2840
2841/*!
2842 Constructs a texture render target description with two attachments, a
2843 color attachment described by \a colorAttachment, and a depth attachment
2844 with \a depthTexture.
2845
2846 \note \a depthTexture must have a suitable format, such as QRhiTexture::D16
2847 or QRhiTexture::D32F.
2848 */
2849QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2850 QRhiTexture *depthTexture)
2851 : m_depthTexture(depthTexture)
2852{
2853 m_colorAttachments.append(colorAttachment);
2854}
2855
2856/*!
2857 \fn void QRhiTextureRenderTargetDescription::setColorAttachments(std::initializer_list<QRhiColorAttachment> list)
2858 Sets the \a list of color attachments.
2859 */
2860
2861/*!
2862 \fn template<typename InputIterator> void QRhiTextureRenderTargetDescription::setColorAttachments(InputIterator first, InputIterator last)
2863 Sets the list of color attachments via the iterators \a first and \a last.
2864 */
2865
2866/*!
2867 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cbeginColorAttachments() const
2868 \return a const iterator pointing to the first item in the attachment list.
2869 */
2870
2871/*!
2872 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cendColorAttachments() const
2873 \return a const iterator pointing just after the last item in the attachment list.
2874 */
2875
2876/*!
2877 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::colorAttachmentAt(qsizetype index) const
2878 \return the color attachment at the specified \a index.
2879 */
2880
2881/*!
2882 \fn qsizetype QRhiTextureRenderTargetDescription::colorAttachmentCount() const
2883 \return the number of currently set color attachments.
2884 */
2885
2886/*!
2887 \fn QRhiRenderBuffer *QRhiTextureRenderTargetDescription::depthStencilBuffer() const
2888 \return the renderbuffer used as depth-stencil buffer, or \nullptr if none was set.
2889 */
2890
2891/*!
2892 \fn void QRhiTextureRenderTargetDescription::setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer)
2893
2894 Sets the \a renderBuffer for depth-stencil. Not mandatory, e.g. when no
2895 depth test/write or stencil-related features are used within any graphics
2896 pipelines in any of the render passes for this render target, it can be
2897 left set to \nullptr.
2898
2899 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2900 non-null at the same time).
2901
2902 Using a QRhiRenderBuffer over a 2D QRhiTexture as the depth or
2903 depth/stencil buffer is very common, and is the recommended approach for
2904 applications. Using a QRhiTexture, and so setDepthTexture() becomes
2905 relevant if the depth data is meant to be accessed (e.g. sampled in a
2906 shader) afterwards, or when
2907 \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering} is
2908 involved (because then the depth texture must be a texture array).
2909
2910 \sa setDepthTexture()
2911 */
2912
2913/*!
2914 \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthTexture() const
2915 \return the currently referenced depth texture, or \nullptr if none was set.
2916 */
2917
2918/*!
2919 \fn void QRhiTextureRenderTargetDescription::setDepthTexture(QRhiTexture *texture)
2920
2921 Sets the \a texture for depth-stencil. This is an alternative to
2922 setDepthStencilBuffer(), where instead of a QRhiRenderBuffer a QRhiTexture
2923 with a suitable type (e.g., QRhiTexture::D32F) is provided.
2924
2925 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2926 non-null at the same time).
2927
2928 \a texture can either be a 2D texture or a 2D texture array (when texture
2929 arrays are supported). Specifying a texture array is relevant in particular
2930 with
2931 \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering}.
2932
2933 \note If \a texture is a format with a stencil component, such as
2934 \l QRhiTexture::D24S8, it will serve as the stencil buffer as well.
2935
2936 \sa setDepthStencilBuffer()
2937 */
2938
2939/*!
2940 \fn int QRhiTextureRenderTargetDescription::depthLayer() const
2941 \return the array slice index to be used for the depth/stencil attachment,
2942 or -1 by default.
2943
2944 \since 6.12
2945 \sa setDepthLayer(), setDepthTexture()
2946 */
2947
2948/*!
2949 \fn void QRhiTextureRenderTargetDescription::setDepthLayer(int depthLayer)
2950
2951 Sets the array slice index to be used for the depth/stencil attachment.
2952
2953 Pass -1 (the default) to not target a particular layer. When set to a
2954 non-negative value, the render target attaches a view that targets exactly
2955 that layer (slice) of the depth texture. This is only effective when a 2D
2956 array depth texture is provided via setDepthTexture(); otherwise the value
2957 is ignored.
2958
2959 The value must be within the array size of the depth texture; passing an
2960 out-of-range index leads to undefined behavior. The index is absolute
2961 with respect to the underlying texture, regardless of any array range
2962 that may have been specified when creating the texture.
2963
2964 Specifying a \a depthLayer disables layered/multiview rendering for the
2965 depth attachment.
2966
2967 \since 6.12
2968 \sa depthLayer(), setDepthTexture()
2969 */
2970
2971/*!
2972 \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthResolveTexture() const
2973
2974 \return the texture to which a multisample depth (or depth-stencil) texture
2975 (or texture array) is resolved to. \nullptr if there is none, which is the
2976 most common case.
2977
2978 \since 6.8
2979 \sa QRhiColorAttachment::resolveTexture(), depthTexture()
2980 */
2981
2982/*!
2983 \fn void QRhiTextureRenderTargetDescription::setDepthResolveTexture(QRhiTexture *tex)
2984
2985 Sets the depth (or depth-stencil) resolve texture \a tex.
2986
2987 \a tex is expected to be a 2D texture or a 2D texture array with a format
2988 matching the texture set via setDepthTexture().
2989
2990 \note Resolving depth (or depth-stencil) data is only functional when the
2991 \l QRhi::ResolveDepthStencil feature is reported as supported at run time.
2992 Support for depth-stencil resolve is not universally available among the
2993 graphics APIs. Designs assuming unconditional availability of depth-stencil
2994 resolve are therefore non-portable, and should be avoided.
2995
2996 \note As an additional limitation for OpenGL ES in particular, setting a
2997 depth resolve texture may only be functional in combination with
2998 setDepthTexture(), not with setDepthStencilBuffer().
2999
3000 \since 6.8
3001 \sa QRhiColorAttachment::setResolveTexture(), setDepthTexture()
3002 */
3003
3004/*!
3005 \fn QRhiShadingRateMap *QRhiTextureRenderTargetDescription::shadingRateMap() const
3006 \return the currently set QRhiShadingRateMap. By default this is \nullptr.
3007 \since 6.9
3008 */
3009
3010/*!
3011 \fn void QRhiTextureRenderTargetDescription::setShadingRateMap(QRhiShadingRateMap *map)
3012
3013 Associates with the specified QRhiShadingRateMap \a map. This is functional
3014 only when the \l QRhi::VariableRateShadingMap feature is reported as
3015 supported.
3016
3017 When QRhiCommandBuffer::setShadingRate() is also called, the higher of the
3018 two shading rates is used for each tile. There is currently no control
3019 offered over the combiner behavior.
3020
3021 \note When the render target had already been built (create() was called
3022 successfully), setting a shading rate map implies that a different, new
3023 QRhiRenderPassDescriptor is needed and thus a rebuild is needed. Call
3024 setRenderPassDescriptor() again (outside of a render pass) and then rebuild
3025 by calling create(). This has other rolling consequences as well, for
3026 example for graphics pipelines: those also need to be associated with the
3027 new QRhiRenderPassDescriptor and then rebuilt. See \l
3028 QRhiRenderPassDescriptor::serializedFormat() for some suggestions on how to
3029 deal with this. Remember to set the QRhiGraphicsPipeline::UsesShadingRate
3030 flag as well.
3031
3032 \since 6.9
3033 */
3034
3035/*!
3036 \class QRhiTextureSubresourceUploadDescription
3037 \inmodule QtGuiPrivate
3038 \inheaderfile rhi/qrhi.h
3039 \since 6.6
3040 \brief Describes the source for one mip level in a layer in a texture upload operation.
3041
3042 The source content is specified either as a QImage or as a raw blob. The
3043 former is only allowed for uncompressed textures with a format that can be
3044 mapped to QImage, while the latter is supported for all formats, including
3045 floating point and compressed.
3046
3047 \note image() and data() cannot be both set at the same time.
3048
3049 destinationTopLeft() specifies the top-left corner of the target
3050 rectangle. Defaults to (0, 0).
3051
3052 An empty sourceSize() (the default) indicates that size is assumed to be
3053 the size of the subresource. With QImage-based uploads this implies that
3054 the size of the source image() must match the subresource. When providing
3055 raw data instead, sufficient number of bytes must be provided in data().
3056
3057 sourceTopLeft() is supported only for QImage-based uploads, and specifies
3058 the top-left corner of the source rectangle.
3059
3060 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3061 internally, depending on the format and the backend.
3062
3063 When providing raw data, and the stride is not specified via
3064 setDataStride(), the stride (row pitch, row length in bytes) of the
3065 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
3066 the number of bytes used for one pixel, and there must be no additional
3067 padding between rows. There is no row start alignment requirement.
3068
3069 When there is unused data at the end of each row in the input raw data,
3070 call setDataStride() with the total number of bytes per row. The stride
3071 must always be a multiple of the number of bytes for one pixel. The row
3072 stride is only applicable to image data for textures with an uncompressed
3073 format.
3074
3075 \note The format of the source data must be compatible with the texture
3076 format. With many graphics APIs the data is copied as-is into a staging
3077 buffer, there is no intermediate format conversion provided by QRhi. This
3078 applies to floating point formats as well, with, for example, RGBA16F
3079 requiring half floats in the source data.
3080
3081 \note Setting the stride via setDataStride() is only functional when
3082 QRhi::ImageDataStride is reported as
3083 \l{QRhi::isFeatureSupported()}{supported}. In practice this can be expected
3084 to be supported everywhere except for OpenGL ES 2.0.
3085
3086 \note When a QImage is given, the stride returned from
3087 QImage::bytesPerLine() is taken into account automatically.
3088
3089 \warning When a QImage is given and the QImage does not own the underlying
3090 pixel data, it is up to the caller to ensure that the associated data stays
3091 valid until the end of the frame. (just submitting the resource update batch
3092 is not sufficient, the data must stay valid until QRhi::endFrame() is called
3093 in order to be portable across all backends) If this cannot be ensured, the
3094 caller is strongly encouraged to call QImage::detach() on the image before
3095 passing it to uploadTexture().
3096
3097 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3098 for details.
3099
3100 \sa QRhiTextureUploadDescription
3101 */
3102
3103/*!
3104 \fn QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription() = default
3105
3106 Constructs an empty subresource description.
3107
3108 \note an empty QRhiTextureSubresourceUploadDescription is not useful on its
3109 own and should not be submitted to a QRhiTextureUploadEntry. At minimum
3110 image or data must be set first.
3111 */
3112
3113/*!
3114 Constructs a mip level description with a \a image.
3115
3116 The \l{QImage::size()}{size} of \a image must match the size of the mip
3117 level. For level 0 that is the \l{QRhiTexture::pixelSize()}{texture size}.
3118
3119 The bit depth of \a image must be compatible with the
3120 \l{QRhiTexture::Format}{texture format}.
3121
3122 To describe a partial upload, call setSourceSize(), setSourceTopLeft(), or
3123 setDestinationTopLeft() afterwards.
3124 */
3125QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QImage &image)
3126 : m_image(image)
3127{
3128}
3129
3130/*!
3131 Constructs a mip level description with the image data is specified by \a
3132 data and \a size. This is suitable for floating point and compressed
3133 formats as well.
3134
3135 \a data can safely be destroyed or changed once this function returns.
3136 */
3137QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const void *data, quint32 size)
3138 : m_data(reinterpret_cast<const char *>(data), size)
3139{
3140}
3141
3142/*!
3143 Constructs a mip level description with the image data specified by \a
3144 data. This is suitable for floating point and compressed formats as well.
3145 */
3146QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QByteArray &data)
3147 : m_data(data)
3148{
3149}
3150
3151/*!
3152 \fn QImage QRhiTextureSubresourceUploadDescription::image() const
3153 \return the currently set QImage.
3154 */
3155
3156/*!
3157 \fn void QRhiTextureSubresourceUploadDescription::setImage(const QImage &image)
3158
3159 Sets \a image.
3160 Upon textures loading, the image data will be read as is, with no formats conversions.
3161
3162 \note image() and data() cannot be both set at the same time.
3163 */
3164
3165/*!
3166 \fn QByteArray QRhiTextureSubresourceUploadDescription::data() const
3167 \return the currently set raw pixel data.
3168 */
3169
3170/*!
3171 \fn void QRhiTextureSubresourceUploadDescription::setData(const QByteArray &data)
3172
3173 Sets \a data.
3174
3175 \note image() and data() cannot be both set at the same time.
3176 */
3177
3178/*!
3179 \fn quint32 QRhiTextureSubresourceUploadDescription::dataStride() const
3180 \return the currently set data stride.
3181 */
3182
3183/*!
3184 \fn void QRhiTextureSubresourceUploadDescription::setDataStride(quint32 stride)
3185
3186 Sets the data \a stride in bytes. By default this is 0 and not always
3187 relevant. When providing raw data(), and the stride is not specified via
3188 setDataStride(), the stride (row pitch, row length in bytes) of the
3189 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
3190 the number of bytes used for one pixel, and there must be no additional
3191 padding between rows. Otherwise, if there is additional space between the
3192 lines, set a non-zero \a stride. All this is applicable only when raw image
3193 data is provided, and is not necessary when working QImage since that has
3194 its own \l{QImage::bytesPerLine()}{stride} value.
3195
3196 \note When a non-zero \a stride is set, make sure the data contains the
3197 trailing padding for the last row as well, i.e. at least \c{stride * height}
3198 bytes in total. While providing the data without the last row's padding
3199 (i.e., interpreting stride as not applicable to the last row) could be safe,
3200 and is in fact safe with Vulkan, OpenGL, and D3D12, this cannot be
3201 guaranteed for all backends, so the safe approach is to avoid this and treat
3202 the last line like all others.
3203
3204 \note Setting the stride via setDataStride() is only functional when
3205 QRhi::ImageDataStride is reported as
3206 \l{QRhi::isFeatureSupported()}{supported}.
3207
3208 \note When a QImage is given, the stride returned from
3209 QImage::bytesPerLine() is taken into account automatically and therefore
3210 there is no need to set the data stride manually.
3211 */
3212
3213/*!
3214 \fn QPoint QRhiTextureSubresourceUploadDescription::destinationTopLeft() const
3215 \return the currently set destination top-left position. Defaults to (0, 0).
3216 */
3217
3218/*!
3219 \fn void QRhiTextureSubresourceUploadDescription::setDestinationTopLeft(const QPoint &p)
3220 Sets the destination top-left position \a p.
3221
3222 \note In the most common case of sourcing the image data from a QImage, Qt
3223 performs clamping of invalid texture upload sizes when the destination
3224 position + the source size exceeds the size of the targeted texture
3225 subresource (i.e, the size at the given mip level). There is also a
3226 qWarning() message printed on the debug output in this case. This is done in
3227 order to avoid confusion when the underlying 3D APIs crash and lead to GPU
3228 device removals at a later point when submitting the commands. Regardless,
3229 developers are encouraged to always validate applications by running with the
3230 Vulkan, D3D12, or Metal validation/debug layers enabled, since those offer a
3231 much wider range of checks on API usage.
3232 */
3233
3234/*!
3235 \fn QSize QRhiTextureSubresourceUploadDescription::sourceSize() const
3236
3237 \return the source size in pixels. Defaults to a default-constructed QSize,
3238 which indicates the entire subresource.
3239 */
3240
3241/*!
3242 \fn void QRhiTextureSubresourceUploadDescription::setSourceSize(const QSize &size)
3243
3244 Sets the source \a size in pixels.
3245
3246 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3247 internally, depending on the format and the backend.
3248 */
3249
3250/*!
3251 \fn QPoint QRhiTextureSubresourceUploadDescription::sourceTopLeft() const
3252 \return the currently set source top-left position. Defaults to (0, 0).
3253 */
3254
3255/*!
3256 \fn void QRhiTextureSubresourceUploadDescription::setSourceTopLeft(const QPoint &p)
3257
3258 Sets the source top-left position \a p.
3259
3260 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3261 internally, depending on the format and the backend.
3262 */
3263
3264/*!
3265 \class QRhiTextureUploadEntry
3266 \inmodule QtGuiPrivate
3267 \inheaderfile rhi/qrhi.h
3268 \since 6.6
3269
3270 \brief Describes one layer (face for cubemaps, slice for 3D textures,
3271 element for texture arrays) in a texture upload operation.
3272
3273 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3274 for details.
3275 */
3276
3277/*!
3278 \fn QRhiTextureUploadEntry::QRhiTextureUploadEntry()
3279
3280 Constructs an empty QRhiTextureUploadEntry targeting layer 0 and level 0.
3281
3282 \note an empty QRhiTextureUploadEntry should not be submitted without
3283 setting a QRhiTextureSubresourceUploadDescription via setDescription()
3284 first.
3285 */
3286
3287/*!
3288 Constructs a QRhiTextureUploadEntry targeting the given \a layer and mip
3289 \a level, with the subresource contents described by \a desc.
3290 */
3291QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
3292 const QRhiTextureSubresourceUploadDescription &desc)
3293 : m_layer(layer),
3294 m_level(level),
3295 m_desc(desc)
3296{
3297}
3298
3299/*!
3300 \fn int QRhiTextureUploadEntry::layer() const
3301 \return the currently set layer index (cubemap face, array layer). Defaults to 0.
3302 */
3303
3304/*!
3305 \fn void QRhiTextureUploadEntry::setLayer(int layer)
3306 Sets the \a layer.
3307 */
3308
3309/*!
3310 \fn int QRhiTextureUploadEntry::level() const
3311 \return the currently set mip level. Defaults to 0.
3312 */
3313
3314/*!
3315 \fn void QRhiTextureUploadEntry::setLevel(int level)
3316 Sets the mip \a level.
3317 */
3318
3319/*!
3320 \fn QRhiTextureSubresourceUploadDescription QRhiTextureUploadEntry::description() const
3321 \return the currently set subresource description.
3322 */
3323
3324/*!
3325 \fn void QRhiTextureUploadEntry::setDescription(const QRhiTextureSubresourceUploadDescription &desc)
3326 Sets the subresource description \a desc.
3327 */
3328
3329/*!
3330 \class QRhiTextureUploadDescription
3331 \inmodule QtGuiPrivate
3332 \inheaderfile rhi/qrhi.h
3333 \since 6.6
3334 \brief Describes a texture upload operation.
3335
3336 Used with QRhiResourceUpdateBatch::uploadTexture(). That function has two
3337 variants: one taking a QImage and one taking a
3338 QRhiTextureUploadDescription. The former is a convenience version,
3339 internally creating a QRhiTextureUploadDescription with a single image
3340 targeting level 0 for layer 0.
3341
3342 An example of the common, simple case of wanting to upload the contents
3343 of a QImage to a QRhiTexture with a matching pixel size:
3344
3345 \code
3346 QImage image(256, 256, QImage::Format_RGBA8888);
3347 image.fill(Qt::green); // or could use a QPainter targeting image
3348 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256));
3349 texture->create();
3350 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
3351 u->uploadTexture(texture, image);
3352 \endcode
3353
3354 When cubemaps, pre-generated mip images, compressed textures, or partial
3355 uploads are involved, applications will have to use this class instead.
3356
3357 QRhiTextureUploadDescription also enables specifying batched uploads, which
3358 are useful for example when generating an atlas or glyph cache texture:
3359 multiple, partial uploads for the same subresource (meaning the same layer
3360 and level) are supported, and can be, depending on the backend and the
3361 underlying graphics API, more efficient when batched into the same
3362 QRhiTextureUploadDescription as opposed to issuing individual
3363 \l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} commands for
3364 each of them.
3365
3366 \note Cubemaps have one layer for each of the six faces in the order +X,
3367 -X, +Y, -Y, +Z, -Z.
3368
3369 For example, specifying the faces of a cubemap could look like the following:
3370
3371 \code
3372 QImage faces[6];
3373 // ...
3374 QVarLengthArray<QRhiTextureUploadEntry, 6> entries;
3375 for (int i = 0; i < 6; ++i)
3376 entries.append(QRhiTextureUploadEntry(i, 0, faces[i]));
3377 QRhiTextureUploadDescription desc;
3378 desc.setEntries(entries.cbegin(), entries.cend());
3379 resourceUpdates->uploadTexture(texture, desc);
3380 \endcode
3381
3382 Another example that specifies mip images for a compressed texture:
3383
3384 \code
3385 QList<QRhiTextureUploadEntry> entries;
3386 const int mipCount = rhi->mipLevelsForSize(compressedTexture->pixelSize());
3387 for (int level = 0; level < mipCount; ++level) {
3388 const QByteArray compressedDataForLevel = ..
3389 entries.append(QRhiTextureUploadEntry(0, level, compressedDataForLevel));
3390 }
3391 QRhiTextureUploadDescription desc;
3392 desc.setEntries(entries.cbegin(), entries.cend());
3393 resourceUpdates->uploadTexture(compressedTexture, desc);
3394 \endcode
3395
3396 With partial uploads targeting the same subresource, it is recommended to
3397 batch them into a single upload request, whenever possible:
3398
3399 \code
3400 QRhiTextureSubresourceUploadDescription subresDesc(image);
3401 subresDesc.setSourceSize(QSize(10, 10));
3402 subResDesc.setDestinationTopLeft(QPoint(50, 40));
3403 QRhiTextureUploadEntry entry(0, 0, subresDesc); // layer 0, level 0
3404
3405 QRhiTextureSubresourceUploadDescription subresDesc2(image);
3406 subresDesc2.setSourceSize(QSize(30, 40));
3407 subResDesc2.setDestinationTopLeft(QPoint(100, 200));
3408 QRhiTextureUploadEntry entry2(0, 0, subresDesc2); // layer 0, level 0, i.e. same subresource
3409
3410 QRhiTextureUploadDescription desc({ entry, entry2});
3411 resourceUpdates->uploadTexture(texture, desc);
3412 \endcode
3413
3414 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3415 for details.
3416
3417 \sa QRhiResourceUpdateBatch
3418 */
3419
3420/*!
3421 \fn QRhiTextureUploadDescription::QRhiTextureUploadDescription()
3422
3423 Constructs an empty texture upload description.
3424 */
3425
3426/*!
3427 Constructs a texture upload description with a single subresource upload
3428 described by \a entry.
3429 */
3430QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry)
3431{
3432 m_entries.append(entry);
3433}
3434
3435/*!
3436 Constructs a texture upload description with the specified \a list of entries.
3437
3438 \note \a list can also contain multiple QRhiTextureUploadEntry elements
3439 with the same layer and level. This makes sense when those uploads are
3440 partial, meaning their subresource description has a source size or image
3441 smaller than the subresource dimensions, and can be more efficient than
3442 issuing separate uploadTexture()'s.
3443 */
3444QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list)
3445 : m_entries(list)
3446{
3447}
3448
3449/*!
3450 \fn void QRhiTextureUploadDescription::setEntries(std::initializer_list<QRhiTextureUploadEntry> list)
3451 Sets the \a list of entries.
3452 */
3453
3454/*!
3455 \fn template<typename InputIterator> void QRhiTextureUploadDescription::setEntries(InputIterator first, InputIterator last)
3456 Sets the list of entries using the iterators \a first and \a last.
3457 */
3458
3459/*!
3460 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cbeginEntries() const
3461 \return a const iterator pointing to the first item in the entry list.
3462 */
3463
3464/*!
3465 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cendEntries() const
3466 \return a const iterator pointing just after the last item in the entry list.
3467 */
3468
3469/*!
3470 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::entryAt(qsizetype index) const
3471 \return the entry at \a index.
3472 */
3473
3474/*!
3475 \fn qsizetype QRhiTextureUploadDescription::entryCount() const
3476 \return the number of entries.
3477 */
3478
3479/*!
3480 \class QRhiBufferCopyDescription
3481 \inmodule QtGuiPrivate
3482 \inheaderfile rhi/qrhi.h
3483 \since 6.13
3484 \brief Describes a buffer-to-buffer copy operation.
3485
3486 A size() of 0 indicates that the entire source buffer is to be copied. A
3487 default constructed copy description therefore leads to copying the whole
3488 of the source buffer to the beginning of the destination buffer.
3489
3490 \note The copied region must fit both the source and the destination
3491 buffer. When it does not, QRhiResourceUpdateBatch::copyBuffer() prints a
3492 warning and drops the operation.
3493
3494 \note size(), sourceOffset(), and destinationOffset() should all be
3495 multiples of 4. This is a requirement of the blit encoder in Metal, and it
3496 applies on macOS on Intel-based devices. Other platforms and 3D APIs,
3497 including Metal on Apple Silicon and on iOS, have no such restriction, but
3498 portable code has to assume the strictest of these. Note that a size() of 0
3499 implies the full size of the source buffer, which is not necessarily a
3500 multiple of 4 either.
3501
3502 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3503 for details.
3504
3505 \sa QRhiResourceUpdateBatch::copyBuffer()
3506 */
3507
3508/*!
3509 \fn QRhiBufferCopyDescription::QRhiBufferCopyDescription()
3510
3511 Constructs an empty buffer copy description.
3512 */
3513
3514/*!
3515 \fn quint32 QRhiBufferCopyDescription::size() const
3516 \return the number of bytes to copy.
3517
3518 \note A size() of 0 indicates that the entire source buffer is to be
3519 copied.
3520 */
3521
3522/*!
3523 \fn void QRhiBufferCopyDescription::setSize(quint32 sz)
3524 Sets the number of bytes to copy to \a sz.
3525 */
3526
3527/*!
3528 \fn quint32 QRhiBufferCopyDescription::sourceOffset() const
3529 \return the offset in bytes into the source buffer. Defaults to 0.
3530 */
3531
3532/*!
3533 \fn void QRhiBufferCopyDescription::setSourceOffset(quint32 offset)
3534 Sets the source \a offset in bytes.
3535 */
3536
3537/*!
3538 \fn quint32 QRhiBufferCopyDescription::destinationOffset() const
3539 \return the offset in bytes into the destination buffer. Defaults to 0.
3540 */
3541
3542/*!
3543 \fn void QRhiBufferCopyDescription::setDestinationOffset(quint32 offset)
3544 Sets the destination \a offset in bytes.
3545 */
3546
3547/*!
3548 \class QRhiTextureCopyDescription
3549 \inmodule QtGuiPrivate
3550 \inheaderfile rhi/qrhi.h
3551 \since 6.6
3552 \brief Describes a texture-to-texture copy operation.
3553
3554 An empty pixelSize() indicates that the entire subresource is to be copied.
3555 A default constructed copy description therefore leads to copying the
3556 entire subresource at level 0 of layer 0.
3557
3558 \note The source texture must be created with
3559 QRhiTexture::UsedAsTransferSource.
3560
3561 \note The source and destination rectangles defined by pixelSize(),
3562 sourceTopLeft(), and destinationTopLeft() must fit the source and
3563 destination textures, respectively. The behavior is undefined otherwise.
3564
3565 With cubemaps, 3D textures, and texture arrays one face or slice can be
3566 copied at a time. The face or slice is specified by the source and
3567 destination layer indices. With mipmapped textures one mip level can be
3568 copied at a time. The source and destination layer and mip level indices can
3569 differ, but the size and position must be carefully controlled to avoid out
3570 of bounds copies, in which case the behavior is undefined.
3571
3572 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3573 for details.
3574 */
3575
3576/*!
3577 \fn QRhiTextureCopyDescription::QRhiTextureCopyDescription()
3578
3579 Constructs an empty texture copy description.
3580 */
3581
3582/*!
3583 \fn QSize QRhiTextureCopyDescription::pixelSize() const
3584 \return the size of the region to copy.
3585
3586 \note An empty pixelSize() indicates that the entire subresource is to be
3587 copied. A default constructed copy description therefore leads to copying
3588 the entire subresource at level 0 of layer 0.
3589 */
3590
3591/*!
3592 \fn void QRhiTextureCopyDescription::setPixelSize(const QSize &sz)
3593 Sets the size of the region to copy to \a sz.
3594 */
3595
3596/*!
3597 \fn int QRhiTextureCopyDescription::sourceLayer() const
3598 \return the source array layer (cubemap face or array layer index). Defaults to 0.
3599 */
3600
3601/*!
3602 \fn void QRhiTextureCopyDescription::setSourceLayer(int layer)
3603 Sets the source array \a layer.
3604 */
3605
3606/*!
3607 \fn int QRhiTextureCopyDescription::sourceLevel() const
3608 \return the source mip level. Defaults to 0.
3609 */
3610
3611/*!
3612 \fn void QRhiTextureCopyDescription::setSourceLevel(int level)
3613 Sets the source mip \a level.
3614 */
3615
3616/*!
3617 \fn QPoint QRhiTextureCopyDescription::sourceTopLeft() const
3618 \return the source top-left position (in pixels). Defaults to (0, 0).
3619 */
3620
3621/*!
3622 \fn void QRhiTextureCopyDescription::setSourceTopLeft(const QPoint &p)
3623 Sets the source top-left position to \a p.
3624 */
3625
3626/*!
3627 \fn int QRhiTextureCopyDescription::destinationLayer() const
3628 \return the destination array layer (cubemap face or array layer index). Default to 0.
3629 */
3630
3631/*!
3632 \fn void QRhiTextureCopyDescription::setDestinationLayer(int layer)
3633 Sets the destination array \a layer.
3634 */
3635
3636/*!
3637 \fn int QRhiTextureCopyDescription::destinationLevel() const
3638 \return the destionation mip level. Defaults to 0.
3639 */
3640
3641/*!
3642 \fn void QRhiTextureCopyDescription::setDestinationLevel(int level)
3643 Sets the destination mip \a level.
3644 */
3645
3646/*!
3647 \fn QPoint QRhiTextureCopyDescription::destinationTopLeft() const
3648 \return the destionation top-left position in pixels. Defaults to (0, 0).
3649 */
3650
3651/*!
3652 \fn void QRhiTextureCopyDescription::setDestinationTopLeft(const QPoint &p)
3653 Sets the destination top-left position \a p.
3654 */
3655
3656/*!
3657 \class QRhiReadbackDescription
3658 \inmodule QtGuiPrivate
3659 \inheaderfile rhi/qrhi.h
3660 \since 6.6
3661 \brief Describes a readback (reading back texture contents from possibly GPU-only memory) operation.
3662
3663 The source of the readback operation is either a QRhiTexture or the
3664 current backbuffer of the currently targeted QRhiSwapChain. When
3665 texture() is not set, the swapchain is used. Otherwise the specified
3666 QRhiTexture is treated as the source.
3667
3668 \note Textures used in readbacks must be created with
3669 QRhiTexture::UsedAsTransferSource.
3670
3671 \note Swapchains used in readbacks must be created with
3672 QRhiSwapChain::UsedAsTransferSource.
3673
3674 layer() and level() are only applicable when the source is a QRhiTexture.
3675
3676 \note Multisample textures cannot be read back. Readbacks are supported for
3677 multisample swapchain buffers however.
3678
3679 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3680 for details.
3681 */
3682
3683/*!
3684 \fn QRhiReadbackDescription::QRhiReadbackDescription() = default
3685
3686 Constructs an empty texture readback description.
3687
3688 \note The source texture is set to null by default, which is still a valid
3689 readback: it specifies that the backbuffer of the current swapchain is to
3690 be read back. (current meaning the frame's target swapchain at the time of
3691 committing the QRhiResourceUpdateBatch with the
3692 \l{QRhiResourceUpdateBatch::readBackTexture()}{texture readback} on it)
3693 */
3694
3695/*!
3696 Constructs an texture readback description that specifies that level 0 of
3697 layer 0 of \a texture is to be read back.
3698
3699 \note \a texture can also be null in which case this constructor is
3700 identical to the argumentless variant.
3701 */
3702QRhiReadbackDescription::QRhiReadbackDescription(QRhiTexture *texture)
3703 : m_texture(texture)
3704{
3705}
3706
3707/*!
3708 \fn QRhiTexture *QRhiReadbackDescription::texture() const
3709
3710 \return the QRhiTexture that is read back. Can be left set to \nullptr
3711 which indicates that the backbuffer of the current swapchain is to be used
3712 instead.
3713 */
3714
3715/*!
3716 \fn void QRhiReadbackDescription::setTexture(QRhiTexture *tex)
3717
3718 Sets the texture \a tex as the source of the readback operation.
3719
3720 Setting \nullptr is valid too, in which case the current swapchain's
3721 current backbuffer is used. (but then the readback cannot be issued in a
3722 non-swapchain-based frame)
3723
3724 \note Multisample textures cannot be read back. Readbacks are supported for
3725 multisample swapchain buffers however.
3726
3727 \note Textures used in readbacks must be created with
3728 QRhiTexture::UsedAsTransferSource.
3729
3730 \note Swapchains used in readbacks must be created with
3731 QRhiSwapChain::UsedAsTransferSource.
3732 */
3733
3734/*!
3735 \fn int QRhiReadbackDescription::layer() const
3736
3737 \return the currently set array layer (cubemap face, array index). Defaults to 0.
3738
3739 Applicable only when the source of the readback is a QRhiTexture.
3740 */
3741
3742/*!
3743 \fn void QRhiReadbackDescription::setLayer(int layer)
3744 Sets the array \a layer to read back.
3745 */
3746
3747/*!
3748 \fn int QRhiReadbackDescription::level() const
3749
3750 \return the currently set mip level. Defaults to 0.
3751
3752 Applicable only when the source of the readback is a QRhiTexture.
3753 */
3754
3755/*!
3756 \fn void QRhiReadbackDescription::setLevel(int level)
3757 Sets the mip \a level to read back.
3758 */
3759
3760/*!
3761 \fn const QRect &QRhiReadbackDescription::rect() const
3762 \since 6.10
3763
3764 \return the rectangle to read back. Defaults to an invalid rectangle.
3765
3766 If invalid, the entire texture or swapchain backbuffer is read back.
3767 */
3768
3769/*!
3770 \fn void QRhiReadbackDescription::setRect(const QRect &rectangle)
3771 \since 6.10
3772
3773 Sets the \a rectangle to read back.
3774 */
3775
3776/*!
3777 \class QRhiReadbackResult
3778 \inmodule QtGuiPrivate
3779 \inheaderfile rhi/qrhi.h
3780 \since 6.6
3781 \brief Describes the results of a potentially asynchronous buffer or texture readback operation.
3782
3783 When \l completed is set, the function is invoked when the \l data is
3784 available. \l format and \l pixelSize are set upon completion together with
3785 \l data.
3786
3787 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3788 for details.
3789 */
3790
3791/*!
3792 \variable QRhiReadbackResult::completed
3793
3794 Callback that is invoked upon completion, on the thread the QRhi operates
3795 on. Can be left set to \nullptr, in which case no callback is invoked.
3796 */
3797
3798/*!
3799 \variable QRhiReadbackResult::format
3800
3801 Valid only for textures, the texture format.
3802 */
3803
3804/*!
3805 \variable QRhiReadbackResult::pixelSize
3806
3807 Valid only for textures, the size in pixels.
3808 */
3809
3810/*!
3811 \variable QRhiReadbackResult::data
3812
3813 The buffer or image data.
3814
3815 \sa QRhiResourceUpdateBatch::readBackTexture(), QRhiResourceUpdateBatch::readBackBuffer()
3816 */
3817
3818
3819/*!
3820 \class QRhiNativeHandles
3821 \inmodule QtGuiPrivate
3822 \inheaderfile rhi/qrhi.h
3823 \since 6.6
3824 \brief Base class for classes exposing backend-specific collections of native resource objects.
3825
3826 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3827 for details.
3828 */
3829
3830/*!
3831 \class QRhiResource
3832 \inmodule QtGuiPrivate
3833 \inheaderfile rhi/qrhi.h
3834 \since 6.6
3835 \brief Base class for classes encapsulating native resource objects.
3836
3837 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3838 for details.
3839 */
3840
3841/*!
3842 \enum QRhiResource::Type
3843 Specifies type of the resource.
3844
3845 \value Buffer
3846 \value Texture
3847 \value Sampler
3848 \value RenderBuffer
3849 \value RenderPassDescriptor
3850 \value SwapChainRenderTarget
3851 \value TextureRenderTarget
3852 \value ShaderResourceBindings
3853 \value GraphicsPipeline
3854 \value SwapChain
3855 \value ComputePipeline
3856 \value CommandBuffer
3857 \value ShadingRateMap
3858 \value [since 6.13] IndirectCommandBuffer
3859 */
3860
3861/*!
3862 \fn virtual QRhiResource::Type QRhiResource::resourceType() const = 0
3863
3864 \return the type of the resource.
3865 */
3866
3867/*!
3868 \internal
3869 */
3870QRhiResource::QRhiResource(QRhiImplementation *rhi)
3871 : m_rhi(rhi)
3872{
3873 m_id = QRhiGlobalObjectIdGenerator::newId();
3874}
3875
3876/*!
3877 Destructor.
3878
3879 Releases (or requests deferred releasing of) the underlying native graphics
3880 resources, if there are any.
3881
3882 \note Resources referenced by commands for the current frame should not be
3883 released until the frame is submitted by QRhi::endFrame().
3884
3885 \sa destroy()
3886 */
3887QRhiResource::~QRhiResource()
3888{
3889 // destroy() cannot be called here, due to virtuals; it is up to the
3890 // subclasses to do that.
3891}
3892
3893/*!
3894 \fn virtual void QRhiResource::destroy() = 0
3895
3896 Releases (or requests deferred releasing of) the underlying native graphics
3897 resources. Safe to call multiple times, subsequent invocations will be a
3898 no-op then.
3899
3900 Once destroy() is called, the QRhiResource instance can be reused, by
3901 calling \c create() again. That will then result in creating new native
3902 graphics resources underneath.
3903
3904 \note Resources referenced by commands for the current frame should not be
3905 released until the frame is submitted by QRhi::endFrame().
3906
3907 The QRhiResource destructor also performs the same task, so calling this
3908 function is not necessary before deleting a QRhiResource.
3909
3910 \sa deleteLater()
3911 */
3912
3913/*!
3914 When called without a frame being recorded, this function is equivalent to
3915 deleting the object. Between a QRhi::beginFrame() and QRhi::endFrame()
3916 however the behavior is different: the QRhiResource will not be destroyed
3917 until the frame is submitted via QRhi::endFrame(), thus satisfying the QRhi
3918 requirement of not altering QRhiResource objects that are referenced by the
3919 frame being recorded.
3920
3921 If the QRhi that created this object is already destroyed, the object is
3922 deleted immediately.
3923
3924 Using deleteLater() can be a useful convenience in many cases, and it
3925 complements the low-level guarantee (that the underlying native graphics
3926 objects are never destroyed until it is safe to do so and it is known for
3927 sure that they are not used by the GPU in an still in-flight frame), by
3928 offering a way to make sure the C++ object instances (of QRhiBuffer,
3929 QRhiTexture, etc.) themselves also stay valid until the end of the current
3930 frame.
3931
3932 The following example shows a convenient way of creating a throwaway buffer
3933 that is only used in one frame and gets automatically released in
3934 endFrame(). (when it comes to the underlying native buffer(s), the usual
3935 guarantee applies: the QRhi backend defers the releasing of those until it
3936 is guaranteed that the frame in which the buffer is accessed by the GPU has
3937 completed)
3938
3939 \code
3940 rhi->beginFrame(swapchain);
3941 QRhiBuffer *buf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, 256);
3942 buf->deleteLater(); // !
3943 u = rhi->nextResourceUpdateBatch();
3944 u->uploadStaticBuffer(buf, data);
3945 // ... draw with buf
3946 rhi->endFrame();
3947 \endcode
3948
3949 \sa destroy()
3950 */
3951void QRhiResource::deleteLater()
3952{
3953 if (m_rhi)
3954 m_rhi->addDeleteLater(this);
3955 else
3956 delete this;
3957}
3958
3959/*!
3960 \return the currently set object name. By default the name is empty.
3961 */
3962QByteArray QRhiResource::name() const
3963{
3964 return m_objectName;
3965}
3966
3967/*!
3968 Sets a \a name for the object.
3969
3970 This allows getting descriptive names for the native graphics
3971 resources visible in graphics debugging tools, such as
3972 \l{https://renderdoc.org/}{RenderDoc} and
3973 \l{https://developer.apple.com/xcode/}{XCode}.
3974
3975 When it comes to naming native objects by relaying the name via the
3976 appropriate graphics API, note that the name is ignored when
3977 QRhi::DebugMarkers are not supported, and may, depending on the backend,
3978 also be ignored when QRhi::EnableDebugMarkers is not set.
3979
3980 \note The name may be ignored for objects other than buffers,
3981 renderbuffers, and textures, depending on the backend.
3982
3983 \note The name may be modified. For slotted resources, such as a QRhiBuffer
3984 backed by multiple native buffers, QRhi will append a suffix to make the
3985 underlying native buffers easily distinguishable from each other.
3986 */
3987void QRhiResource::setName(const QByteArray &name)
3988{
3989 m_objectName = name;
3990}
3991
3992/*!
3993 \return the global, unique identifier of this QRhiResource.
3994
3995 User code rarely needs to deal with the value directly. It is used
3996 internally for tracking and bookkeeping purposes.
3997 */
3998quint64 QRhiResource::globalResourceId() const
3999{
4000 return m_id;
4001}
4002
4003/*!
4004 \return the QRhi that created this resource.
4005
4006 If the QRhi that created this object is already destroyed, the result is
4007 \nullptr.
4008 */
4009QRhi *QRhiResource::rhi() const
4010{
4011 return m_rhi ? m_rhi->q : nullptr;
4012}
4013
4014/*!
4015 \class QRhiBuffer
4016 \inmodule QtGuiPrivate
4017 \inheaderfile rhi/qrhi.h
4018 \since 6.6
4019 \brief Vertex, index, or uniform (constant) buffer resource.
4020
4021 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4022 for details.
4023
4024 A QRhiBuffer encapsulates zero, one, or more native buffer objects (such as
4025 a \c VkBuffer or \c MTLBuffer). With some graphics APIs and backends
4026 certain types of buffers may not use a native buffer object at all (e.g.
4027 OpenGL if uniform buffer objects are not used), but this is transparent to
4028 the user of the QRhiBuffer API. Similarly, the fact that some types of
4029 buffers may use two or three native buffers underneath, in order to allow
4030 efficient per-frame content update without stalling the GPU pipeline, is
4031 mostly invisible to the applications and libraries.
4032
4033 A QRhiBuffer instance is always created by calling
4034 \l{QRhi::newBuffer()}{the QRhi's newBuffer() function}. This creates no
4035 native graphics resources. To do that, call create() after setting the
4036 appropriate options, such as the type, usage flags, size, although in most cases these
4037 are already set based on the arguments passed to
4038 \l{QRhi::newBuffer()}{newBuffer()}.
4039
4040 \section1 Example usage
4041
4042 To create a uniform buffer for a shader where the GLSL uniform block
4043 contains a single \c mat4 member, and update the contents:
4044
4045 \code
4046 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64);
4047 if (!ubuf->create()) { error(); }
4048 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4049 QMatrix4x4 mvp;
4050 // ... set up the modelview-projection matrix
4051 batch->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
4052 // ...
4053 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4054 \endcode
4055
4056 An example of creating a buffer with vertex data:
4057
4058 \code
4059 const float vertices[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f };
4060 QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices));
4061 if (!vbuf->create()) { error(); }
4062 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4063 batch->uploadStaticBuffer(vbuf, vertices);
4064 // ...
4065 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4066 \endcode
4067
4068 An index buffer:
4069
4070 \code
4071 static const quint16 indices[] = { 0, 1, 2 };
4072 QRhiBuffer *ibuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices));
4073 if (!ibuf->create()) { error(); }
4074 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4075 batch->uploadStaticBuffer(ibuf, indices);
4076 // ...
4077 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4078 \endcode
4079
4080 \section1 Common patterns
4081
4082 A call to create() destroys any existing native resources if create() was
4083 successfully called before. If those native resources are still in use by
4084 an in-flight frame (i.e., there's a chance they are still read by the GPU),
4085 the destroying of those resources is deferred automatically. Thus a very
4086 common and convenient pattern to safely increase the size of an already
4087 initialized buffer is the following. In practice this drops and creates a
4088 whole new set of native resources underneath, so it is not necessarily a
4089 cheap operation, but is more convenient and still faster than the
4090 alternatives, because by not destroying the \c buf object itself, all
4091 references to it stay valid in other data structures (e.g., in any
4092 QRhiShaderResourceBinding the QRhiBuffer is referenced from).
4093
4094 \code
4095 if (buf->size() < newSize) {
4096 buf->setSize(newSize);
4097 if (!buf->create()) { error(); }
4098 }
4099 // continue using buf, fill it with new data
4100 \endcode
4101
4102 When working with uniform buffers, it will sometimes be necessary to
4103 combine data for multiple draw calls into a single buffer for efficiency
4104 reasons. Be aware of the aligment requirements: with some graphics APIs
4105 offsets for a uniform buffer must be aligned to 256 bytes. This applies
4106 both to QRhiShaderResourceBinding and to the dynamic offsets passed to
4107 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}. Use the
4108 \l{QRhi::ubufAlignment()}{ubufAlignment()} and
4109 \l{QRhi::ubufAligned()}{ubufAligned()} functions to create portable code.
4110 As an example, the following is an outline for issuing multiple (\c N) draw
4111 calls with the same pipeline and geometry, but with a different data in the
4112 uniform buffers exposed at binding point 0. This assumes the buffer is
4113 exposed via
4114 \l{QRhiShaderResourceBinding::uniformBufferWithDynamicOffset()}{uniformBufferWithDynamicOffset()}
4115 which allows passing a QRhiCommandBuffer::DynamicOffset list to
4116 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}.
4117
4118 \code
4119 const int N = 2;
4120 const int UB_SIZE = 64 + 4; // assuming a uniform block with { mat4 matrix; float opacity; }
4121 const int ONE_UBUF_SIZE = rhi->ubufAligned(UB_SIZE);
4122 const int TOTAL_UBUF_SIZE = N * ONE_UBUF_SIZE;
4123 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, TOTAL_UBUF_SIZE);
4124 if (!ubuf->create()) { error(); }
4125 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4126 for (int i = 0; i < N; ++i) {
4127 batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE, 64, matrix.constData());
4128 batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE + 64, 4, &opacity);
4129 }
4130 // ...
4131 // beginPass(), set pipeline, etc., and then:
4132 for (int i = 0; i < N; ++i) {
4133 QRhiCommandBuffer::DynamicOffset dynOfs[] = { { 0, i * ONE_UBUF_SIZE } };
4134 cb->setShaderResources(srb, 1, dynOfs);
4135 cb->draw(36);
4136 }
4137 \endcode
4138
4139 \sa QRhiResourceUpdateBatch, QRhi, QRhiCommandBuffer
4140 */
4141
4142/*!
4143 \enum QRhiBuffer::Type
4144 Specifies storage type of buffer resource.
4145
4146 \value Immutable Indicates that the data is not expected to change ever
4147 after the initial upload. Under the hood such buffer resources are
4148 typically placed in device local (GPU) memory (on systems where
4149 applicable). Uploading new data is possible, but may be expensive. The
4150 upload typically happens by copying to a separate, host visible staging
4151 buffer from which a GPU buffer-to-buffer copy is issued into the actual
4152 GPU-only buffer.
4153
4154 \value Static Indicates that the data is expected to change only
4155 infrequently. Typically placed in device local (GPU) memory, where
4156 applicable. On backends where host visible staging buffers are used for
4157 uploading, the staging buffers are kept around for this type, unlike with
4158 Immutable, so subsequent uploads do not suffer in performance. Frequent
4159 updates, especially updates in consecutive frames, should be avoided.
4160
4161 \value Dynamic Indicates that the data is expected to change frequently.
4162 Not recommended for large buffers. Typically backed by host visible memory
4163 in 2 copies in order to allow for changing without stalling the graphics
4164 pipeline. The double buffering is managed transparently to the applications
4165 and is not exposed in the API here in any form. This is the recommended,
4166 and, with some backends, the only possible, type for buffers with
4167 UniformBuffer usage.
4168 */
4169
4170/*!
4171 \enum QRhiBuffer::UsageFlag
4172 Flag values to specify how the buffer is going to be used.
4173
4174 \value VertexBuffer Vertex buffer. This allows the QRhiBuffer to be used in
4175 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
4176
4177 \value IndexBuffer Index buffer. This allows the QRhiBuffer to be used in
4178 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
4179
4180 \value UniformBuffer Uniform buffer (also called constant buffer). This
4181 allows the QRhiBuffer to be used in combination with
4182 \l{QRhiShaderResourceBinding::UniformBuffer}{UniformBuffer}. When
4183 \l{QRhi::NonDynamicUniformBuffers}{NonDynamicUniformBuffers} is reported as
4184 not supported, this usage can only be combined with the type Dynamic.
4185
4186 \value StorageBuffer Storage buffer. This allows the QRhiBuffer to be used
4187 in combination with \l{QRhiShaderResourceBinding::BufferLoad}{BufferLoad},
4188 \l{QRhiShaderResourceBinding::BufferStore}{BufferStore}, or
4189 \l{QRhiShaderResourceBinding::BufferLoadStore}{BufferLoadStore}. This usage
4190 can only be combined with the types Immutable or Static, and is only
4191 available when the \l{QRhi::Compute}{Compute feature} is reported as
4192 supported.
4193
4194 \value [since 6.12] IndirectBuffer Indirect draw or dispatch buffer. This
4195 allows the QRhiBuffer to be used in
4196 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()},
4197 \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}, and
4198 \l{QRhiCommandBuffer::dispatchIndirect()}{dispatchIndirect()}.
4199 This usage can be combined with types Immutable or Static. Combining it with
4200 Dynamic is unsupported with D3D11, where create() will fail. This usage may
4201 also be combined with StorageBuffer on backends that support
4202 \l{QRhi::Compute}{compute shaders}, allowing indirect draw or dispatch
4203 commands to be generated by compute shaders and consumed by indirect
4204 draw/dispatch calls.
4205 */
4206
4207/*!
4208 \class QRhiBuffer::NativeBuffer
4209 \inmodule QtGuiPrivate
4210 \inheaderfile rhi/qrhi.h
4211 \brief Contains information about the underlying native resources of a buffer.
4212 */
4213
4214/*!
4215 \variable QRhiBuffer::NativeBuffer::objects
4216 \brief an array with pointers to the native object handles.
4217
4218 With OpenGL, the native handle is a GLuint value, so the elements in the \c
4219 objects array are pointers to a GLuint. With Vulkan, the native handle is a
4220 VkBuffer, so the elements of the array are pointers to a VkBuffer. With
4221 Direct3D 11 and Metal the elements are pointers to a ID3D11Buffer or
4222 MTLBuffer pointer, respectively. With Direct3D 12, the elements are
4223 pointers to a ID3D12Resource.
4224
4225 \note Pay attention to the fact that the elements are always pointers to
4226 the native buffer handle type, even if the native type itself is a pointer.
4227 (so the elements are \c{VkBuffer *} on Vulkan, even though VkBuffer itself
4228 is a pointer on 64-bit architectures).
4229 */
4230
4231/*!
4232 \variable QRhiBuffer::NativeBuffer::slotCount
4233 \brief Specifies the number of valid elements in the objects array.
4234
4235 The value can be 0, 1, 2, or 3 in practice. 0 indicates that the QRhiBuffer
4236 is not backed by any native buffer objects. This can happen with
4237 QRhiBuffers with the usage UniformBuffer when the underlying API does not
4238 support (or the backend chooses not to use) native uniform buffers. 1 is
4239 commonly used for Immutable and Static types (but some backends may
4240 differ). 2 or 3 is typical when the type is Dynamic (but some backends may
4241 differ).
4242
4243 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4244 */
4245
4246/*!
4247 \internal
4248 */
4249QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, quint32 size_)
4250 : QRhiResource(rhi),
4251 m_type(type_), m_usage(usage_), m_size(size_)
4252{
4253}
4254
4255/*!
4256 \return the resource type.
4257 */
4258QRhiResource::Type QRhiBuffer::resourceType() const
4259{
4260 return Buffer;
4261}
4262
4263/*!
4264 \fn virtual bool QRhiBuffer::create() = 0
4265
4266 Creates the corresponding native graphics resources. If there are already
4267 resources present due to an earlier create() with no corresponding
4268 destroy(), then destroy() is called implicitly first.
4269
4270 \return \c true when successful, \c false when a graphics operation failed.
4271 Regardless of the return value, calling destroy() is always safe.
4272 */
4273
4274/*!
4275 \fn QRhiBuffer::Type QRhiBuffer::type() const
4276 \return the buffer type.
4277 */
4278
4279/*!
4280 \fn void QRhiBuffer::setType(Type t)
4281 Sets the buffer's type to \a t.
4282 */
4283
4284/*!
4285 \fn QRhiBuffer::UsageFlags QRhiBuffer::usage() const
4286 \return the buffer's usage flags.
4287 */
4288
4289/*!
4290 \fn void QRhiBuffer::setUsage(UsageFlags u)
4291 Sets the buffer's usage flags to \a u.
4292 */
4293
4294/*!
4295 \fn quint32 QRhiBuffer::size() const
4296
4297 \return the buffer's size in bytes.
4298
4299 This is always the value that was passed to setSize() or QRhi::newBuffer().
4300 Internally, the native buffers may be bigger if that is required by the
4301 underlying graphics API.
4302 */
4303
4304/*!
4305 \fn void QRhiBuffer::setSize(quint32 sz)
4306
4307 Sets the size of the buffer in bytes. The size is normally specified in
4308 QRhi::newBuffer() so this function is only used when the size has to be
4309 changed. As with other setters, the size only takes effect when calling
4310 create(), and for already created buffers this involves releasing the previous
4311 native resource and creating new ones under the hood.
4312
4313 Backends may choose to allocate buffers bigger than \a sz in order to
4314 fulfill alignment requirements. This is hidden from the applications and
4315 size() will always report the size requested in \a sz.
4316 */
4317
4318/*!
4319 \return the underlying native resources for this buffer. The returned value
4320 will be empty if exposing the underlying native resources is not supported by
4321 the backend.
4322
4323 A QRhiBuffer may be backed by multiple native buffer objects, depending on
4324 the type() and the QRhi backend in use. When this is the case, all of them
4325 are returned in the objects array in the returned struct, with slotCount
4326 specifying the number of native buffer objects. While
4327 \l{QRhi::beginFrame()}{recording a frame}, QRhi::currentFrameSlot() can be
4328 used to determine which of the native buffers QRhi is using for operations
4329 that read or write from this QRhiBuffer within the frame being recorded.
4330
4331 In some cases a QRhiBuffer will not be backed by a native buffer object at
4332 all. In this case slotCount will be set to 0 and no valid native objects
4333 are returned. This is not an error, and is perfectly valid when a given
4334 backend does not use native buffers for QRhiBuffers with certain types or
4335 usages.
4336
4337 \note Be aware that QRhi backends may employ various buffer update
4338 strategies. Unlike textures, where uploading image data always means
4339 recording a buffer-to-image (or similar) copy command on the command
4340 buffer, buffers, in particular Dynamic and UniformBuffer ones, can operate
4341 in many different ways. For example, a QRhiBuffer with usage type
4342 UniformBuffer may not even be backed by a native buffer object at all if
4343 uniform buffers are not used or supported by a given backend and graphics
4344 API. There are also differences to how data is written to the buffer and
4345 the type of backing memory used. For buffers backed by host visible memory,
4346 calling this function guarantees that pending host writes are executed for
4347 all the returned native buffers.
4348
4349 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4350 */
4351QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
4352{
4353 return { {}, 0 };
4354}
4355
4356/*!
4357 \return a pointer to a memory block with the host visible buffer data.
4358
4359 This is a shortcut for medium-to-large dynamic uniform buffers that have
4360 their \b entire contents (or at least all regions that are read by the
4361 shaders in the current frame) changed \b{in every frame} and the
4362 QRhiResourceUpdateBatch-based update mechanism is seen too heavy due to the
4363 amount of data copying involved.
4364
4365 The call to this function must be eventually followed by a call to
4366 endFullDynamicUniformBufferUpdateForCurrentFrame(), before recording any
4367 render or compute pass that relies on this buffer.
4368
4369 \warning Updating data via this method is not compatible with
4370 QRhiResourceUpdateBatch-based updates and readbacks. Unexpected behavior
4371 may occur when attempting to combine the two update models for the same
4372 buffer. Similarly, the data updated this direct way may not be visible to
4373 \l{QRhiResourceUpdateBatch::readBackBuffer()}{readBackBuffer operations},
4374 depending on the backend.
4375
4376 \warning When updating buffer data via this method, the update must be done
4377 in every frame, otherwise backends that perform double or triple buffering
4378 of resources may end up in unexpected behavior.
4379
4380 \warning Partial updates are not possible with this approach since some
4381 backends may choose a strategy where the previous contents of the buffer is
4382 lost upon calling this function. Data must be written to all regions that
4383 are read by shaders in the frame currently being prepared.
4384
4385 \warning This function can only be called when recording a frame, so
4386 between QRhi::beginFrame() and QRhi::endFrame().
4387
4388 \warning This function can only be called on Dynamic buffers.
4389 */
4390char *QRhiBuffer::beginFullDynamicBufferUpdateForCurrentFrame()
4391{
4392 return nullptr;
4393}
4394
4395/*!
4396 To be called when the entire contents of the buffer data has been updated
4397 in the memory block returned from
4398 beginFullDynamicBufferUpdateForCurrentFrame().
4399 */
4400void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
4401{
4402}
4403
4404/*!
4405 \internal
4406 */
4407void QRhiBuffer::fullDynamicBufferUpdateForCurrentFrame(const void *data, quint32 size)
4408{
4409 char *p = beginFullDynamicBufferUpdateForCurrentFrame();
4410 if (p) {
4411 memcpy(p, data, size > 0 ? size : m_size);
4412 endFullDynamicBufferUpdateForCurrentFrame();
4413 }
4414}
4415
4416/*!
4417 \class QRhiRenderBuffer
4418 \inmodule QtGuiPrivate
4419 \inheaderfile rhi/qrhi.h
4420 \since 6.6
4421 \brief Renderbuffer resource.
4422
4423 Renderbuffers cannot be sampled or read but have some benefits over
4424 textures in some cases:
4425
4426 A \l DepthStencil renderbuffer may be lazily allocated and be backed by
4427 transient memory with some APIs. On some platforms this may mean the
4428 depth/stencil buffer uses no physical backing at all.
4429
4430 That transient nature has a consequence: the contents of a \l DepthStencil
4431 renderbuffer are not guaranteed to survive if a backend has to interrupt and
4432 restart a render pass internally. With Metal this happens when a draw call
4433 is implemented via indirect command buffers, which is the case for
4434 \l{QRhiCommandBuffer::drawIndirectCount()}{drawIndirectCount()} and its
4435 indexed variant, for a high draw count
4436 \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()} or
4437 \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}, and
4438 also when tessellation is used. Draws recorded after such a call then
4439 depth-test against a depth buffer that lost its contents. When this matters,
4440 set the \l NoTransientBacking flag, which makes the contents preservable at
4441 the cost of the memory and bandwidth that the transient backing was saving.
4442 Alternatively, where a QRhiTextureRenderTarget is used anyway, attach a depth
4443 or depth-stencil QRhiTexture with
4444 \l{QRhiTextureRenderTargetDescription::setDepthTexture()}{setDepthTexture()}
4445 instead of a renderbuffer: that is preserved across an interruption, unless
4446 QRhiTextureRenderTarget::DoNotStoreDepthStencilContents is set.
4447
4448 Note that the indirect drawing cases above are avoidable. A
4449 QRhiIndirectCommandBuffer executed with
4450 \l{QRhiCommandBuffer::executeIndirect()}{executeIndirect()} is prepared
4451 before the render pass begins, so it never interrupts the pass however many
4452 commands it holds, and none of this applies to it. Only tessellation then
4453 remains as a reason to consider \l NoTransientBacking.
4454
4455 \l Color renderbuffers are useful since QRhi::MultisampleRenderBuffer may be
4456 supported even when QRhi::MultisampleTexture is not.
4457
4458 How the renderbuffer is implemented by a backend is not exposed to the
4459 applications. In some cases it may be backed by ordinary textures, while in
4460 others there may be a different kind of native resource used.
4461
4462 Renderbuffers that are used as (and are only used as) depth-stencil buffers
4463 in combination with a QRhiSwapChain's color buffers should have the
4464 UsedWithSwapChainOnly flag set. This serves a double purpose: such buffers,
4465 depending on the backend and the underlying APIs, be more efficient, and
4466 QRhi provides automatic sizing behavior to match the color buffers, which
4467 means calling setPixelSize() and create() are not necessary for such
4468 renderbuffers.
4469
4470 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4471 for details.
4472 */
4473
4474/*!
4475 \enum QRhiRenderBuffer::Type
4476 Specifies the type of the renderbuffer
4477
4478 \value DepthStencil Combined depth/stencil
4479 \value Color Color
4480 */
4481
4482/*!
4483 \struct QRhiRenderBuffer::NativeRenderBuffer
4484 \inmodule QtGuiPrivate
4485 \inheaderfile rhi/qrhi.h
4486 \brief Wraps a native renderbuffer object.
4487 */
4488
4489/*!
4490 \variable QRhiRenderBuffer::NativeRenderBuffer::object
4491 \brief 64-bit integer containing the native object handle.
4492
4493 Used with QRhiRenderBuffer::createFrom().
4494
4495 With OpenGL the native handle is a GLuint value. \c object is expected to
4496 be a valid OpenGL renderbuffer object ID.
4497 */
4498
4499/*!
4500 \enum QRhiRenderBuffer::Flag
4501 Flag values for flags() and setFlags()
4502
4503 \value UsedWithSwapChainOnly For DepthStencil renderbuffers this indicates
4504 that the renderbuffer is only used in combination with a QRhiSwapChain, and
4505 never in any other way. This provides automatic sizing and resource
4506 rebuilding, so calling setPixelSize() or create() is not needed whenever
4507 this flag is set. This flag value may also trigger backend-specific
4508 behavior, for example with OpenGL, where a separate windowing system
4509 interface API is in use (EGL, GLX, etc.), the flag is especially important
4510 as it avoids creating any actual renderbuffer resource as there is already
4511 a windowing system provided depth/stencil buffer as requested by
4512 QSurfaceFormat.
4513
4514 \value [since 6.13] NoTransientBacking Requests that the renderbuffer is not
4515 backed by transient, lazily allocated memory. Only relevant for
4516 \l DepthStencil renderbuffers, and only with backends that would otherwise
4517 choose such storage, which in practice means Metal on Apple GPUs. Set this
4518 when the contents have to survive a render pass being interrupted and
4519 continued internally by a backend, as described in the
4520 \l{QRhiRenderBuffer}{class documentation}. It costs actual memory and
4521 bandwidth for the depth/stencil buffer, so do not set it when not needed.
4522 In particular it is not needed on account of
4523 \l{QRhiCommandBuffer::executeIndirect()}{executeIndirect()}, which never
4524 interrupts the pass.
4525 */
4526
4527/*!
4528 \internal
4529 */
4530QRhiRenderBuffer::QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
4531 int sampleCount_, Flags flags_,
4532 QRhiTexture::Format backingFormatHint_)
4533 : QRhiResource(rhi),
4534 m_type(type_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_),
4535 m_backingFormatHint(backingFormatHint_)
4536{
4537}
4538
4539/*!
4540 \return the resource type.
4541 */
4542QRhiResource::Type QRhiRenderBuffer::resourceType() const
4543{
4544 return RenderBuffer;
4545}
4546
4547/*!
4548 \fn virtual bool QRhiRenderBuffer::create() = 0
4549
4550 Creates the corresponding native graphics resources. If there are already
4551 resources present due to an earlier create() with no corresponding
4552 destroy(), then destroy() is called implicitly first.
4553
4554 \return \c true when successful, \c false when a graphics operation failed.
4555 Regardless of the return value, calling destroy() is always safe.
4556 */
4557
4558/*!
4559 Similar to create() except that no new native renderbuffer objects are
4560 created. Instead, the native renderbuffer object specified by \a src is
4561 used.
4562
4563 This allows importing an existing renderbuffer object (which must belong to
4564 the same device or sharing context, depending on the graphics API) from an
4565 external graphics engine.
4566
4567 \note This is currently applicable to OpenGL only. This function exists
4568 solely to allow importing a renderbuffer object that is bound to some
4569 special, external object, such as an EGLImageKHR. Once the application
4570 performed the glEGLImageTargetRenderbufferStorageOES call, the renderbuffer
4571 object can be passed to this function to create a wrapping
4572 QRhiRenderBuffer, which in turn can be passed in as a color attachment to
4573 a QRhiTextureRenderTarget to enable rendering to the EGLImage.
4574
4575 \note pixelSize(), sampleCount(), and flags() must still be set correctly.
4576 Passing incorrect sizes and other values to QRhi::newRenderBuffer() and
4577 then following it with a createFrom() expecting that the native
4578 renderbuffer object alone is sufficient to deduce such values is \b wrong
4579 and will lead to problems.
4580
4581 \note QRhiRenderBuffer does not take ownership of the native object, and
4582 destroy() will not release that object.
4583
4584 \note This function is only implemented when the QRhi::RenderBufferImport
4585 feature is reported as \l{QRhi::isFeatureSupported()}{supported}. Otherwise,
4586 the function does nothing and the return value is \c false.
4587
4588 \return \c true when successful, \c false when not supported.
4589 */
4590bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
4591{
4592 Q_UNUSED(src);
4593 return false;
4594}
4595
4596/*!
4597 \fn QRhiRenderBuffer::Type QRhiRenderBuffer::type() const
4598 \return the renderbuffer type.
4599 */
4600
4601/*!
4602 \fn void QRhiRenderBuffer::setType(Type t)
4603 Sets the type to \a t.
4604 */
4605
4606/*!
4607 \fn QSize QRhiRenderBuffer::pixelSize() const
4608 \return the pixel size.
4609 */
4610
4611/*!
4612 \fn void QRhiRenderBuffer::setPixelSize(const QSize &sz)
4613 Sets the size (in pixels) to \a sz.
4614 */
4615
4616/*!
4617 \fn int QRhiRenderBuffer::sampleCount() const
4618 \return the sample count. 1 means no multisample antialiasing.
4619 */
4620
4621/*!
4622 \fn void QRhiRenderBuffer::setSampleCount(int s)
4623 Sets the sample count to \a s.
4624 */
4625
4626/*!
4627 \fn QRhiRenderBuffer::Flags QRhiRenderBuffer::flags() const
4628 \return the flags.
4629 */
4630
4631/*!
4632 \fn void QRhiRenderBuffer::setFlags(Flags f)
4633 Sets the flags to \a f.
4634 */
4635
4636/*!
4637 \fn virtual QRhiTexture::Format QRhiRenderBuffer::backingFormat() const = 0
4638
4639 \internal
4640 */
4641
4642/*!
4643 \class QRhiTexture
4644 \inmodule QtGuiPrivate
4645 \inheaderfile rhi/qrhi.h
4646 \since 6.6
4647 \brief Texture resource.
4648
4649 A QRhiTexture encapsulates a native texture object, such as a \c VkImage or
4650 \c MTLTexture.
4651
4652 A QRhiTexture instance is always created by calling
4653 \l{QRhi::newTexture()}{the QRhi's newTexture() function}. This creates no
4654 native graphics resources. To do that, call create() after setting the
4655 appropriate options, such as the format and size, although in most cases
4656 these are already set based on the arguments passed to
4657 \l{QRhi::newTexture()}{newTexture()}.
4658
4659 Setting the \l{QRhiTexture::Flags}{flags} correctly is essential, otherwise
4660 various errors can occur depending on the underlying QRhi backend and
4661 graphics API. For example, when a texture will be rendered into from a
4662 render pass via QRhiTextureRenderTarget, the texture must be created with
4663 the \l RenderTarget flag set. Similarly, when the texture is going to be
4664 \l{QRhiResourceUpdateBatch::readBackTexture()}{read back}, the \l
4665 UsedAsTransferSource flag must be set upfront. Mipmapped textures must have
4666 the MipMapped flag set. And so on. It is not possible to change the flags
4667 once create() has succeeded. To release the existing and create a new
4668 native texture object with the changed settings, call the setters and call
4669 create() again. This then might be a potentially expensive operation.
4670
4671 \section1 Example usage
4672
4673 To create a 2D texture with a size of 512x512 pixels and set its contents to all green:
4674
4675 \code
4676 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512));
4677 if (!texture->create()) { error(); }
4678 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4679 QImage image(512, 512, QImage::Format_RGBA8888);
4680 image.fill(Qt::green);
4681 batch->uploadTexture(texture, image);
4682 // ...
4683 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4684 \endcode
4685
4686 \section1 Common patterns
4687
4688 A call to create() destroys any existing native resources if create() was
4689 successfully called before. If those native resources are still in use by
4690 an in-flight frame (i.e., there's a chance they are still read by the GPU),
4691 the destroying of those resources is deferred automatically. Thus a very
4692 common and convenient pattern to safely change the size of an already
4693 existing texture is the following. In practice this drops and creates a
4694 whole new native texture resource underneath, so it is not necessarily a
4695 cheap operation, but is more convenient and still faster than the
4696 alternatives, because by not destroying the \c texture object itself, all
4697 references to it stay valid in other data structures (e.g., in any
4698 QShaderResourceBinding the QRhiTexture is referenced from).
4699
4700 \code
4701 // determine newSize, e.g. based on the swapchain's output size or other factors
4702 if (texture->pixelSize() != newSize) {
4703 texture->setPixelSize(newSize);
4704 if (!texture->create()) { error(); }
4705 }
4706 // continue using texture, fill it with new data
4707 \endcode
4708
4709 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4710 for details.
4711
4712 \sa QRhiResourceUpdateBatch, QRhi, QRhiTextureRenderTarget
4713 */
4714
4715/*!
4716 \enum QRhiTexture::Flag
4717
4718 Flag values to specify how the texture is going to be used. Not honoring
4719 the flags set before create() and attempting to use the texture in ways that
4720 was not declared upfront can lead to unspecified behavior or decreased
4721 performance depending on the backend and the underlying graphics API.
4722
4723 \value RenderTarget The texture going to be used in combination with
4724 QRhiTextureRenderTarget.
4725
4726 \value CubeMap The texture is a cubemap. Such textures have 6 layers, one
4727 for each face in the order of +X, -X, +Y, -Y, +Z, -Z. Cubemap textures
4728 cannot be multisample.
4729
4730 \value MipMapped The texture has mipmaps. The appropriate mip count is
4731 calculated automatically and can also be retrieved via
4732 QRhi::mipLevelsForSize(). The images for the mip levels have to be
4733 provided in the texture uploaded or generated via
4734 QRhiResourceUpdateBatch::generateMips(). Multisample textures cannot have
4735 mipmaps.
4736
4737 \value sRGB Use an sRGB format.
4738
4739 \value UsedAsTransferSource The texture is used as the source of a texture
4740 copy or readback, meaning the texture is given as the source in
4741 QRhiResourceUpdateBatch::copyTexture() or
4742 QRhiResourceUpdateBatch::readBackTexture().
4743
4744 \value UsedWithGenerateMips The texture is going to be used with
4745 QRhiResourceUpdateBatch::generateMips().
4746
4747 \value UsedWithLoadStore The texture is going to be used with image
4748 load/store operations, for example, in a compute shader.
4749
4750 \value UsedAsCompressedAtlas The texture has a compressed format and the
4751 dimensions of subresource uploads may not match the texture size.
4752
4753 \value ExternalOES The texture should use the GL_TEXTURE_EXTERNAL_OES
4754 target with OpenGL. This flag is ignored with other graphics APIs.
4755
4756 \value ThreeDimensional The texture is a 3D texture. Such textures should
4757 be created with the QRhi::newTexture() overload taking a depth in addition
4758 to width and height. A 3D texture can have mipmaps but cannot be
4759 multisample. When rendering into, or uploading data to a 3D texture, the \c
4760 layer specified in the render target's color attachment or the upload
4761 description refers to a single slice in range [0..depth-1]. The underlying
4762 graphics API may not support 3D textures at run time. Support is indicated
4763 by the QRhi::ThreeDimensionalTextures feature.
4764
4765 \value TextureRectangleGL The texture should use the GL_TEXTURE_RECTANGLE
4766 target with OpenGL. This flag is ignored with other graphics APIs. Just
4767 like ExternalOES, this flag is useful when working with platform APIs where
4768 native OpenGL texture objects received from the platform are wrapped in a
4769 QRhiTexture, and the platform can only provide textures for a non-2D
4770 texture target.
4771
4772 \value TextureArray The texture is a texture array, i.e. a single texture
4773 object that is a homogeneous array of 2D textures. Texture arrays are
4774 created with QRhi::newTextureArray(). The underlying graphics API may not
4775 support texture array objects at run time. Support is indicated by the
4776 QRhi::TextureArrays feature. When rendering into, or uploading data to a
4777 texture array, the \c layer specified in the render target's color
4778 attachment or the upload description selects a single element in the array.
4779
4780 \value OneDimensional The texture is a 1D texture. Such textures can be
4781 created by passing a 0 height and depth to QRhi::newTexture(). Note that
4782 there can be limitations on one dimensional textures depending on the
4783 underlying graphics API. For example, rendering to them or using them with
4784 mipmap-based filtering may be unsupported. This is indicated by the
4785 QRhi::OneDimensionalTextures and QRhi::OneDimensionalTextureMipmaps
4786 feature flags.
4787
4788 \value UsedAsShadingRateMap
4789 */
4790
4791/*!
4792 \enum QRhiTexture::Format
4793
4794 Specifies the texture format. See also QRhi::isTextureFormatSupported() and
4795 note that flags() can modify the format when QRhiTexture::sRGB is set.
4796
4797 \value UnknownFormat Not a valid format. This cannot be passed to setFormat().
4798
4799 \value RGBA8 Four components, unsigned normalized 8-bit per component. Always supported. (32 bits total)
4800
4801 \value BGRA8 Four components, unsigned normalized 8-bit per component. (32 bits total)
4802
4803 \value R8 One component, unsigned normalized 8-bit. (8 bits total)
4804
4805 \value RG8 Two components, unsigned normalized 8-bit. (16 bits total)
4806
4807 \value R16 One component, unsigned normalized 16-bit. (16 bits total)
4808
4809 \value RG16 Two components, unsigned normalized 16-bit. (32 bits total)
4810
4811 \value RED_OR_ALPHA8 Either same as R8, or is a similar format with the component swizzled to alpha,
4812 depending on \l{QRhi::RedOrAlpha8IsRed}{RedOrAlpha8IsRed}. (8 bits total)
4813
4814 \value RGBA16F Four components, 16-bit float. (64 bits total)
4815
4816 \value RGBA32F Four components, 32-bit float. (128 bits total)
4817
4818 \value R16F One component, 16-bit float. (16 bits total)
4819
4820 \value R32F One component, 32-bit float. (32 bits total)
4821
4822 \value RGB10A2 Four components, unsigned normalized 10 bit R, G, and B,
4823 2-bit alpha. This is a packed format so native endianness applies. Note
4824 that there is no BGR10A2. This is because RGB10A2 maps to
4825 DXGI_FORMAT_R10G10B10A2_UNORM with D3D, MTLPixelFormatRGB10A2Unorm with
4826 Metal, VK_FORMAT_A2B10G10R10_UNORM_PACK32 with Vulkan, and
4827 GL_RGB10_A2/GL_RGB/GL_UNSIGNED_INT_2_10_10_10_REV on OpenGL (ES). This is
4828 the only universally supported RGB30 option. The corresponding QImage
4829 formats are QImage::Format_BGR30 and QImage::Format_A2BGR30_Premultiplied.
4830 (32 bits total)
4831
4832 \value D16 16-bit depth (normalized unsigned integer)
4833
4834 \value D24 24-bit depth (normalized unsigned integer)
4835
4836 \value D24S8 24-bit depth (normalized unsigned integer), 8 bit stencil
4837
4838 \value D32F 32-bit depth (32-bit float)
4839
4840 \value [since 6.9] D32FS8 32-bit depth (32-bit float), 8 bits of stencil, 24 bits unused
4841 (64 bits total)
4842
4843 \value BC1
4844 \value BC2
4845 \value BC3
4846 \value BC4
4847 \value BC5
4848 \value BC6H
4849 \value BC7
4850
4851 \value ETC2_RGB8
4852 \value ETC2_RGB8A1
4853 \value ETC2_RGBA8
4854
4855 \value ASTC_4x4
4856 \value ASTC_5x4
4857 \value ASTC_5x5
4858 \value ASTC_6x5
4859 \value ASTC_6x6
4860 \value ASTC_8x5
4861 \value ASTC_8x6
4862 \value ASTC_8x8
4863 \value ASTC_10x5
4864 \value ASTC_10x6
4865 \value ASTC_10x8
4866 \value ASTC_10x10
4867 \value ASTC_12x10
4868 \value ASTC_12x12
4869
4870 \value [since 6.9] R8UI One component, unsigned 8-bit. (8 bits total)
4871 \value [since 6.9] R32UI One component, unsigned 32-bit. (32 bits total)
4872 \value [since 6.9] RG32UI Two components, unsigned 32-bit. (64 bits total)
4873 \value [since 6.9] RGBA32UI Four components, unsigned 32-bit. (128 bits total)
4874
4875 \value [since 6.10] R8SI One component, signed 8-bit. (8 bits total)
4876 \value [since 6.10] R32SI One component, signed 32-bit. (32 bits total)
4877 \value [since 6.10] RG32SI Two components, signed 32-bit. (64 bits total)
4878 \value [since 6.10] RGBA32SI Four components, signed 32-bit. (128 bits total)
4879 */
4880
4881// When adding new texture formats, update void tst_QRhi::textureFormats_data().
4882
4883/*!
4884 \struct QRhiTexture::NativeTexture
4885 \inmodule QtGuiPrivate
4886 \inheaderfile rhi/qrhi.h
4887 \brief Contains information about the underlying native resources of a texture.
4888 */
4889
4890/*!
4891 \variable QRhiTexture::NativeTexture::object
4892 \brief 64-bit integer containing the native object handle.
4893
4894 With OpenGL, the native handle is a GLuint value, so \c object can then be
4895 cast to a GLuint. With Vulkan, the native handle is a VkImage, so \c object
4896 can be cast to a VkImage. With Direct3D 11 and Metal \c object contains a
4897 ID3D11Texture2D or MTLTexture pointer, respectively. With Direct3D 12
4898 \c object contains a ID3D12Resource pointer.
4899 */
4900
4901/*!
4902 \variable QRhiTexture::NativeTexture::layout
4903 \brief Specifies the current image layout for APIs like Vulkan.
4904
4905 For Vulkan, \c layout contains a \c VkImageLayout value.
4906 */
4907
4908/*!
4909 \internal
4910 */
4911QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
4912 int arraySize_, int sampleCount_, Flags flags_)
4913 : QRhiResource(rhi),
4914 m_format(format_), m_pixelSize(pixelSize_), m_depth(depth_),
4915 m_arraySize(arraySize_), m_sampleCount(sampleCount_), m_flags(flags_)
4916{
4917}
4918
4919/*!
4920 \return the resource type.
4921 */
4922QRhiResource::Type QRhiTexture::resourceType() const
4923{
4924 return Texture;
4925}
4926
4927/*!
4928 \fn virtual bool QRhiTexture::create() = 0
4929
4930 Creates the corresponding native graphics resources. If there are already
4931 resources present due to an earlier create() with no corresponding
4932 destroy(), then destroy() is called implicitly first.
4933
4934 \return \c true when successful, \c false when a graphics operation failed.
4935 Regardless of the return value, calling destroy() is always safe.
4936 */
4937
4938/*!
4939 \return the underlying native resources for this texture. The returned value
4940 will be empty if exposing the underlying native resources is not supported by
4941 the backend.
4942
4943 \sa createFrom()
4944 */
4945QRhiTexture::NativeTexture QRhiTexture::nativeTexture()
4946{
4947 return {};
4948}
4949
4950/*!
4951 Similar to create(), except that no new native textures are created.
4952 Instead, the native texture resources specified by \a src is used.
4953
4954 This allows importing an existing native texture object (which must belong
4955 to the same device or sharing context, depending on the graphics API) from
4956 an external graphics engine.
4957
4958 \return true if the specified existing native texture object has been
4959 successfully wrapped as a non-owning QRhiTexture.
4960
4961 \note format(), pixelSize(), sampleCount(), and flags() must still be set
4962 correctly. Passing incorrect sizes and other values to QRhi::newTexture()
4963 and then following it with a createFrom() expecting that the native texture
4964 object alone is sufficient to deduce such values is \b wrong and will lead
4965 to problems.
4966
4967 \note QRhiTexture does not take ownership of the texture object. destroy()
4968 does not free the object or any associated memory.
4969
4970 The opposite of this operation, exposing a QRhiTexture-created native
4971 texture object to a foreign engine, is possible via nativeTexture().
4972
4973 \note When importing a 3D texture, or a texture array object, or, with
4974 OpenGL ES, an external texture, it is then especially important to set the
4975 corresponding flags (ThreeDimensional, TextureArray, ExternalOES) via
4976 setFlags() before calling this function.
4977*/
4978bool QRhiTexture::createFrom(QRhiTexture::NativeTexture src)
4979{
4980 Q_UNUSED(src);
4981 return false;
4982}
4983
4984/*!
4985 With some graphics APIs, such as Vulkan, integrating custom rendering code
4986 that uses the graphics API directly needs special care when it comes to
4987 image layouts. This function allows communicating the expected \a layout the
4988 image backing the QRhiTexture is in after the native rendering commands.
4989
4990 For example, consider rendering into a QRhiTexture's VkImage directly with
4991 Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and
4992 QRhiCommandBuffer::endExternal(), followed by using the image for texture
4993 sampling in a QRhi-based render pass. To avoid potentially incorrect image
4994 layout transitions, this function can be used to indicate what the image
4995 layout will be once the commands recorded in said code block complete.
4996
4997 Calling this function makes sense only after
4998 QRhiCommandBuffer::endExternal() and before a subsequent
4999 QRhiCommandBuffer::beginPass().
5000
5001 This function has no effect with QRhi backends where the underlying
5002 graphics API does not expose a concept of image layouts.
5003
5004 \note With Vulkan \a layout is a \c VkImageLayout. With Direct 3D 12 \a
5005 layout is a value composed of the bits from \c D3D12_RESOURCE_STATES.
5006 */
5007void QRhiTexture::setNativeLayout(int layout)
5008{
5009 Q_UNUSED(layout);
5010}
5011
5012/*!
5013 \fn QRhiTexture::Format QRhiTexture::format() const
5014 \return the texture format.
5015 */
5016
5017/*!
5018 \fn void QRhiTexture::setFormat(QRhiTexture::Format fmt)
5019
5020 Sets the requested texture format to \a fmt.
5021
5022 \note The value set is only taken into account upon the next call to
5023 create(), i.e. when the underlying graphics resource are (re)created.
5024 Setting a new value is futile otherwise and must be avoided since it can
5025 lead to inconsistent state.
5026 */
5027
5028/*!
5029 \fn QSize QRhiTexture::pixelSize() const
5030 \return the size in pixels.
5031 */
5032
5033/*!
5034 \fn void QRhiTexture::setPixelSize(const QSize &sz)
5035
5036 Sets the texture size, specified in pixels, to \a sz.
5037
5038 \note The value set is only taken into account upon the next call to
5039 create(), i.e. when the underlying graphics resource are (re)created.
5040 Setting a new value is futile otherwise and must be avoided since it can
5041 lead to inconsistent state. The same applies to all other setters as well.
5042 */
5043
5044/*!
5045 \fn int QRhiTexture::depth() const
5046 \return the depth for 3D textures.
5047 */
5048
5049/*!
5050 \fn void QRhiTexture::setDepth(int depth)
5051 Sets the \a depth for a 3D texture.
5052 */
5053
5054/*!
5055 \fn int QRhiTexture::arraySize() const
5056 \return the texture array size.
5057 */
5058
5059/*!
5060 \fn void QRhiTexture::setArraySize(int arraySize)
5061 Sets the texture \a arraySize.
5062 */
5063
5064/*!
5065 \fn int QRhiTexture::arrayRangeStart() const
5066
5067 \return the first array layer when setArrayRange() was called.
5068
5069 \sa setArrayRange()
5070 */
5071
5072/*!
5073 \fn int QRhiTexture::arrayRangeLength() const
5074
5075 \return the exposed array range size when setArrayRange() was called.
5076
5077 \sa setArrayRange()
5078*/
5079
5080/*!
5081 \fn void QRhiTexture::setArrayRange(int startIndex, int count)
5082
5083 Normally all array layers are exposed and it is up to the shader to select
5084 the layer via the third coordinate passed to the \c{texture()} GLSL
5085 function when sampling the \c sampler2DArray. When QRhi::TextureArrayRange
5086 is reported as supported, calling setArrayRange() before create() or
5087 createFrom() requests selecting only the specified range, \a count elements
5088 starting from \a startIndex. The shader logic can then be written with this
5089 in mind.
5090
5091 \sa QRhi::TextureArrayRange
5092 */
5093
5094/*!
5095 \fn Flags QRhiTexture::flags() const
5096 \return the texture flags.
5097 */
5098
5099/*!
5100 \fn void QRhiTexture::setFlags(Flags f)
5101 Sets the texture flags to \a f.
5102 */
5103
5104/*!
5105 \fn int QRhiTexture::sampleCount() const
5106 \return the sample count. 1 means no multisample antialiasing.
5107 */
5108
5109/*!
5110 \fn void QRhiTexture::setSampleCount(int s)
5111 Sets the sample count to \a s.
5112 */
5113
5114/*!
5115 \struct QRhiTexture::ViewFormat
5116 \inmodule QtGuiPrivate
5117 \inheaderfile rhi/qrhi.h
5118 \since 6.8
5119 \brief Specifies the view format for reading or writing from or to the texture.
5120
5121 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5122 for details.
5123 */
5124
5125/*!
5126 \variable QRhiTexture::ViewFormat::format
5127 */
5128
5129/*!
5130 \variable QRhiTexture::ViewFormat::srgb
5131 */
5132
5133/*!
5134 \fn QRhiTexture::ViewFormat QRhiTexture::readViewFormat() const
5135 \since 6.8
5136 \return the view format used when sampling the texture. When not called, the view
5137 format is assumed to be the same as format().
5138 */
5139
5140/*!
5141 \fn void QRhiTexture::setReadViewFormat(const ViewFormat &fmt)
5142 \since 6.8
5143
5144 Sets the shader resource view format (or the format of the view used for
5145 sampling the texture) to \a fmt. By default the same format (and sRGB-ness)
5146 is used as the texture itself, and in most cases this function does not need
5147 to be called.
5148
5149 This setting is only taken into account when the \l QRhi::TextureViewFormat
5150 feature is reported as supported.
5151
5152 \note This functionality is provided to allow "casting" between
5153 non-sRGB and sRGB in order to get the shader reads perform, or not perform,
5154 the implicit sRGB conversions. Other types of casting may or may not be
5155 functional.
5156 */
5157
5158/*!
5159 \fn QRhiTexture::ViewFormat QRhiTexture::writeViewFormat() const
5160 \since 6.8
5161 \return the view format used when writing to the texture and when using it
5162 with image load/store. When not called, the view format is assumed to be the
5163 same as format().
5164 */
5165
5166/*!
5167 \fn void QRhiTexture::setWriteViewFormat(const ViewFormat &fmt)
5168 \since 6.8
5169
5170 Sets the render target view format to \a fmt. By default the same format
5171 (and sRGB-ness) is used as the texture itself, and in most cases this
5172 function does not need to be called.
5173
5174 One common use case for providing a write view format is working with
5175 externally provided textures that, outside of our control, use an sRGB
5176 format with 3D APIs such as Vulkan or Direct 3D, but the rendering engine is
5177 already prepared to handle linearization and conversion to sRGB at the end
5178 of its shading pipeline. In this case what is wanted when rendering into
5179 such a texture is a render target view (e.g. VkImageView) that has the same,
5180 but non-sRGB format. (if e.g. from an OpenXR implementation one gets a
5181 VK_FORMAT_R8G8B8A8_SRGB texture, it is likely that rendering into it should
5182 be done using a VK_FORMAT_R8G8B8A8_UNORM view, if that is what the rendering
5183 engine's pipeline requires; in this example one would call this function
5184 with a ViewFormat that has a format of QRhiTexture::RGBA8 and \c srgb set to
5185 \c false).
5186
5187 This setting is only taken into account when the \l QRhi::TextureViewFormat
5188 feature is reported as supported.
5189
5190 \note This functionality is provided to allow "casting" between
5191 non-sRGB and sRGB in order to get the shader write not perform, or perform,
5192 the implicit sRGB conversions. Other types of casting may or may not be
5193 functional.
5194 */
5195
5196/*!
5197 \class QRhiSampler
5198 \inmodule QtGuiPrivate
5199 \inheaderfile rhi/qrhi.h
5200 \since 6.6
5201 \brief Sampler resource.
5202
5203 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5204 for details.
5205 */
5206
5207/*!
5208 \enum QRhiSampler::Filter
5209 Specifies the minification, magnification, or mipmap filtering
5210
5211 \value None Applicable only for mipmapMode(), indicates no mipmaps to be used
5212 \value Nearest
5213 \value Linear
5214 */
5215
5216/*!
5217 \enum QRhiSampler::AddressMode
5218 Specifies the addressing mode
5219
5220 \value Repeat
5221 \value ClampToEdge
5222 \value Mirror
5223 */
5224
5225/*!
5226 \enum QRhiSampler::CompareOp
5227 Specifies the texture comparison function.
5228
5229 \value Never (default)
5230 \value Less
5231 \value Equal
5232 \value LessOrEqual
5233 \value Greater
5234 \value NotEqual
5235 \value GreaterOrEqual
5236 \value Always
5237 */
5238
5239/*!
5240 \internal
5241 */
5242QRhiSampler::QRhiSampler(QRhiImplementation *rhi,
5243 Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
5244 AddressMode u_, AddressMode v_, AddressMode w_)
5245 : QRhiResource(rhi),
5246 m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_),
5247 m_addressU(u_), m_addressV(v_), m_addressW(w_),
5248 m_compareOp(QRhiSampler::Never)
5249{
5250}
5251
5252/*!
5253 \return the resource type.
5254 */
5255QRhiResource::Type QRhiSampler::resourceType() const
5256{
5257 return Sampler;
5258}
5259
5260/*!
5261 \fn QRhiSampler::Filter QRhiSampler::magFilter() const
5262 \return the magnification filter mode.
5263 */
5264
5265/*!
5266 \fn void QRhiSampler::setMagFilter(Filter f)
5267 Sets the magnification filter mode to \a f.
5268 */
5269
5270/*!
5271 \fn QRhiSampler::Filter QRhiSampler::minFilter() const
5272 \return the minification filter mode.
5273 */
5274
5275/*!
5276 \fn void QRhiSampler::setMinFilter(Filter f)
5277 Sets the minification filter mode to \a f.
5278 */
5279
5280/*!
5281 \fn QRhiSampler::Filter QRhiSampler::mipmapMode() const
5282 \return the mipmap filter mode.
5283 */
5284
5285/*!
5286 \fn void QRhiSampler::setMipmapMode(Filter f)
5287
5288 Sets the mipmap filter mode to \a f.
5289
5290 Leave this set to None when the texture has no mip levels, or when the mip
5291 levels are not to be taken into account.
5292 */
5293
5294/*!
5295 \fn QRhiSampler::AddressMode QRhiSampler::addressU() const
5296 \return the horizontal wrap mode.
5297 */
5298
5299/*!
5300 \fn void QRhiSampler::setAddressU(AddressMode mode)
5301 Sets the horizontal wrap \a mode.
5302 */
5303
5304/*!
5305 \fn QRhiSampler::AddressMode QRhiSampler::addressV() const
5306 \return the vertical wrap mode.
5307 */
5308
5309/*!
5310 \fn void QRhiSampler::setAddressV(AddressMode mode)
5311 Sets the vertical wrap \a mode.
5312 */
5313
5314/*!
5315 \fn QRhiSampler::AddressMode QRhiSampler::addressW() const
5316 \return the depth wrap mode.
5317 */
5318
5319/*!
5320 \fn void QRhiSampler::setAddressW(AddressMode mode)
5321 Sets the depth wrap \a mode.
5322 */
5323
5324/*!
5325 \fn QRhiSampler::CompareOp QRhiSampler::textureCompareOp() const
5326 \return the texture comparison function.
5327 */
5328
5329/*!
5330 \fn void QRhiSampler::setTextureCompareOp(CompareOp op)
5331 Sets the texture comparison function \a op.
5332 */
5333
5334/*!
5335 \class QRhiShadingRateMap
5336 \inmodule QtGuiPrivate
5337 \inheaderfile rhi/qrhi.h
5338 \since 6.9
5339 \brief An object that wraps a texture or another kind of native 3D API object.
5340
5341 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5342 for details.
5343
5344 For an introduction to Variable Rate Shading (VRS), see
5345 \l{https://learn.microsoft.com/en-us/windows/win32/direct3d12/vrs}. Qt
5346 supports a subset of the VRS features offered by Direct 3D 12 and Vulkan. In
5347 addition, Metal's somewhat different mechanism is supported by making it
5348 possible to set up a QRhiShadingRateMap with an existing
5349 MTLRasterizationRateMap object.
5350 */
5351
5352/*!
5353 \struct QRhiShadingRateMap::NativeShadingRateMap
5354 \inmodule QtGuiPrivate
5355 \inheaderfile rhi/qrhi.h
5356 \since 6.9
5357 \brief Wraps a native shading rate map.
5358
5359 An example is MTLRasterizationRateMap with Metal. Other 3D APIs that use
5360 textures for image-based VRS do not use this struct since those can function
5361 via the QRhiTexture-based overload of QRhiShadingRateMap::createFrom().
5362 */
5363
5364/*!
5365 \variable QRhiShadingRateMap::NativeShadingRateMap::object
5366 \brief 64-bit integer containing the native object handle.
5367
5368 Used with QRhiShadingRateMap::createFrom(). For example, with Metal,
5369 \c object is expected to be an id<MTLRasterizationRateMap>.
5370 */
5371
5372/*!
5373 \internal
5374 */
5375QRhiShadingRateMap::QRhiShadingRateMap(QRhiImplementation *rhi)
5376 : QRhiResource(rhi)
5377{
5378}
5379
5380/*!
5381 \return the resource type.
5382 */
5383QRhiResource::Type QRhiShadingRateMap::resourceType() const
5384{
5385 return ShadingRateMap;
5386}
5387
5388/*!
5389 Sets up the shading rate map to use a native 3D API shading rate object
5390 \a src.
5391
5392 \return \c true when successful, \c false when not supported.
5393
5394 \note This is functional only when the QRhi::VariableRateShadingMap feature
5395 is reported as supported, while QRhi::VariableRateShadingMapWithTexture
5396 feature is not. Currently this is true for Metal, assuming variable rate
5397 shading is supported by the GPU.
5398
5399 \note With Metal, the \c object field of \a src is expected to contain an
5400 id<MTLRasterizationRateMap>. Qt passes the MTLRasterizationRateMap on to the
5401 MTLRenderPassDescriptor, and, because Metal then interprets viewports and
5402 scissor rectangles in the map's screen space coordinate system, sizes the
5403 default scissor and converts viewports and scissors specified via
5404 QRhiCommandBuffer accordingly. The size of that coordinate system is
5405 reported by logicalSize(). Anything else, such as scaling when sampling
5406 the rendered result, is up to the application (or the XR compositor).
5407 */
5408bool QRhiShadingRateMap::createFrom(NativeShadingRateMap src)
5409{
5410 Q_UNUSED(src);
5411 return false;
5412}
5413
5414/*!
5415 Sets up the shading rate map to use the texture \a src as the
5416 image containing the per-tile shading rates.
5417
5418 \return \c true when successful, \c false when not supported.
5419
5420 The QRhiShadingRateMap does not take ownership of \a src.
5421
5422 \note This is functional only when the
5423 QRhi::VariableRateShadingMapWithTexture feature is reported as supported. In
5424 practice may be supported on Vulkan and Direct 3D 12 when using modern
5425 graphics cards. It will never be supported on OpenGL or Metal, for example.
5426
5427 \note \a src must have a format of QRhiTexture::R8UI.
5428
5429 \note \a src must have a width of \c{ceil(render_target_pixel_width /
5430 (float)tile_width)} and a height of \c{ceil(render_target_pixel_height /
5431 (float)tile_height)}. It is up to the application to ensure the size of the
5432 texture is as expected, using the above formula, at all times. The tile size
5433 can be queried via \l QRhi::resourceLimit() and
5434 QRhi::ShadingRateImageTileSize.
5435
5436 Each byte (texel) in the texture corresponds to the shading rate value for
5437 one tile. 0 indicates 1x1, while a value of 10 indicates 4x4. See
5438 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shading_rate}{D3D12_SHADING_RATE}
5439 for other possible values.
5440 */
5441bool QRhiShadingRateMap::createFrom(QRhiTexture *src)
5442{
5443 Q_UNUSED(src);
5444 return false;
5445}
5446
5447/*!
5448 \since 6.13
5449
5450 \return the size of the logical coordinate space the shading rate map
5451 defines, or an invalid QSize when the map does not define one.
5452
5453 Some implementations, Metal in particular, describe a shading rate map in
5454 terms of a logical (screen space) size that is mapped onto the physical
5455 pixels of the render target. When such a map is attached to a render
5456 target, viewports and scissor rectangles are interpreted in the logical
5457 coordinate system, and the logical size is typically larger than
5458 QRhiRenderTarget::pixelSize(). Applications that derive viewports,
5459 scissors, or projection setup from the render target size should use this
5460 size instead whenever it is valid.
5461
5462 For implementations where the shading rate map is a tile image covering
5463 the render target, such as Vulkan and Direct 3D 12, there is no separate
5464 logical coordinate space, and an invalid QSize is returned. The render
5465 target's pixel size applies as usual in that case.
5466
5467 \sa QRhiRenderTarget::pixelSize()
5468 */
5469QSize QRhiShadingRateMap::logicalSize() const
5470{
5471 return QSize();
5472}
5473
5474/*!
5475 \class QRhiRenderPassDescriptor
5476 \inmodule QtGuiPrivate
5477 \inheaderfile rhi/qrhi.h
5478 \since 6.6
5479 \brief Render pass resource.
5480
5481 A render pass, if such a concept exists in the underlying graphics API, is
5482 a collection of attachments (color, depth, stencil) and describes how those
5483 attachments are used.
5484
5485 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5486 for details.
5487 */
5488
5489/*!
5490 \internal
5491 */
5492QRhiRenderPassDescriptor::QRhiRenderPassDescriptor(QRhiImplementation *rhi)
5493 : QRhiResource(rhi)
5494{
5495}
5496
5497/*!
5498 \return the resource type.
5499 */
5500QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
5501{
5502 return RenderPassDescriptor;
5503}
5504
5505/*!
5506 \fn virtual bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const = 0
5507
5508 \return true if the \a other QRhiRenderPassDescriptor is compatible with
5509 this one, meaning \c this and \a other can be used interchangeably in
5510 QRhiGraphicsPipeline::setRenderPassDescriptor().
5511
5512 The concept of the compatibility of renderpass descriptors is similar to
5513 the \l{QRhiShaderResourceBindings::isLayoutCompatible}{layout
5514 compatibility} of QRhiShaderResourceBindings instances. They allow better
5515 reuse of QRhiGraphicsPipeline instances: for example, a
5516 QRhiGraphicsPipeline instance cache is expected to use these functions to
5517 look for a matching pipeline, instead of just comparing pointers, thus
5518 allowing a different QRhiRenderPassDescriptor and
5519 QRhiShaderResourceBindings to be used in combination with the pipeline, as
5520 long as they are compatible.
5521
5522 The exact details of compatibility depend on the underlying graphics API.
5523 Two renderpass descriptors
5524 \l{QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()}{created}
5525 from the same QRhiTextureRenderTarget are always compatible.
5526
5527 Similarly to QRhiShaderResourceBindings, compatibility can also be tested
5528 without having two existing objects available. Extracting the opaque blob by
5529 calling serializedFormat() allows testing for compatibility by comparing the
5530 returned vector to another QRhiRenderPassDescriptor's
5531 serializedFormat(). This has benefits in certain situations, because it
5532 allows testing the compatibility of a QRhiRenderPassDescriptor with a
5533 QRhiGraphicsPipeline even when the QRhiRenderPassDescriptor the pipeline was
5534 originally built with is no longer available (but the data returned from its
5535 serializedFormat() still is).
5536
5537 \sa newCompatibleRenderPassDescriptor(), serializedFormat()
5538 */
5539
5540/*!
5541 \fn virtual QRhiRenderPassDescriptor *QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor() const = 0
5542
5543 \return a new QRhiRenderPassDescriptor that is
5544 \l{isCompatible()}{compatible} with this one.
5545
5546 This function allows cloning a QRhiRenderPassDescriptor. The returned
5547 object is ready to be used, and the ownership is transferred to the caller.
5548 Cloning a QRhiRenderPassDescriptor object can become useful in situations
5549 where the object is stored in data structures related to graphics pipelines
5550 (in order to allow creating new pipelines which in turn requires a
5551 renderpass descriptor object), and the lifetime of the renderpass
5552 descriptor created from a render target may be shorter than the pipelines.
5553 (for example, because the engine manages and destroys renderpasses together
5554 with the textures and render targets it was created from) In such a
5555 situation, it can be beneficial to store a cloned version in the data
5556 structures, and thus transferring ownership as well.
5557
5558 \sa isCompatible()
5559 */
5560
5561/*!
5562 \fn virtual QVector<quint32> QRhiRenderPassDescriptor::serializedFormat() const = 0
5563
5564 \return a vector of integers containing an opaque blob describing the data
5565 relevant for \l{isCompatible()}{compatibility}.
5566
5567 Given two QRhiRenderPassDescriptor objects \c rp1 and \c rp2, if the data
5568 returned from this function is identical, then \c{rp1->isCompatible(rp2)},
5569 and vice versa hold true as well.
5570
5571 \note The returned data is meant to be used for storing in memory and
5572 comparisons during the lifetime of the QRhi the object belongs to. It is not
5573 meant for storing on disk, reusing between processes, or using with multiple
5574 QRhi instances with potentially different backends.
5575
5576 \note Calling this function is expected to be a cheap operation since the
5577 backends are not supposed to calculate the data in this function, but rather
5578 return an already calculated series of data.
5579
5580 When creating reusable components as part of a library, where graphics
5581 pipelines are created and maintained while targeting a QRhiRenderTarget (be
5582 it a swapchain or a texture) managed by the client of the library, the
5583 components must be able to deal with a changing QRhiRenderPassDescriptor.
5584 For example, because the render target changes and so invalidates the
5585 previously QRhiRenderPassDescriptor (with regards to the new render target
5586 at least) due to having a potentially different color format and attachments
5587 now. Or because \l{QRhiShadingRateMap}{variable rate shading} is taken into
5588 use dynamically. A simple pattern that helps dealing with this is performing
5589 the following check on every frame, to recognize the case when the pipeline
5590 needs to be associated with a new QRhiRenderPassDescriptor, because
5591 something is different about the render target now, compared to earlier
5592 frames:
5593
5594 \code
5595 QRhiRenderPassDescriptor *rp = m_renderTarget->renderPassDescriptor();
5596 if (m_pipeline && rp->serializedFormat() != m_renderPassFormat) {
5597 m_pipeline->setRenderPassDescriptor(rp);
5598 m_renderPassFormat = rp->serializedFormat();
5599 m_pipeline->create();
5600 }
5601 // remember to store m_renderPassFormat also when creating m_pipeline the first time
5602 \endcode
5603
5604 \sa isCompatible()
5605 */
5606
5607/*!
5608 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
5609 QRhiVulkanRenderPassNativeHandles. The returned value is \nullptr when exposing
5610 the underlying native resources is not supported by the backend.
5611
5612 \sa QRhiVulkanRenderPassNativeHandles
5613 */
5614const QRhiNativeHandles *QRhiRenderPassDescriptor::nativeHandles()
5615{
5616 return nullptr;
5617}
5618
5619/*!
5620 \class QRhiRenderTarget
5621 \inmodule QtGuiPrivate
5622 \inheaderfile rhi/qrhi.h
5623 \since 6.6
5624 \brief Represents an onscreen (swapchain) or offscreen (texture) render target.
5625
5626 Applications do not create an instance of this class directly. Rather, it
5627 is the subclass QRhiTextureRenderTarget that is instantiable by clients of
5628 the API via \l{QRhi::newTextureRenderTarget()}{newTextureRenderTarget()}.
5629 The other subclass is QRhiSwapChainRenderTarget, which is the type
5630 QRhiSwapChain returns when calling
5631 \l{QRhiSwapChain::currentFrameRenderTarget()}{currentFrameRenderTarget()}.
5632
5633 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5634 for details.
5635
5636 \sa QRhiSwapChainRenderTarget, QRhiTextureRenderTarget
5637 */
5638
5639/*!
5640 \internal
5641 */
5642QRhiRenderTarget::QRhiRenderTarget(QRhiImplementation *rhi)
5643 : QRhiResource(rhi)
5644{
5645}
5646
5647/*!
5648 \fn virtual QSize QRhiRenderTarget::pixelSize() const = 0
5649
5650 \return the size in pixels.
5651
5652 Valid only after create() has been called successfully. Until then the
5653 result is a default-constructed QSize.
5654
5655 With QRhiTextureRenderTarget the returned size is the size of the
5656 associated attachments at the time of create(), in practice the size of the
5657 first color attachment, or the depth/stencil buffer if there are no color
5658 attachments. If the associated textures or renderbuffers are resized and
5659 rebuilt afterwards, then pixelSize() performs an implicit call to create()
5660 in order to rebuild the underlying data structures. This implicit check is
5661 similar to what QRhiCommandBuffer::beginPass() does, and ensures that the
5662 returned size is always up-to-date.
5663 */
5664
5665/*!
5666 \fn virtual float QRhiRenderTarget::devicePixelRatio() const = 0
5667
5668 \return the device pixel ratio. For QRhiTextureRenderTarget this is always
5669 1. For targets retrieved from a QRhiSwapChain the value reflects the
5670 \l{QWindow::devicePixelRatio()}{device pixel ratio} of the targeted
5671 QWindow.
5672 */
5673
5674/*!
5675 \fn virtual int QRhiRenderTarget::sampleCount() const = 0
5676
5677 \return the sample count or 1 if multisample antialiasing is not relevant for
5678 this render target.
5679 */
5680
5681/*!
5682 \fn QRhiRenderPassDescriptor *QRhiRenderTarget::renderPassDescriptor() const
5683
5684 \return the associated QRhiRenderPassDescriptor.
5685 */
5686
5687/*!
5688 \fn void QRhiRenderTarget::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
5689
5690 Sets the QRhiRenderPassDescriptor \a desc for use with this render target.
5691 */
5692
5693/*!
5694 \internal
5695 */
5696QRhiSwapChainRenderTarget::QRhiSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain_)
5697 : QRhiRenderTarget(rhi),
5698 m_swapchain(swapchain_)
5699{
5700}
5701
5702/*!
5703 \class QRhiSwapChainRenderTarget
5704 \inmodule QtGuiPrivate
5705 \inheaderfile rhi/qrhi.h
5706 \since 6.6
5707 \brief Swapchain render target resource.
5708
5709 When targeting the color buffers of a swapchain, active render target is a
5710 QRhiSwapChainRenderTarget. This is what
5711 QRhiSwapChain::currentFrameRenderTarget() returns.
5712
5713 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5714 for details.
5715
5716 \sa QRhiSwapChain
5717 */
5718
5719/*!
5720 \return the resource type.
5721 */
5722QRhiResource::Type QRhiSwapChainRenderTarget::resourceType() const
5723{
5724 return SwapChainRenderTarget;
5725}
5726
5727/*!
5728 \fn QRhiSwapChain *QRhiSwapChainRenderTarget::swapChain() const
5729
5730 \return the swapchain object.
5731 */
5732
5733/*!
5734 \class QRhiTextureRenderTarget
5735 \inmodule QtGuiPrivate
5736 \inheaderfile rhi/qrhi.h
5737 \since 6.6
5738 \brief Texture render target resource.
5739
5740 A texture render target allows rendering into one or more textures,
5741 optionally with a depth texture or depth/stencil renderbuffer.
5742
5743 For multisample rendering the common approach is to use a renderbuffer as
5744 the color attachment and set the non-multisample destination texture as the
5745 \c{resolve texture}. For more information, read the detailed description of
5746 the \l QRhiColorAttachment class.
5747
5748 \note Textures used in combination with QRhiTextureRenderTarget must be
5749 created with the QRhiTexture::RenderTarget flag.
5750
5751 The simplest example of creating a render target with a texture as its
5752 single color attachment:
5753
5754 \code
5755 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
5756 texture->create();
5757 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture });
5758 rp = rt->newCompatibleRenderPassDescriptor();
5759 rt->setRenderPassDescriptor(rp);
5760 rt->create();
5761 // rt can now be used with beginPass()
5762 \endcode
5763
5764 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5765 for details.
5766 */
5767
5768/*!
5769 \enum QRhiTextureRenderTarget::Flag
5770
5771 Flag values describing the load/store behavior for the render target. The
5772 load/store behavior may be baked into native resources under the hood,
5773 depending on the backend, and therefore it needs to be known upfront and
5774 cannot be changed without rebuilding (and so releasing and creating new
5775 native resources).
5776
5777 \value PreserveColorContents Indicates that the contents of the color
5778 attachments is to be loaded when starting a render pass, instead of
5779 clearing. This is potentially more expensive, especially on mobile (tiled)
5780 GPUs, but allows preserving the existing contents between passes. When doing
5781 multisample rendering with a resolve texture set, setting this flag also
5782 requests the multisample color data to be stored (written out) to the
5783 multisample texture or render buffer. (for non-multisample rendering the
5784 color data is always stored, but for MSAA storing the multisample data
5785 decreases efficiency for certain GPU architectures, hence defaulting to not
5786 writing it out) Note however that this is non-portable: in some cases there
5787 is no intermediate multisample texture on the graphics API level, e.g. when
5788 using OpenGL ES's \c{GL_EXT_multisampled_render_to_texture} as it is all
5789 implicit, handled by the OpenGL ES implementation. In that case,
5790 PreserveColorContents will likely have no effect. Therefore, avoid relying
5791 on this flag when using multisample rendering and the color attachment is
5792 using a multisample QRhiTexture (not QRhiRenderBuffer).
5793
5794 \value PreserveDepthStencilContents Indicates that the contents of the
5795 depth texture is to be loaded when starting a render pass, instead
5796 clearing. Only applicable when a texture is used as the depth buffer
5797 (QRhiTextureRenderTargetDescription::depthTexture() is set) because
5798 depth/stencil renderbuffers may not have any physical backing and data may
5799 not be written out in the first place.
5800
5801 \value DoNotStoreDepthStencilContents Indicates that the contents of the
5802 depth texture does not need to be written out. Relevant only when a
5803 QRhiTexture, not QRhiRenderBuffer, is used as the depth-stencil buffer,
5804 because for QRhiRenderBuffer this is implicit. When a depthResolveTexture is
5805 set, the flag is not relevant, because the behavior is then as if the flag
5806 was set. This enum value is introduced in Qt 6.8.
5807 */
5808
5809/*!
5810 \internal
5811 */
5812QRhiTextureRenderTarget::QRhiTextureRenderTarget(QRhiImplementation *rhi,
5813 const QRhiTextureRenderTargetDescription &desc_,
5814 Flags flags_)
5815 : QRhiRenderTarget(rhi),
5816 m_desc(desc_),
5817 m_flags(flags_)
5818{
5819}
5820
5821/*!
5822 \return the resource type.
5823 */
5824QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
5825{
5826 return TextureRenderTarget;
5827}
5828
5829/*!
5830 \fn virtual QRhiRenderPassDescriptor *QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() = 0
5831
5832 \return a new QRhiRenderPassDescriptor that is compatible with this render
5833 target.
5834
5835 The returned value is used in two ways: it can be passed to
5836 setRenderPassDescriptor() and
5837 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
5838 describes the attachments (color, depth/stencil) and the load/store
5839 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
5840 be used in combination with a render target that has a
5841 \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
5842 QRhiRenderPassDescriptor set.
5843
5844 Two QRhiTextureRenderTarget instances can share the same render pass
5845 descriptor as long as they have the same number and type of attachments.
5846 The associated QRhiTexture or QRhiRenderBuffer instances are not part of
5847 the render pass descriptor so those can differ in the two
5848 QRhiTextureRenderTarget instances.
5849
5850 \note resources, such as QRhiTexture instances, referenced in description()
5851 must already have create() called on them.
5852
5853 \sa create()
5854 */
5855
5856/*!
5857 \fn virtual bool QRhiTextureRenderTarget::create() = 0
5858
5859 Creates the corresponding native graphics resources. If there are already
5860 resources present due to an earlier create() with no corresponding
5861 destroy(), then destroy() is called implicitly first.
5862
5863 \note renderPassDescriptor() must be set before calling create(). To obtain
5864 a QRhiRenderPassDescriptor compatible with the render target, call
5865 newCompatibleRenderPassDescriptor() before create() but after setting all
5866 other parameters, such as description() and flags(). To save resources,
5867 reuse the same QRhiRenderPassDescriptor with multiple
5868 QRhiTextureRenderTarget instances, whenever possible. Sharing the same
5869 render pass descriptor is only possible when the render targets have the
5870 same number and type of attachments (the actual textures can differ) and
5871 the same flags.
5872
5873 \note resources, such as QRhiTexture instances, referenced in description()
5874 must already have create() called on them.
5875
5876 \return \c true when successful, \c false when a graphics operation failed.
5877 Regardless of the return value, calling destroy() is always safe.
5878 */
5879
5880/*!
5881 \fn QRhiTextureRenderTargetDescription QRhiTextureRenderTarget::description() const
5882 \return the render target description.
5883 */
5884
5885/*!
5886 \fn void QRhiTextureRenderTarget::setDescription(const QRhiTextureRenderTargetDescription &desc)
5887 Sets the render target description \a desc.
5888 */
5889
5890/*!
5891 \fn QRhiTextureRenderTarget::Flags QRhiTextureRenderTarget::flags() const
5892 \return the currently set flags.
5893 */
5894
5895/*!
5896 \fn void QRhiTextureRenderTarget::setFlags(Flags f)
5897 Sets the flags to \a f.
5898 */
5899
5900/*!
5901 \class QRhiShaderResourceBindings
5902 \inmodule QtGuiPrivate
5903 \inheaderfile rhi/qrhi.h
5904 \since 6.6
5905 \brief Encapsulates resources for making buffer, texture, sampler resources visible to shaders.
5906
5907 A QRhiShaderResourceBindings is a collection of QRhiShaderResourceBinding
5908 objects, each of which describe a single binding.
5909
5910 Take a fragment shader with the following interface:
5911
5912 \badcode
5913 layout(std140, binding = 0) uniform buf {
5914 mat4 mvp;
5915 int flip;
5916 } ubuf;
5917
5918 layout(binding = 1) uniform sampler2D tex;
5919 \endcode
5920
5921 To make resources visible to the shader, the following
5922 QRhiShaderResourceBindings could be created and then passed to
5923 QRhiGraphicsPipeline::setShaderResourceBindings():
5924
5925 \code
5926 QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings();
5927 srb->setBindings({
5928 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf),
5929 QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler)
5930 });
5931 srb->create();
5932 // ...
5933 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
5934 // ...
5935 ps->setShaderResourceBindings(srb);
5936 ps->create();
5937 // ...
5938 cb->setGraphicsPipeline(ps);
5939 cb->setShaderResources(); // binds srb
5940 \endcode
5941
5942 This assumes that \c ubuf is a QRhiBuffer, \c texture is a QRhiTexture,
5943 while \a sampler is a QRhiSampler. The example also assumes that the
5944 uniform block is present in the vertex shader as well so the same buffer is
5945 made visible to the vertex stage too.
5946
5947 \section1 Advanced usage
5948
5949 Building on the above example, let's assume that a pass now needs to use
5950 the exact same pipeline and shaders with a different texture. Creating a
5951 whole separate QRhiGraphicsPipeline just for this would be an overkill.
5952 This is why QRhiCommandBuffer::setShaderResources() allows specifying a \a
5953 srb argument. As long as the layouts (so the number of bindings and the
5954 binding points) match between two QRhiShaderResourceBindings, they can both
5955 be used with the same pipeline, assuming the pipeline was created with one of
5956 them in the first place. See isLayoutCompatible() for more details.
5957
5958 \code
5959 QRhiShaderResourceBindings *srb2 = rhi->newShaderResourceBindings();
5960 // ...
5961 cb->setGraphicsPipeline(ps);
5962 cb->setShaderResources(srb2); // binds srb2
5963 \endcode
5964
5965 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5966 for details.
5967 */
5968
5969/*!
5970 \typedef QRhiShaderResourceBindingSet
5971 \relates QRhi
5972 \since 6.7
5973
5974 Synonym for QRhiShaderResourceBindings.
5975*/
5976
5977/*!
5978 \internal
5979 */
5980QRhiShaderResourceBindings::QRhiShaderResourceBindings(QRhiImplementation *rhi)
5981 : QRhiResource(rhi)
5982{
5983 m_layoutDesc.reserve(BINDING_PREALLOC * QRhiShaderResourceBinding::LAYOUT_DESC_ENTRIES_PER_BINDING);
5984}
5985
5986/*!
5987 \return the resource type.
5988 */
5989QRhiResource::Type QRhiShaderResourceBindings::resourceType() const
5990{
5991 return ShaderResourceBindings;
5992}
5993
5994/*!
5995 \return \c true if the layout is compatible with \a other. The layout does
5996 not include the actual resource (such as, buffer or texture) and related
5997 parameters (such as, offset or size). It does include the binding point,
5998 pipeline stage, and resource type, however. The number and order of the
5999 bindings must also match in order to be compatible.
6000
6001 When there is a QRhiGraphicsPipeline created with this
6002 QRhiShaderResourceBindings, and the function returns \c true, \a other can
6003 then safely be passed to QRhiCommandBuffer::setShaderResources(), and so
6004 be used with the pipeline in place of this QRhiShaderResourceBindings.
6005
6006 \note This function must only be called after a successful create(), because
6007 it relies on data generated during the baking of the underlying data
6008 structures. This way the function can implement a comparison approach that
6009 is more efficient than iterating through two binding lists and calling
6010 QRhiShaderResourceBinding::isLayoutCompatible() on each pair. This becomes
6011 relevant especially when this function is called at a high frequency.
6012
6013 \sa serializedLayoutDescription()
6014 */
6015bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBindings *other) const
6016{
6017 if (other == this)
6018 return true;
6019
6020 if (!other)
6021 return false;
6022
6023 // This can become a hot code path. Therefore we do not iterate and call
6024 // isLayoutCompatible() on m_bindings, but rather check a pre-calculated
6025 // hash code and then, if the hash matched, do a uint array comparison
6026 // (that's still more cache friendly).
6027
6028 return m_layoutDescHash == other->m_layoutDescHash
6029 && m_layoutDesc == other->m_layoutDesc;
6030}
6031
6032/*!
6033 \fn QVector<quint32> QRhiShaderResourceBindings::serializedLayoutDescription() const
6034
6035 \return a vector of integers containing an opaque blob describing the layout
6036 of the binding list, i.e. the data relevant for
6037 \l{isLayoutCompatible()}{layout compatibility tests}.
6038
6039 Given two objects \c srb1 and \c srb2, if the data returned from this
6040 function is identical, then \c{srb1->isLayoutCompatible(srb2)}, and vice
6041 versa hold true as well.
6042
6043 \note The returned data is meant to be used for storing in memory and
6044 comparisons during the lifetime of the QRhi the object belongs to. It is not
6045 meant for storing on disk, reusing between processes, or using with multiple
6046 QRhi instances with potentially different backends.
6047
6048 \sa isLayoutCompatible()
6049 */
6050
6051void QRhiImplementation::updateLayoutDesc(QRhiShaderResourceBindings *srb)
6052{
6053 srb->m_layoutDescHash = 0;
6054 srb->m_layoutDesc.clear();
6055 auto layoutDescAppender = std::back_inserter(srb->m_layoutDesc);
6056 for (const QRhiShaderResourceBinding &b : std::as_const(srb->m_bindings)) {
6057 const QRhiShaderResourceBinding::Data *d = &b.d;
6058 srb->m_layoutDescHash ^= uint(d->binding) ^ uint(d->stage) ^ uint(d->type)
6059 ^ uint(d->arraySize());
6060 layoutDescAppender = d->serialize(layoutDescAppender);
6061 }
6062}
6063
6064/*!
6065 \fn virtual bool QRhiShaderResourceBindings::create() = 0
6066
6067 Creates the corresponding resource binding set. Depending on the underlying
6068 graphics API, this may involve creating native graphics resources, and
6069 therefore it should not be assumed that this is a cheap operation.
6070
6071 If create() has been called before with no corresponding destroy(), then
6072 destroy() is called implicitly first.
6073
6074 \return \c true when successful, \c false when failed.
6075 Regardless of the return value, calling destroy() is always safe.
6076 */
6077
6078/*!
6079 \fn void QRhiShaderResourceBindings::setBindings(std::initializer_list<QRhiShaderResourceBinding> list)
6080 Sets the \a list of bindings.
6081 */
6082
6083/*!
6084 \fn template<typename InputIterator> void QRhiShaderResourceBindings::setBindings(InputIterator first, InputIterator last)
6085 Sets the list of bindings from the iterators \a first and \a last.
6086 */
6087
6088/*!
6089 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cbeginBindings() const
6090 \return a const iterator pointing to the first item in the binding list.
6091 */
6092
6093/*!
6094 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cendBindings() const
6095 \return a const iterator pointing just after the last item in the binding list.
6096 */
6097
6098/*!
6099 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::bindingAt(qsizetype index) const
6100 \return the binding at the specified \a index.
6101 */
6102
6103/*!
6104 \fn qsizetype QRhiShaderResourceBindings::bindingCount() const
6105 \return the number of bindings.
6106 */
6107
6108/*!
6109 \class QRhiShaderResourceBinding
6110 \inmodule QtGuiPrivate
6111 \inheaderfile rhi/qrhi.h
6112 \since 6.6
6113 \brief Describes the shader resource for a single binding point.
6114
6115 A QRhiShaderResourceBinding cannot be constructed directly. Instead, use the
6116 static functions such as uniformBuffer() or sampledTexture() to get an
6117 instance.
6118
6119 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
6120 for details.
6121 */
6122
6123/*!
6124 \enum QRhiShaderResourceBinding::Type
6125 Specifies type of the shader resource bound to a binding point
6126
6127 \value UniformBuffer Uniform buffer
6128
6129 \value SampledTexture Combined image sampler (a texture and sampler pair).
6130 Even when the shading language associated with the underlying 3D API has no
6131 support for this concept (e.g. D3D and HLSL), this is still supported
6132 because the shader translation layer takes care of the appropriate
6133 translation and remapping of binding points or shader registers.
6134
6135 \value Texture Texture (separate)
6136
6137 \value Sampler Sampler (separate)
6138
6139 \value ImageLoad Image load (with GLSL this maps to doing imageLoad() on a
6140 single level - and either one or all layers - of a texture exposed to the
6141 shader as an image object)
6142
6143 \value ImageStore Image store (with GLSL this maps to doing imageStore() or
6144 imageAtomic*() on a single level - and either one or all layers - of a
6145 texture exposed to the shader as an image object)
6146
6147 \value ImageLoadStore Image load and store
6148
6149 \value BufferLoad Storage buffer load (with GLSL this maps to reading from
6150 a shader storage buffer)
6151
6152 \value BufferStore Storage buffer store (with GLSL this maps to writing to
6153 a shader storage buffer)
6154
6155 \value BufferLoadStore Storage buffer load and store
6156 */
6157
6158/*!
6159 \enum QRhiShaderResourceBinding::StageFlag
6160 Flag values to indicate which stages the shader resource is visible in
6161
6162 \value VertexStage Vertex stage
6163 \value TessellationControlStage Tessellation control (hull shader) stage
6164 \value TessellationEvaluationStage Tessellation evaluation (domain shader) stage
6165 \value FragmentStage Fragment (pixel shader) stage
6166 \value ComputeStage Compute stage
6167 \value GeometryStage Geometry stage
6168 */
6169
6170/*!
6171 \return \c true if the layout is compatible with \a other. The layout does not
6172 include the actual resource (such as, buffer or texture) and related
6173 parameters (such as, offset or size).
6174
6175 For example, \c a and \c b below are not equal, but are compatible layout-wise:
6176
6177 \code
6178 auto a = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buffer);
6179 auto b = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, someOtherBuffer, 256);
6180 \endcode
6181 */
6182bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBinding &other) const
6183{
6184 // everything that goes into a VkDescriptorSetLayoutBinding must match
6185 return d.binding == other.d.binding
6186 && d.stage == other.d.stage
6187 && d.type == other.d.type
6188 && d.arraySize() == other.d.arraySize();
6189}
6190
6191/*!
6192 \return a shader resource binding for the given binding number, pipeline
6193 stages, and buffer specified by \a binding, \a stage, and \a buf.
6194
6195 \note When \a buf is not null, it must have been created with
6196 QRhiBuffer::UniformBuffer.
6197
6198 \note \a buf can be null. It is valid to create a
6199 QRhiShaderResourceBindings with unspecified resources, but such an object
6200 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6201 suitable for creating pipelines. Such a pipeline must then always be used
6202 together with another, layout compatible QRhiShaderResourceBindings with
6203 resources present passed to QRhiCommandBuffer::setShaderResources().
6204
6205 \note If the size of \a buf exceeds the limit reported for
6206 QRhi::MaxUniformBufferRange, unexpected errors may occur.
6207 */
6208QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
6209 int binding, StageFlags stage, QRhiBuffer *buf)
6210{
6211 QRhiShaderResourceBinding b;
6212 b.d.binding = binding;
6213 b.d.stage = stage;
6214 b.d.type = UniformBuffer;
6215 b.d.u.ubuf.buf = buf;
6216 b.d.u.ubuf.offset = 0;
6217 b.d.u.ubuf.maybeSize = 0; // entire buffer
6218 b.d.u.ubuf.hasDynamicOffset = false;
6219 return b;
6220}
6221
6222/*!
6223 \return a shader resource binding for the given binding number, pipeline
6224 stages, and buffer specified by \a binding, \a stage, and \a buf. This
6225 overload binds a region only, as specified by \a offset and \a size.
6226
6227 \note It is up to the user to ensure the offset is aligned to
6228 QRhi::ubufAlignment().
6229
6230 \note \a size must be greater than 0.
6231
6232 \note When \a buf is not null, it must have been created with
6233 QRhiBuffer::UniformBuffer.
6234
6235 \note \a buf can be null. It is valid to create a
6236 QRhiShaderResourceBindings with unspecified resources, but such an object
6237 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6238 suitable for creating pipelines. Such a pipeline must then always be used
6239 together with another, layout compatible QRhiShaderResourceBindings with
6240 resources present passed to QRhiCommandBuffer::setShaderResources().
6241
6242 \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
6243 unexpected errors may occur.
6244 */
6245QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
6246 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6247{
6248 Q_ASSERT(size > 0);
6249 QRhiShaderResourceBinding b;
6250 b.d.binding = binding;
6251 b.d.stage = stage;
6252 b.d.type = UniformBuffer;
6253 b.d.u.ubuf.buf = buf;
6254 b.d.u.ubuf.offset = offset;
6255 b.d.u.ubuf.maybeSize = size;
6256 b.d.u.ubuf.hasDynamicOffset = false;
6257 return b;
6258}
6259
6260/*!
6261 \return a shader resource binding for the given binding number, pipeline
6262 stages, and buffer specified by \a binding, \a stage, and \a buf. The
6263 uniform buffer is assumed to have dynamic offset. The dynamic offset can be
6264 specified in QRhiCommandBuffer::setShaderResources(), thus allowing using
6265 varying offset values without creating new bindings for the buffer. The
6266 size of the bound region is specified by \a size. Like with non-dynamic
6267 offsets, \c{offset + size} cannot exceed the size of \a buf.
6268
6269 \note When \a buf is not null, it must have been created with
6270 QRhiBuffer::UniformBuffer.
6271
6272 \note \a buf can be null. It is valid to create a
6273 QRhiShaderResourceBindings with unspecified resources, but such an object
6274 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6275 suitable for creating pipelines. Such a pipeline must then always be used
6276 together with another, layout compatible QRhiShaderResourceBindings with
6277 resources present passed to QRhiCommandBuffer::setShaderResources().
6278
6279 \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
6280 unexpected errors may occur.
6281 */
6282QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(
6283 int binding, StageFlags stage, QRhiBuffer *buf, quint32 size)
6284{
6285 Q_ASSERT(size > 0);
6286 QRhiShaderResourceBinding b;
6287 b.d.binding = binding;
6288 b.d.stage = stage;
6289 b.d.type = UniformBuffer;
6290 b.d.u.ubuf.buf = buf;
6291 b.d.u.ubuf.offset = 0;
6292 b.d.u.ubuf.maybeSize = size;
6293 b.d.u.ubuf.hasDynamicOffset = true;
6294 return b;
6295}
6296
6297/*!
6298 \return a shader resource binding for the given binding number, pipeline
6299 stages, texture, and sampler specified by \a binding, \a stage, \a tex,
6300 \a sampler.
6301
6302 \note This function is equivalent to calling sampledTextures() with a
6303 \c count of 1.
6304
6305 \note \a tex and \a sampler can be null. It is valid to create a
6306 QRhiShaderResourceBindings with unspecified resources, but such an object
6307 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6308 suitable for creating pipelines. Such a pipeline must then always be used
6309 together with another, layout compatible QRhiShaderResourceBindings with
6310 resources present passed to QRhiCommandBuffer::setShaderResources().
6311
6312 \note A shader may not be able to consume more than 16 textures/samplers,
6313 depending on the underlying graphics API. This hard limit must be kept in
6314 mind in renderer design. This does not apply to texture arrays which
6315 consume a single binding point (shader register) and can contain 256-2048
6316 textures, depending on the underlying graphics API. Arrays of textures (see
6317 sampledTextures()) are however no different in this regard than using the
6318 same number of individual textures.
6319
6320 \sa sampledTextures()
6321 */
6322QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
6323 int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
6324{
6325 QRhiShaderResourceBinding b;
6326 b.d.binding = binding;
6327 b.d.stage = stage;
6328 b.d.type = SampledTexture;
6329 b.d.stex.texSamplers.resize(1);
6330 b.d.stex.texSamplers[0] = { tex, sampler };
6331 return b;
6332}
6333
6334/*!
6335 \return a shader resource binding for the given binding number, pipeline
6336 stages, and the array of texture-sampler pairs specified by \a binding, \a
6337 stage, \a count, and \a texSamplers.
6338
6339 \note \a count must be at least 1, and not larger than 16.
6340
6341 \note When \a count is 1, this function is equivalent to sampledTexture().
6342
6343 This function is relevant when arrays of combined image samplers are
6344 involved. For example, in GLSL \c{layout(binding = 5) uniform sampler2D
6345 shadowMaps[8];} declares an array of combined image samplers. The
6346 application is then expected provide a QRhiShaderResourceBinding for
6347 binding point 5, set up by calling this function with \a count set to 8 and
6348 a valid texture and sampler for each element of the array.
6349
6350 \warning All elements of the array must be specified. With the above
6351 example, the only valid, portable approach is calling this function with a
6352 \a count of 8. Additionally, all QRhiTexture and QRhiSampler instances must
6353 be valid, meaning nullptr is not an accepted value. This is due to some of
6354 the underlying APIs, such as, Vulkan, that require a valid image and
6355 sampler object for each element in descriptor arrays. Applications are
6356 advised to provide "dummy" samplers and textures if some array elements are
6357 not relevant (due to not being accessed in the shader).
6358
6359 \note \a texSamplers can be null. It is valid to create a
6360 QRhiShaderResourceBindings with unspecified resources, but such an object
6361 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6362 suitable for creating pipelines. Such a pipeline must then always be used
6363 together with another, layout compatible QRhiShaderResourceBindings with
6364 resources present passed to QRhiCommandBuffer::setShaderResources().
6365
6366 \sa sampledTexture()
6367 */
6368QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTextures(
6369 int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers)
6370{
6371 Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
6372 QRhiShaderResourceBinding b;
6373 b.d.binding = binding;
6374 b.d.stage = stage;
6375 b.d.type = SampledTexture;
6376 b.d.stex.texSamplers.resize(count);
6377 for (int i = 0; i < count; ++i) {
6378 if (texSamplers)
6379 b.d.stex.texSamplers[i] = texSamplers[i];
6380 else
6381 b.d.stex.texSamplers[i] = { nullptr, nullptr };
6382 }
6383 return b;
6384}
6385
6386/*!
6387 \return a shader resource binding for the given binding number, pipeline
6388 stages, and texture specified by \a binding, \a stage, \a tex.
6389
6390 \note This function is equivalent to calling textures() with a
6391 \c count of 1.
6392
6393 \note \a tex can be null. It is valid to create a
6394 QRhiShaderResourceBindings with unspecified resources, but such an object
6395 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6396 suitable for creating pipelines. Such a pipeline must then always be used
6397 together with another, layout compatible QRhiShaderResourceBindings with
6398 resources present passed to QRhiCommandBuffer::setShaderResources().
6399
6400 This creates a binding for a separate texture (image) object, whereas
6401 sampledTexture() is suitable for combined image samplers. In
6402 Vulkan-compatible GLSL code separate textures are declared as \c texture2D
6403 as opposed to \c sampler2D: \c{layout(binding = 1) uniform texture2D tex;}
6404
6405 \note A shader may not be able to consume more than 16 textures, depending
6406 on the underlying graphics API. This hard limit must be kept in mind in
6407 renderer design. This does not apply to texture arrays which consume a
6408 single binding point (shader register) and can contain 256-2048 textures,
6409 depending on the underlying graphics API. Arrays of textures (see
6410 sampledTextures()) are however no different in this regard than using the
6411 same number of individual textures.
6412
6413 \sa textures(), sampler()
6414 */
6415QRhiShaderResourceBinding QRhiShaderResourceBinding::texture(int binding, StageFlags stage, QRhiTexture *tex)
6416{
6417 QRhiShaderResourceBinding b;
6418 b.d.binding = binding;
6419 b.d.stage = stage;
6420 b.d.type = Texture;
6421 b.d.stex.texSamplers.resize(1);
6422 b.d.stex.texSamplers[0] = { tex, nullptr };
6423 return b;
6424}
6425
6426/*!
6427 \return a shader resource binding for the given binding number, pipeline
6428 stages, and the array of (separate) textures specified by \a binding, \a
6429 stage, \a count, and \a tex.
6430
6431 \note \a count must be at least 1, and not larger than 16.
6432
6433 \note When \a count is 1, this function is equivalent to texture().
6434
6435 \warning All elements of the array must be specified.
6436
6437 \note \a tex can be null. It is valid to create a
6438 QRhiShaderResourceBindings with unspecified resources, but such an object
6439 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6440 suitable for creating pipelines. Such a pipeline must then always be used
6441 together with another, layout compatible QRhiShaderResourceBindings with
6442 resources present passed to QRhiCommandBuffer::setShaderResources().
6443
6444 \sa texture(), sampler()
6445 */
6446QRhiShaderResourceBinding QRhiShaderResourceBinding::textures(int binding, StageFlags stage, int count, QRhiTexture **tex)
6447{
6448 Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
6449 QRhiShaderResourceBinding b;
6450 b.d.binding = binding;
6451 b.d.stage = stage;
6452 b.d.type = Texture;
6453 b.d.stex.texSamplers.resize(count);
6454 for (int i = 0; i < count; ++i) {
6455 if (tex)
6456 b.d.stex.texSamplers[i] = { tex[i], nullptr };
6457 else
6458 b.d.stex.texSamplers[i] = { nullptr, nullptr };
6459 }
6460 return b;
6461}
6462
6463/*!
6464 \return a shader resource binding for the given binding number, pipeline
6465 stages, and sampler specified by \a binding, \a stage, \a sampler.
6466
6467 \note \a sampler can be null. It is valid to create a
6468 QRhiShaderResourceBindings with unspecified resources, but such an object
6469 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6470 suitable for creating pipelines. Such a pipeline must then always be used
6471 together with another, layout compatible QRhiShaderResourceBindings with
6472 resources present passed to QRhiCommandBuffer::setShaderResources().
6473
6474 Arrays of separate samplers are not supported.
6475
6476 This creates a binding for a separate sampler object, whereas
6477 sampledTexture() is suitable for combined image samplers. In
6478 Vulkan-compatible GLSL code separate samplers are declared as \c sampler
6479 as opposed to \c sampler2D: \c{layout(binding = 2) uniform sampler samp;}
6480
6481 With both a \c texture2D and \c sampler present, they can be used together
6482 to sample the texture: \c{fragColor = texture(sampler2D(tex, samp),
6483 texcoord);}.
6484
6485 \note A shader may not be able to consume more than 16 samplers, depending
6486 on the underlying graphics API. This hard limit must be kept in mind in
6487 renderer design.
6488
6489 \sa texture()
6490 */
6491QRhiShaderResourceBinding QRhiShaderResourceBinding::sampler(int binding, StageFlags stage, QRhiSampler *sampler)
6492{
6493 QRhiShaderResourceBinding b;
6494 b.d.binding = binding;
6495 b.d.stage = stage;
6496 b.d.type = Sampler;
6497 b.d.stex.texSamplers.resize(1);
6498 b.d.stex.texSamplers[0] = { nullptr, sampler };
6499 return b;
6500}
6501
6502/*!
6503 \return a shader resource binding for a read-only storage image with the
6504 given \a binding number and pipeline \a stage. The image load operations
6505 will have access to all layers of the specified \a level. (so if the texture
6506 is a cubemap, the shader must use imageCube instead of image2D)
6507
6508 \note When \a tex is not null, it must have been created with
6509 QRhiTexture::UsedWithLoadStore.
6510
6511 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6512 with unspecified resources, but such an object cannot be used with
6513 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6514 pipelines. Such a pipeline must then always be used together with another,
6515 layout compatible QRhiShaderResourceBindings with resources present passed
6516 to QRhiCommandBuffer::setShaderResources().
6517
6518 \note Image load/store is only available within the compute and fragment stages.
6519 */
6520QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoad(
6521 int binding, StageFlags stage, QRhiTexture *tex, int level)
6522{
6523 QRhiShaderResourceBinding b;
6524 b.d.binding = binding;
6525 b.d.stage = stage;
6526 b.d.type = ImageLoad;
6527 b.d.u.simage.tex = tex;
6528 b.d.u.simage.level = level;
6529 return b;
6530}
6531
6532/*!
6533 \return a shader resource binding for a write-only storage image with the
6534 given \a binding number and pipeline \a stage. The image store operations
6535 will have access to all layers of the specified \a level. (so if the texture
6536 is a cubemap, the shader must use imageCube instead of image2D)
6537
6538 \note When \a tex is not null, it must have been created with
6539 QRhiTexture::UsedWithLoadStore.
6540
6541 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6542 with unspecified resources, but such an object cannot be used with
6543 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6544 pipelines. Such a pipeline must then always be used together with another,
6545 layout compatible QRhiShaderResourceBindings with resources present passed
6546 to QRhiCommandBuffer::setShaderResources().
6547
6548 \note Image load/store is only available within the compute and fragment stages.
6549 */
6550QRhiShaderResourceBinding QRhiShaderResourceBinding::imageStore(
6551 int binding, StageFlags stage, QRhiTexture *tex, int level)
6552{
6553 QRhiShaderResourceBinding b;
6554 b.d.binding = binding;
6555 b.d.stage = stage;
6556 b.d.type = ImageStore;
6557 b.d.u.simage.tex = tex;
6558 b.d.u.simage.level = level;
6559 return b;
6560}
6561
6562/*!
6563 \return a shader resource binding for a read/write storage image with the
6564 given \a binding number and pipeline \a stage. The image load/store operations
6565 will have access to all layers of the specified \a level. (so if the texture
6566 is a cubemap, the shader must use imageCube instead of image2D)
6567
6568 \note When \a tex is not null, it must have been created with
6569 QRhiTexture::UsedWithLoadStore.
6570
6571 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6572 with unspecified resources, but such an object cannot be used with
6573 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6574 pipelines. Such a pipeline must then always be used together with another,
6575 layout compatible QRhiShaderResourceBindings with resources present passed
6576 to QRhiCommandBuffer::setShaderResources().
6577
6578 \note Image load/store is only available within the compute and fragment stages.
6579 */
6580QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoadStore(
6581 int binding, StageFlags stage, QRhiTexture *tex, int level)
6582{
6583 QRhiShaderResourceBinding b;
6584 b.d.binding = binding;
6585 b.d.stage = stage;
6586 b.d.type = ImageLoadStore;
6587 b.d.u.simage.tex = tex;
6588 b.d.u.simage.level = level;
6589 return b;
6590}
6591
6592/*!
6593 \return a shader resource binding for a read-only storage buffer with the
6594 given \a binding number and pipeline \a stage.
6595
6596 \note When \a buf is not null, must have been created with
6597 QRhiBuffer::StorageBuffer.
6598
6599 \note \a buf can be null. It is valid to create a
6600 QRhiShaderResourceBindings with unspecified resources, but such an object
6601 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6602 suitable for creating pipelines. Such a pipeline must then always be used
6603 together with another, layout compatible QRhiShaderResourceBindings with
6604 resources present passed to QRhiCommandBuffer::setShaderResources().
6605
6606 \note Buffer load/store is only guaranteed to be available within a compute
6607 pipeline. While some backends may support using these resources in a
6608 graphics pipeline as well, this is not universally supported, and even when
6609 it is, unexpected problems may arise when it comes to barriers and
6610 synchronization. Therefore, avoid using such resources with shaders other
6611 than compute.
6612 */
6613QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6614 int binding, StageFlags stage, QRhiBuffer *buf)
6615{
6616 QRhiShaderResourceBinding b;
6617 b.d.binding = binding;
6618 b.d.stage = stage;
6619 b.d.type = BufferLoad;
6620 b.d.u.sbuf.buf = buf;
6621 b.d.u.sbuf.offset = 0;
6622 b.d.u.sbuf.maybeSize = 0; // entire buffer
6623 return b;
6624}
6625
6626/*!
6627 \return a shader resource binding for a read-only storage buffer with the
6628 given \a binding number and pipeline \a stage. This overload binds a region
6629 only, as specified by \a offset and \a size.
6630
6631 \note When \a buf is not null, must have been created with
6632 QRhiBuffer::StorageBuffer.
6633
6634 \note \a buf can be null. It is valid to create a
6635 QRhiShaderResourceBindings with unspecified resources, but such an object
6636 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6637 suitable for creating pipelines. Such a pipeline must then always be used
6638 together with another, layout compatible QRhiShaderResourceBindings with
6639 resources present passed to QRhiCommandBuffer::setShaderResources().
6640
6641 \note Buffer load/store is only guaranteed to be available within a compute
6642 pipeline. While some backends may support using these resources in a
6643 graphics pipeline as well, this is not universally supported, and even when
6644 it is, unexpected problems may arise when it comes to barriers and
6645 synchronization. Therefore, avoid using such resources with shaders other
6646 than compute.
6647 */
6648QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6649 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6650{
6651 Q_ASSERT(size > 0);
6652 QRhiShaderResourceBinding b;
6653 b.d.binding = binding;
6654 b.d.stage = stage;
6655 b.d.type = BufferLoad;
6656 b.d.u.sbuf.buf = buf;
6657 b.d.u.sbuf.offset = offset;
6658 b.d.u.sbuf.maybeSize = size;
6659 return b;
6660}
6661
6662/*!
6663 \return a shader resource binding for a write-only storage buffer with the
6664 given \a binding number and pipeline \a stage.
6665
6666 \note When \a buf is not null, must have been created with
6667 QRhiBuffer::StorageBuffer.
6668
6669 \note \a buf can be null. It is valid to create a
6670 QRhiShaderResourceBindings with unspecified resources, but such an object
6671 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6672 suitable for creating pipelines. Such a pipeline must then always be used
6673 together with another, layout compatible QRhiShaderResourceBindings with
6674 resources present passed to QRhiCommandBuffer::setShaderResources().
6675
6676 \note Buffer load/store is only guaranteed to be available within a compute
6677 pipeline. While some backends may support using these resources in a
6678 graphics pipeline as well, this is not universally supported, and even when
6679 it is, unexpected problems may arise when it comes to barriers and
6680 synchronization. Therefore, avoid using such resources with shaders other
6681 than compute.
6682 */
6683QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6684 int binding, StageFlags stage, QRhiBuffer *buf)
6685{
6686 QRhiShaderResourceBinding b;
6687 b.d.binding = binding;
6688 b.d.stage = stage;
6689 b.d.type = BufferStore;
6690 b.d.u.sbuf.buf = buf;
6691 b.d.u.sbuf.offset = 0;
6692 b.d.u.sbuf.maybeSize = 0; // entire buffer
6693 return b;
6694}
6695
6696/*!
6697 \return a shader resource binding for a write-only storage buffer with the
6698 given \a binding number and pipeline \a stage. This overload binds a region
6699 only, as specified by \a offset and \a size.
6700
6701 \note When \a buf is not null, must have been created with
6702 QRhiBuffer::StorageBuffer.
6703
6704 \note \a buf can be null. It is valid to create a
6705 QRhiShaderResourceBindings with unspecified resources, but such an object
6706 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6707 suitable for creating pipelines. Such a pipeline must then always be used
6708 together with another, layout compatible QRhiShaderResourceBindings with
6709 resources present passed to QRhiCommandBuffer::setShaderResources().
6710
6711 \note Buffer load/store is only guaranteed to be available within a compute
6712 pipeline. While some backends may support using these resources in a
6713 graphics pipeline as well, this is not universally supported, and even when
6714 it is, unexpected problems may arise when it comes to barriers and
6715 synchronization. Therefore, avoid using such resources with shaders other
6716 than compute.
6717 */
6718QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6719 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6720{
6721 Q_ASSERT(size > 0);
6722 QRhiShaderResourceBinding b;
6723 b.d.binding = binding;
6724 b.d.stage = stage;
6725 b.d.type = BufferStore;
6726 b.d.u.sbuf.buf = buf;
6727 b.d.u.sbuf.offset = offset;
6728 b.d.u.sbuf.maybeSize = size;
6729 return b;
6730}
6731
6732/*!
6733 \return a shader resource binding for a read-write storage buffer with the
6734 given \a binding number and pipeline \a stage.
6735
6736 \note When \a buf is not null, must have been created with
6737 QRhiBuffer::StorageBuffer.
6738
6739 \note \a buf can be null. It is valid to create a
6740 QRhiShaderResourceBindings with unspecified resources, but such an object
6741 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6742 suitable for creating pipelines. Such a pipeline must then always be used
6743 together with another, layout compatible QRhiShaderResourceBindings with
6744 resources present passed to QRhiCommandBuffer::setShaderResources().
6745
6746 \note Buffer load/store is only guaranteed to be available within a compute
6747 pipeline. While some backends may support using these resources in a
6748 graphics pipeline as well, this is not universally supported, and even when
6749 it is, unexpected problems may arise when it comes to barriers and
6750 synchronization. Therefore, avoid using such resources with shaders other
6751 than compute.
6752 */
6753QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6754 int binding, StageFlags stage, QRhiBuffer *buf)
6755{
6756 QRhiShaderResourceBinding b;
6757 b.d.binding = binding;
6758 b.d.stage = stage;
6759 b.d.type = BufferLoadStore;
6760 b.d.u.sbuf.buf = buf;
6761 b.d.u.sbuf.offset = 0;
6762 b.d.u.sbuf.maybeSize = 0; // entire buffer
6763 return b;
6764}
6765
6766/*!
6767 \return a shader resource binding for a read-write storage buffer with the
6768 given \a binding number and pipeline \a stage. This overload binds a region
6769 only, as specified by \a offset and \a size.
6770
6771 \note When \a buf is not null, must have been created with
6772 QRhiBuffer::StorageBuffer.
6773
6774 \note \a buf can be null. It is valid to create a
6775 QRhiShaderResourceBindings with unspecified resources, but such an object
6776 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6777 suitable for creating pipelines. Such a pipeline must then always be used
6778 together with another, layout compatible QRhiShaderResourceBindings with
6779 resources present passed to QRhiCommandBuffer::setShaderResources().
6780
6781 \note Buffer load/store is only guaranteed to be available within a compute
6782 pipeline. While some backends may support using these resources in a
6783 graphics pipeline as well, this is not universally supported, and even when
6784 it is, unexpected problems may arise when it comes to barriers and
6785 synchronization. Therefore, avoid using such resources with shaders other
6786 than compute.
6787 */
6788QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6789 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6790{
6791 Q_ASSERT(size > 0);
6792 QRhiShaderResourceBinding b;
6793 b.d.binding = binding;
6794 b.d.stage = stage;
6795 b.d.type = BufferLoadStore;
6796 b.d.u.sbuf.buf = buf;
6797 b.d.u.sbuf.offset = offset;
6798 b.d.u.sbuf.maybeSize = size;
6799 return b;
6800}
6801
6802/*!
6803 \return \c true if the contents of the two QRhiShaderResourceBinding
6804 objects \a a and \a b are equal. This includes the resources (buffer,
6805 texture) and related parameters (offset, size) as well. To only compare
6806 layouts (binding point, pipeline stage, resource type), use
6807 \l{QRhiShaderResourceBinding::isLayoutCompatible()}{isLayoutCompatible()}
6808 instead.
6809
6810 \relates QRhiShaderResourceBinding
6811 */
6812bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6813{
6814 const QRhiShaderResourceBinding::Data *da = QRhiImplementation::shaderResourceBindingData(a);
6815 const QRhiShaderResourceBinding::Data *db = QRhiImplementation::shaderResourceBindingData(b);
6816
6817 if (da == db)
6818 return true;
6819
6820
6821 if (da->binding != db->binding
6822 || da->stage != db->stage
6823 || da->type != db->type)
6824 {
6825 return false;
6826 }
6827
6828 switch (da->type) {
6829 case QRhiShaderResourceBinding::UniformBuffer:
6830 if (da->u.ubuf.buf != db->u.ubuf.buf
6831 || da->u.ubuf.offset != db->u.ubuf.offset
6832 || da->u.ubuf.maybeSize != db->u.ubuf.maybeSize)
6833 {
6834 return false;
6835 }
6836 break;
6837 case QRhiShaderResourceBinding::SampledTexture:
6838 if (da->stex.count() != db->stex.count())
6839 return false;
6840 for (int i = 0; i < da->stex.count(); ++i) {
6841 if (da->stex.texSamplers[i].tex != db->stex.texSamplers[i].tex
6842 || da->stex.texSamplers[i].sampler != db->stex.texSamplers[i].sampler)
6843 {
6844 return false;
6845 }
6846 }
6847 break;
6848 case QRhiShaderResourceBinding::Texture:
6849 if (da->stex.count() != db->stex.count())
6850 return false;
6851 for (int i = 0; i < da->stex.count(); ++i) {
6852 if (da->stex.texSamplers[i].tex != db->stex.texSamplers[i].tex)
6853 return false;
6854 }
6855 break;
6856 case QRhiShaderResourceBinding::Sampler:
6857 if (da->stex.texSamplers[0].sampler != db->stex.texSamplers[0].sampler)
6858 return false;
6859 break;
6860 case QRhiShaderResourceBinding::ImageLoad:
6861 case QRhiShaderResourceBinding::ImageStore:
6862 case QRhiShaderResourceBinding::ImageLoadStore:
6863 if (da->u.simage.tex != db->u.simage.tex
6864 || da->u.simage.level != db->u.simage.level)
6865 {
6866 return false;
6867 }
6868 break;
6869 case QRhiShaderResourceBinding::BufferLoad:
6870 case QRhiShaderResourceBinding::BufferStore:
6871 case QRhiShaderResourceBinding::BufferLoadStore:
6872 if (da->u.sbuf.buf != db->u.sbuf.buf
6873 || da->u.sbuf.offset != db->u.sbuf.offset
6874 || da->u.sbuf.maybeSize != db->u.sbuf.maybeSize)
6875 {
6876 return false;
6877 }
6878 break;
6879 default:
6880 Q_UNREACHABLE_RETURN(false);
6881 }
6882
6883 return true;
6884}
6885
6886/*!
6887 \return \c false if all the bindings in the two QRhiShaderResourceBinding
6888 objects \a a and \a b are equal; otherwise returns \c true.
6889
6890 \relates QRhiShaderResourceBinding
6891 */
6892bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6893{
6894 return !(a == b);
6895}
6896
6897/*!
6898 \fn size_t qHash(const QRhiShaderResourceBinding &key, size_t seed)
6899 \qhashold{QRhiShaderResourceBinding}
6900 */
6901size_t qHash(const QRhiShaderResourceBinding &b, size_t seed) noexcept
6902{
6903 const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6904 QtPrivate::QHashCombineWithSeed hash(seed);
6905 seed = hash(seed, d->binding);
6906 seed = hash(seed, d->stage);
6907 seed = hash(seed, d->type);
6908 switch (d->type) {
6909 case QRhiShaderResourceBinding::UniformBuffer:
6910 seed = hash(seed, reinterpret_cast<quintptr>(d->u.ubuf.buf));
6911 break;
6912 case QRhiShaderResourceBinding::SampledTexture:
6913 seed = hash(seed, reinterpret_cast<quintptr>(d->stex.texSamplers[0].tex));
6914 seed = hash(seed, reinterpret_cast<quintptr>(d->stex.texSamplers[0].sampler));
6915 break;
6916 case QRhiShaderResourceBinding::Texture:
6917 seed = hash(seed, reinterpret_cast<quintptr>(d->stex.texSamplers[0].tex));
6918 break;
6919 case QRhiShaderResourceBinding::Sampler:
6920 seed = hash(seed, reinterpret_cast<quintptr>(d->stex.texSamplers[0].sampler));
6921 break;
6922 case QRhiShaderResourceBinding::ImageLoad:
6923 case QRhiShaderResourceBinding::ImageStore:
6924 case QRhiShaderResourceBinding::ImageLoadStore:
6925 seed = hash(seed, reinterpret_cast<quintptr>(d->u.simage.tex));
6926 break;
6927 case QRhiShaderResourceBinding::BufferLoad:
6928 case QRhiShaderResourceBinding::BufferStore:
6929 case QRhiShaderResourceBinding::BufferLoadStore:
6930 seed = hash(seed, reinterpret_cast<quintptr>(d->u.sbuf.buf));
6931 break;
6932 }
6933 return seed;
6934}
6935
6936#ifndef QT_NO_DEBUG_STREAM
6937QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
6938{
6939 QDebugStateSaver saver(dbg);
6940 const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6941 dbg.nospace() << "QRhiShaderResourceBinding("
6942 << "binding=" << d->binding
6943 << " stage=" << d->stage
6944 << " type=" << d->type;
6945 switch (d->type) {
6946 case QRhiShaderResourceBinding::UniformBuffer:
6947 dbg.nospace() << " UniformBuffer("
6948 << "buffer=" << d->u.ubuf.buf
6949 << " offset=" << d->u.ubuf.offset
6950 << " maybeSize=" << d->u.ubuf.maybeSize
6951 << ')';
6952 break;
6953 case QRhiShaderResourceBinding::SampledTexture:
6954 dbg.nospace() << " SampledTextures("
6955 << "count=" << d->stex.count();
6956 for (int i = 0; i < d->stex.count(); ++i) {
6957 dbg.nospace() << " texture=" << d->stex.texSamplers[i].tex
6958 << " sampler=" << d->stex.texSamplers[i].sampler;
6959 }
6960 dbg.nospace() << ')';
6961 break;
6962 case QRhiShaderResourceBinding::Texture:
6963 dbg.nospace() << " Textures("
6964 << "count=" << d->stex.count();
6965 for (int i = 0; i < d->stex.count(); ++i)
6966 dbg.nospace() << " texture=" << d->stex.texSamplers[i].tex;
6967 dbg.nospace() << ')';
6968 break;
6969 case QRhiShaderResourceBinding::Sampler:
6970 dbg.nospace() << " Sampler("
6971 << " sampler=" << d->stex.texSamplers[0].sampler
6972 << ')';
6973 break;
6974 case QRhiShaderResourceBinding::ImageLoad:
6975 dbg.nospace() << " ImageLoad("
6976 << "texture=" << d->u.simage.tex
6977 << " level=" << d->u.simage.level
6978 << ')';
6979 break;
6980 case QRhiShaderResourceBinding::ImageStore:
6981 dbg.nospace() << " ImageStore("
6982 << "texture=" << d->u.simage.tex
6983 << " level=" << d->u.simage.level
6984 << ')';
6985 break;
6986 case QRhiShaderResourceBinding::ImageLoadStore:
6987 dbg.nospace() << " ImageLoadStore("
6988 << "texture=" << d->u.simage.tex
6989 << " level=" << d->u.simage.level
6990 << ')';
6991 break;
6992 case QRhiShaderResourceBinding::BufferLoad:
6993 dbg.nospace() << " BufferLoad("
6994 << "buffer=" << d->u.sbuf.buf
6995 << " offset=" << d->u.sbuf.offset
6996 << " maybeSize=" << d->u.sbuf.maybeSize
6997 << ')';
6998 break;
6999 case QRhiShaderResourceBinding::BufferStore:
7000 dbg.nospace() << " BufferStore("
7001 << "buffer=" << d->u.sbuf.buf
7002 << " offset=" << d->u.sbuf.offset
7003 << " maybeSize=" << d->u.sbuf.maybeSize
7004 << ')';
7005 break;
7006 case QRhiShaderResourceBinding::BufferLoadStore:
7007 dbg.nospace() << " BufferLoadStore("
7008 << "buffer=" << d->u.sbuf.buf
7009 << " offset=" << d->u.sbuf.offset
7010 << " maybeSize=" << d->u.sbuf.maybeSize
7011 << ')';
7012 break;
7013 default:
7014 dbg.nospace() << " UNKNOWN()";
7015 break;
7016 }
7017 dbg.nospace() << ')';
7018 return dbg;
7019}
7020#endif
7021
7022#ifndef QT_NO_DEBUG_STREAM
7023QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
7024{
7025 QDebugStateSaver saver(dbg);
7026 dbg.nospace() << "QRhiShaderResourceBindings("
7027 << srb.m_bindings
7028 << ')';
7029 return dbg;
7030}
7031#endif
7032
7033/*!
7034 \class QRhiGraphicsPipeline
7035 \inmodule QtGuiPrivate
7036 \inheaderfile rhi/qrhi.h
7037 \since 6.6
7038 \brief Graphics pipeline state resource.
7039
7040 Represents a graphics pipeline. What exactly this map to in the underlying
7041 native graphics API, varies. Where there is a concept of pipeline objects,
7042 for example with Vulkan, the QRhi backend will create such an object upon
7043 calling create(). Elsewhere, for example with OpenGL, the
7044 QRhiGraphicsPipeline may merely collect the various state, and create()'s
7045 main task is to set up the corresponding shader program, but deferring
7046 looking at any of the requested state to a later point.
7047
7048 As with all QRhiResource subclasses, the two-phased initialization pattern
7049 applies: setting any values via the setters, for example setDepthTest(), is
7050 only effective after calling create(). Avoid changing any values once the
7051 QRhiGraphicsPipeline has been initialized via create(). To change some
7052 state, set the new value and call create() again. However, that will
7053 effectively release all underlying native resources and create new ones. As
7054 a result, it may be a heavy, expensive operation. Rather, prefer creating
7055 multiple pipelines with the different states, and
7056 \l{QRhiCommandBuffer::setGraphicsPipeline()}{switch between them} when
7057 recording the render pass.
7058
7059 \note Setting the shader stages is mandatory. There must be at least one
7060 stage, and there must be a vertex stage.
7061
7062 \note Setting the shader resource bindings is mandatory. The referenced
7063 QRhiShaderResourceBindings must already have create() called on it by the
7064 time create() is called. Associating with a QRhiShaderResourceBindings that
7065 has no bindings is also valid, as long as no shader in any stage expects any
7066 resources. Using a QRhiShaderResourceBindings object that does not specify
7067 any actual resources (i.e., the buffers, textures, etc. for the binding
7068 points are set to \nullptr) is valid as well, as long as a
7069 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
7070 QRhiShaderResourceBindings, that specifies resources for all the bindings,
7071 is going to be set via
7072 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} when
7073 recording the render pass.
7074
7075 \note Setting the render pass descriptor is mandatory. To obtain a
7076 QRhiRenderPassDescriptor that can be passed to setRenderPassDescriptor(),
7077 use either QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() or
7078 QRhiSwapChain::newCompatibleRenderPassDescriptor().
7079
7080 \note Setting the vertex input layout is mandatory.
7081
7082 \note sampleCount() defaults to 1 and must match the sample count of the
7083 render target's color and depth stencil attachments.
7084
7085 \note The depth test, depth write, and stencil test are disabled by
7086 default. The face culling mode defaults to no culling.
7087
7088 \note stencilReadMask() and stencilWriteMask() apply to both faces. They
7089 both default to 0xFF.
7090
7091 \section1 Example usage
7092
7093 All settings of a graphics pipeline have defaults which might be suitable
7094 to many applications. Therefore a minimal example of creating a graphics
7095 pipeline could be the following. This assumes that the vertex shader takes
7096 a single \c{vec3 position} input at the input location 0. With the
7097 QRhiShaderResourceBindings and QRhiRenderPassDescriptor objects, plus the
7098 QShader collections for the vertex and fragment stages, a pipeline could be
7099 created like this:
7100
7101 \code
7102 QRhiShaderResourceBindings *srb;
7103 QRhiRenderPassDescriptor *rpDesc;
7104 QShader vs, fs;
7105 // ...
7106
7107 QRhiVertexInputLayout inputLayout;
7108 inputLayout.setBindings({ { 3 * sizeof(float) } });
7109 inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float3, 0 } });
7110
7111 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
7112 ps->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
7113 ps->setVertexInputLayout(inputLayout);
7114 ps->setShaderResourceBindings(srb);
7115 ps->setRenderPassDescriptor(rpDesc);
7116 if (!ps->create()) { error(); }
7117 \endcode
7118
7119 The above code creates a pipeline object that uses the defaults for many
7120 settings and states. For example, it will use a \l Triangles topology, no
7121 backface culling, blending is disabled but color write is enabled for all
7122 four channels, depth test/write are disabled, stencil operations are
7123 disabled.
7124
7125 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7126 for details.
7127
7128 \sa QRhiCommandBuffer, QRhi
7129 */
7130
7131/*!
7132 \enum QRhiGraphicsPipeline::Flag
7133
7134 Flag values for describing the dynamic state of the pipeline, and other
7135 options. The viewport is always dynamic.
7136
7137 \value UsesBlendConstants Indicates that a blend color constant will be set
7138 via QRhiCommandBuffer::setBlendConstants()
7139
7140 \value UsesStencilRef Indicates that a stencil reference value will be set
7141 via QRhiCommandBuffer::setStencilRef()
7142
7143 \value UsesScissor Indicates that a scissor rectangle will be set via
7144 QRhiCommandBuffer::setScissor()
7145
7146 \value CompileShadersWithDebugInfo Requests compiling shaders with debug
7147 information enabled. This is relevant only when runtime shader compilation
7148 from source code is involved, and only when the underlying infrastructure
7149 supports this. With concrete examples, this is not relevant with Vulkan and
7150 SPIR-V, because the GLSL-to-SPIR-V compilation does not happen at run
7151 time. On the other hand, consider Direct3D and HLSL, where there are
7152 multiple options: when the QShader packages ship with pre-compiled bytecode
7153 (\c DXBC), debug information is to be requested through the tool that
7154 generates the \c{.qsb} file, similarly to the case of Vulkan and
7155 SPIR-V. However, when having HLSL source code in the pre- or
7156 runtime-generated QShader packages, the first phase of compilation (HLSL
7157 source to intermediate format) happens at run time too, with this flag taken
7158 into account. Debug information is relevant in particular with tools like
7159 RenderDoc since it allows seeing the original source code when investigating
7160 the pipeline and when performing vertex or fragment shader debugging.
7161
7162 \value UsesShadingRate Indicates that a per-draw (per-pipeline) shading rate
7163 value will be set via QRhiCommandBuffer::setShadingRate(). Not specifying
7164 this flag and still calling setShadingRate() may lead to varying, unexpected
7165 results depending on the underlying graphics API.
7166
7167 \value [since 6.12] UsesIndirectDraws Indicates that this pipeline will be used with
7168 indirect draw calls (QRhiCommandBuffer::drawIndirect() or
7169 QRhiCommandBuffer::drawIndexedIndirect()). Setting this flag allows the
7170 Metal backend to use Indirect Command Buffers (ICB) for GPU-driven
7171 rendering, which significantly reduces CPU overhead for large draw counts.
7172 Not setting this flag when using indirect draws is still functional but may
7173 result in less optimal performance on Metal: QRhi::DrawIndirectMulti reports
7174 what the device can do, without knowing about individual pipelines, so a
7175 pipeline without this flag falls back to CPU-side looping even when that
7176 feature is reported as supported. The exception is
7177 QRhiCommandBuffer::drawIndirectCount() and
7178 QRhiCommandBuffer::drawIndexedIndirectCount(), for which the flag is
7179 mandatory on Metal because there is no non-ICB implementation of those. This
7180 flag has no effect on other backends.
7181 */
7182
7183/*!
7184 \enum QRhiGraphicsPipeline::Topology
7185 Specifies the primitive topology
7186
7187 \value Triangles (default)
7188 \value TriangleStrip
7189 \value TriangleFan (only available if QRhi::TriangleFanTopology is supported)
7190 \value Lines
7191 \value LineStrip
7192 \value Points
7193
7194 \value Patches (only available if QRhi::Tessellation is supported, and
7195 requires the tessellation stages to be present in the pipeline)
7196 */
7197
7198/*!
7199 \enum QRhiGraphicsPipeline::CullMode
7200 Specifies the culling mode
7201
7202 \value None No culling (default)
7203 \value Front Cull front faces
7204 \value Back Cull back faces
7205 */
7206
7207/*!
7208 \enum QRhiGraphicsPipeline::FrontFace
7209 Specifies the front face winding order
7210
7211 \value CCW Counter clockwise (default)
7212 \value CW Clockwise
7213 */
7214
7215/*!
7216 \enum QRhiGraphicsPipeline::ColorMaskComponent
7217 Flag values for specifying the color write mask
7218
7219 \value R
7220 \value G
7221 \value B
7222 \value A
7223 */
7224
7225/*!
7226 \enum QRhiGraphicsPipeline::BlendFactor
7227 Specifies the blend factor
7228
7229 \value Zero
7230 \value One
7231 \value SrcColor
7232 \value OneMinusSrcColor
7233 \value DstColor
7234 \value OneMinusDstColor
7235 \value SrcAlpha
7236 \value OneMinusSrcAlpha
7237 \value DstAlpha
7238 \value OneMinusDstAlpha
7239 \value ConstantColor
7240 \value OneMinusConstantColor
7241 \value ConstantAlpha
7242 \value OneMinusConstantAlpha
7243 \value SrcAlphaSaturate
7244 \value Src1Color
7245 \value OneMinusSrc1Color
7246 \value Src1Alpha
7247 \value OneMinusSrc1Alpha
7248 */
7249
7250/*!
7251 \enum QRhiGraphicsPipeline::BlendOp
7252 Specifies the blend operation
7253
7254 \value Add
7255 \value Subtract
7256 \value ReverseSubtract
7257 \value Min
7258 \value Max
7259 */
7260
7261/*!
7262 \enum QRhiGraphicsPipeline::CompareOp
7263 Specifies the depth or stencil comparison function
7264
7265 \value Never
7266 \value Less (default for depth)
7267 \value Equal
7268 \value LessOrEqual
7269 \value Greater
7270 \value NotEqual
7271 \value GreaterOrEqual
7272 \value Always (default for stencil)
7273 */
7274
7275/*!
7276 \enum QRhiGraphicsPipeline::StencilOp
7277 Specifies the stencil operation
7278
7279 \value StencilZero
7280 \value Keep (default)
7281 \value Replace
7282 \value IncrementAndClamp
7283 \value DecrementAndClamp
7284 \value Invert
7285 \value IncrementAndWrap
7286 \value DecrementAndWrap
7287 */
7288
7289/*!
7290 \enum QRhiGraphicsPipeline::PolygonMode
7291 \brief Specifies the polygon rasterization mode
7292
7293 Polygon Mode (Triangle Fill Mode in Metal, Fill Mode in D3D) specifies
7294 the fill mode used when rasterizing polygons. Polygons may be drawn as
7295 solids (Fill), or as a wire mesh (Line).
7296
7297 Support for non-fill polygon modes is optional and is indicated by the
7298 QRhi::NonFillPolygonMode feature. With OpenGL ES and some Vulkan
7299 implementations the feature will likely be reported as unsupported, which
7300 then means values other than Fill cannot be used.
7301
7302 \value Fill The interior of the polygon is filled (default)
7303 \value Line Boundary edges of the polygon are drawn as line segments.
7304 */
7305
7306/*!
7307 \struct QRhiGraphicsPipeline::TargetBlend
7308 \inmodule QtGuiPrivate
7309 \inheaderfile rhi/qrhi.h
7310 \since 6.6
7311 \brief Describes the blend state for one color attachment.
7312
7313 Defaults to color write enabled, blending disabled. The blend values are
7314 set up for pre-multiplied alpha (One, OneMinusSrcAlpha, One,
7315 OneMinusSrcAlpha) by default. This means that to get the alpha blending
7316 mode Qt Quick uses, it is enough to set the \c enable flag to true while
7317 leaving other values at their defaults.
7318
7319 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7320 for details.
7321 */
7322
7323/*!
7324 \variable QRhiGraphicsPipeline::TargetBlend::colorWrite
7325 */
7326
7327/*!
7328 \variable QRhiGraphicsPipeline::TargetBlend::enable
7329 */
7330
7331/*!
7332 \variable QRhiGraphicsPipeline::TargetBlend::srcColor
7333 */
7334
7335/*!
7336 \variable QRhiGraphicsPipeline::TargetBlend::dstColor
7337 */
7338
7339/*!
7340 \variable QRhiGraphicsPipeline::TargetBlend::opColor
7341 */
7342
7343/*!
7344 \variable QRhiGraphicsPipeline::TargetBlend::srcAlpha
7345 */
7346
7347/*!
7348 \variable QRhiGraphicsPipeline::TargetBlend::dstAlpha
7349 */
7350
7351/*!
7352 \variable QRhiGraphicsPipeline::TargetBlend::opAlpha
7353 */
7354
7355/*!
7356 \struct QRhiGraphicsPipeline::StencilOpState
7357 \inmodule QtGuiPrivate
7358 \inheaderfile rhi/qrhi.h
7359 \since 6.6
7360 \brief Describes the stencil operation state.
7361
7362 The default-constructed StencilOpState has the following set:
7363 \list
7364 \li failOp - \l Keep
7365 \li depthFailOp - \l Keep
7366 \li passOp - \l Keep
7367 \li compareOp \l Always
7368 \endlist
7369
7370 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7371 for details.
7372 */
7373
7374/*!
7375 \variable QRhiGraphicsPipeline::StencilOpState::failOp
7376 */
7377
7378/*!
7379 \variable QRhiGraphicsPipeline::StencilOpState::depthFailOp
7380 */
7381
7382/*!
7383 \variable QRhiGraphicsPipeline::StencilOpState::passOp
7384 */
7385
7386/*!
7387 \variable QRhiGraphicsPipeline::StencilOpState::compareOp
7388 */
7389
7390/*!
7391 \internal
7392 */
7393QRhiGraphicsPipeline::QRhiGraphicsPipeline(QRhiImplementation *rhi)
7394 : QRhiResource(rhi)
7395{
7396}
7397
7398/*!
7399 \return the resource type.
7400 */
7401QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
7402{
7403 return GraphicsPipeline;
7404}
7405
7406/*!
7407 \fn virtual bool QRhiGraphicsPipeline::create() = 0
7408
7409 Creates the corresponding native graphics resources. If there are already
7410 resources present due to an earlier create() with no corresponding
7411 destroy(), then destroy() is called implicitly first.
7412
7413 \return \c true when successful, \c false when a graphics operation failed.
7414 Regardless of the return value, calling destroy() is always safe.
7415
7416 \note This may be, depending on the underlying graphics API, an expensive
7417 operation, especially when shaders get compiled/optimized from source or
7418 from an intermediate bytecode format to the GPU's own instruction set.
7419 Where applicable, the QRhi backend automatically sets up the relevant
7420 non-persistent facilities to accelerate this, for example the Vulkan
7421 backend automatically creates a \c VkPipelineCache to improve data reuse
7422 during the lifetime of the application.
7423
7424 \note Drivers may also employ various persistent (disk-based) caching
7425 strategies for shader and pipeline data, which is hidden to and is outside
7426 of Qt's control. In some cases, depending on the graphics API and the QRhi
7427 backend, there are facilities within QRhi for manually managing such a
7428 cache, allowing the retrieval of a serializable blob that can then be
7429 reloaded in the future runs of the application to ensure faster pipeline
7430 creation times. See QRhi::pipelineCacheData() and
7431 QRhi::setPipelineCacheData() for details. Note also that when working with
7432 a QRhi instance managed by a higher level Qt framework, such as Qt Quick,
7433 it is possible that such disk-based caching is taken care of automatically,
7434 for example QQuickWindow uses a disk-based pipeline cache by default (which
7435 comes in addition to any driver-level caching).
7436 */
7437
7438/*!
7439 \fn QRhiGraphicsPipeline::Flags QRhiGraphicsPipeline::flags() const
7440 \return the currently set flags.
7441 */
7442
7443/*!
7444 \fn void QRhiGraphicsPipeline::setFlags(Flags f)
7445 Sets the flags \a f.
7446 */
7447
7448/*!
7449 \fn QRhiGraphicsPipeline::Topology QRhiGraphicsPipeline::topology() const
7450 \return the currently set primitive topology.
7451 */
7452
7453/*!
7454 \fn void QRhiGraphicsPipeline::setTopology(Topology t)
7455 Sets the primitive topology \a t.
7456 */
7457
7458/*!
7459 \fn QRhiGraphicsPipeline::CullMode QRhiGraphicsPipeline::cullMode() const
7460 \return the currently set face culling mode.
7461 */
7462
7463/*!
7464 \fn void QRhiGraphicsPipeline::setCullMode(CullMode mode)
7465 Sets the specified face culling \a mode.
7466 */
7467
7468/*!
7469 \fn QRhiGraphicsPipeline::FrontFace QRhiGraphicsPipeline::frontFace() const
7470 \return the currently set front face mode.
7471 */
7472
7473/*!
7474 \fn void QRhiGraphicsPipeline::setFrontFace(FrontFace f)
7475 Sets the front face mode \a f.
7476 */
7477
7478/*!
7479 \fn void QRhiGraphicsPipeline::setTargetBlends(std::initializer_list<TargetBlend> list)
7480
7481 Sets the \a list of render target blend settings. This is a list because
7482 when multiple render targets are used (i.e., a QRhiTextureRenderTarget with
7483 more than one QRhiColorAttachment), there needs to be a TargetBlend
7484 structure per render target (color attachment).
7485
7486 By default there is one default-constructed TargetBlend set.
7487
7488 \sa QRhi::MaxColorAttachments
7489 */
7490
7491/*!
7492 \fn template<typename InputIterator> void QRhiGraphicsPipeline::setTargetBlends(InputIterator first, InputIterator last)
7493 Sets the list of render target blend settings from the iterators \a first and \a last.
7494 */
7495
7496/*!
7497 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cbeginTargetBlends() const
7498 \return a const iterator pointing to the first item in the render target blend setting list.
7499 */
7500
7501/*!
7502 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cendTargetBlends() const
7503 \return a const iterator pointing just after the last item in the render target blend setting list.
7504 */
7505
7506/*!
7507 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::targetBlendAt(qsizetype index) const
7508 \return the render target blend setting at the specified \a index.
7509 */
7510
7511/*!
7512 \fn qsizetype QRhiGraphicsPipeline::targetBlendCount() const
7513 \return the number of render target blend settings.
7514 */
7515
7516/*!
7517 \fn bool QRhiGraphicsPipeline::hasDepthTest() const
7518 \return true if depth testing is enabled.
7519 */
7520
7521/*!
7522 \fn void QRhiGraphicsPipeline::setDepthTest(bool enable)
7523
7524 Enables or disables depth testing based on \a enable. Both depth test and
7525 the writing out of depth data are disabled by default.
7526
7527 \sa setDepthWrite()
7528 */
7529
7530/*!
7531 \fn bool QRhiGraphicsPipeline::hasDepthWrite() const
7532 \return true if depth write is enabled.
7533 */
7534
7535/*!
7536 \fn void QRhiGraphicsPipeline::setDepthWrite(bool enable)
7537
7538 Controls the writing out of depth data into the depth buffer based on
7539 \a enable. By default this is disabled. Depth write is typically enabled
7540 together with the depth test.
7541
7542 \note Enabling depth write without having depth testing enabled may not
7543 lead to the desired result, and should be avoided.
7544
7545 \sa setDepthTest()
7546 */
7547
7548/*!
7549 \fn bool QRhiGraphicsPipeline::hasDepthClamp() const
7550 \return true if depth clamp is enabled.
7551
7552 \since 6.11
7553 */
7554
7555/*!
7556 \fn void QRhiGraphicsPipeline::setDepthClamp(bool enable)
7557
7558 Enables depth clamping when \a enable is true. When depth clamping is
7559 enabled, primitives that would otherwise be clipped by the near or far
7560 clip plane are rasterized and their depth values are clamped to the
7561 depth range. When disabled (the default), such primitives are clipped.
7562
7563 \note This setting is ignored when the QRhi::DepthClamp feature is
7564 reported as unsupported.
7565
7566 \since 6.11
7567 */
7568
7569/*!
7570 \fn QRhiGraphicsPipeline::CompareOp QRhiGraphicsPipeline::depthOp() const
7571 \return the depth comparison function.
7572 */
7573
7574/*!
7575 \fn void QRhiGraphicsPipeline::setDepthOp(CompareOp op)
7576 Sets the depth comparison function \a op.
7577 */
7578
7579/*!
7580 \fn bool QRhiGraphicsPipeline::hasStencilTest() const
7581 \return true if stencil testing is enabled.
7582 */
7583
7584/*!
7585 \fn void QRhiGraphicsPipeline::setStencilTest(bool enable)
7586 Enables or disables stencil tests based on \a enable.
7587 By default this is disabled.
7588 */
7589
7590/*!
7591 \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilFront() const
7592 \return the current stencil test state for front faces.
7593 */
7594
7595/*!
7596 \fn void QRhiGraphicsPipeline::setStencilFront(const StencilOpState &state)
7597 Sets the stencil test \a state for front faces.
7598 */
7599
7600/*!
7601 \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilBack() const
7602 \return the current stencil test state for back faces.
7603 */
7604
7605/*!
7606 \fn void QRhiGraphicsPipeline::setStencilBack(const StencilOpState &state)
7607 Sets the stencil test \a state for back faces.
7608 */
7609
7610/*!
7611 \fn quint32 QRhiGraphicsPipeline::stencilReadMask() const
7612 \return the currrent stencil read mask.
7613 */
7614
7615/*!
7616 \fn void QRhiGraphicsPipeline::setStencilReadMask(quint32 mask)
7617 Sets the stencil read \a mask. The default value is 0xFF.
7618 */
7619
7620/*!
7621 \fn quint32 QRhiGraphicsPipeline::stencilWriteMask() const
7622 \return the current stencil write mask.
7623 */
7624
7625/*!
7626 \fn void QRhiGraphicsPipeline::setStencilWriteMask(quint32 mask)
7627 Sets the stencil write \a mask. The default value is 0xFF.
7628 */
7629
7630/*!
7631 \fn int QRhiGraphicsPipeline::sampleCount() const
7632 \return the currently set sample count. 1 means no multisample antialiasing.
7633 */
7634
7635/*!
7636 \fn void QRhiGraphicsPipeline::setSampleCount(int s)
7637
7638 Sets the sample count. Typical values for \a s are 1, 4, or 8. The pipeline
7639 must always be compatible with the render target, i.e. the sample counts
7640 must match.
7641
7642 \sa QRhi::supportedSampleCounts()
7643 */
7644
7645/*!
7646 \fn float QRhiGraphicsPipeline::lineWidth() const
7647 \return the currently set line width. The default is 1.0f.
7648 */
7649
7650/*!
7651 \fn void QRhiGraphicsPipeline::setLineWidth(float width)
7652
7653 Sets the line \a width. If the QRhi::WideLines feature is reported as
7654 unsupported at runtime, values other than 1.0f are ignored.
7655 */
7656
7657/*!
7658 \fn int QRhiGraphicsPipeline::depthBias() const
7659 \return the currently set depth bias.
7660 */
7661
7662/*!
7663 \fn void QRhiGraphicsPipeline::setDepthBias(int bias)
7664 Sets the depth \a bias. The default value is 0.
7665 */
7666
7667/*!
7668 \fn float QRhiGraphicsPipeline::slopeScaledDepthBias() const
7669 \return the currently set slope scaled depth bias.
7670 */
7671
7672/*!
7673 \fn void QRhiGraphicsPipeline::setSlopeScaledDepthBias(float bias)
7674 Sets the slope scaled depth \a bias. The default value is 0.
7675 */
7676
7677/*!
7678 \fn void QRhiGraphicsPipeline::setShaderStages(std::initializer_list<QRhiShaderStage> list)
7679 Sets the \a list of shader stages.
7680 */
7681
7682/*!
7683 \fn template<typename InputIterator> void QRhiGraphicsPipeline::setShaderStages(InputIterator first, InputIterator last)
7684 Sets the list of shader stages from the iterators \a first and \a last.
7685 */
7686
7687/*!
7688 \fn const QRhiShaderStage *QRhiGraphicsPipeline::cbeginShaderStages() const
7689 \return a const iterator pointing to the first item in the shader stage list.
7690 */
7691
7692/*!
7693 \fn const QRhiShaderStage *QRhiGraphicsPipeline::cendShaderStages() const
7694 \return a const iterator pointing just after the last item in the shader stage list.
7695 */
7696
7697/*!
7698 \fn const QRhiShaderStage *QRhiGraphicsPipeline::shaderStageAt(qsizetype index) const
7699 \return the shader stage at the specified \a index.
7700 */
7701
7702/*!
7703 \fn qsizetype QRhiGraphicsPipeline::shaderStageCount() const
7704 \return the number of shader stages in this pipeline.
7705 */
7706
7707/*!
7708 \fn QRhiVertexInputLayout QRhiGraphicsPipeline::vertexInputLayout() const
7709 \return the currently set vertex input layout specification.
7710 */
7711
7712/*!
7713 \fn void QRhiGraphicsPipeline::setVertexInputLayout(const QRhiVertexInputLayout &layout)
7714 Specifies the vertex input \a layout.
7715 */
7716
7717/*!
7718 \fn QRhiShaderResourceBindings *QRhiGraphicsPipeline::shaderResourceBindings() const
7719 \return the currently associated QRhiShaderResourceBindings object.
7720 */
7721
7722/*!
7723 \fn void QRhiGraphicsPipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
7724
7725 Associates with \a srb describing the resource binding layout and the
7726 resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional,
7727 because only the layout matters during pipeline creation. Therefore, the \a
7728 srb passed in here can leave the actual buffer or texture objects
7729 unspecified (\nullptr) as long as there is another,
7730 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
7731 QRhiShaderResourceBindings bound via
7732 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
7733 recording the draw calls.
7734 */
7735
7736/*!
7737 \fn QRhiRenderPassDescriptor *QRhiGraphicsPipeline::renderPassDescriptor() const
7738 \return the currently set QRhiRenderPassDescriptor.
7739 */
7740
7741/*!
7742 \fn void QRhiGraphicsPipeline::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
7743 Associates with the specified QRhiRenderPassDescriptor \a desc.
7744 */
7745
7746/*!
7747 \fn int QRhiGraphicsPipeline::patchControlPointCount() const
7748 \return the currently set patch control point count.
7749 */
7750
7751/*!
7752 \fn void QRhiGraphicsPipeline::setPatchControlPointCount(int count)
7753
7754 Sets the number of patch control points to \a count. The default value is
7755 3. This is used only when the topology is set to \l Patches.
7756 */
7757
7758/*!
7759 \fn QRhiGraphicsPipeline::PolygonMode QRhiGraphicsPipeline::polygonMode() const
7760 \return the polygon mode.
7761 */
7762
7763/*!
7764 \fn void QRhiGraphicsPipeline::setPolygonMode(PolygonMode mode)
7765 Sets the polygon \a mode. The default is Fill.
7766
7767 \sa QRhi::NonFillPolygonMode
7768 */
7769
7770/*!
7771 \fn int QRhiGraphicsPipeline::multiViewCount() const
7772 \return the view count. The default is 0, indicating no multiview rendering.
7773 \since 6.7
7774 */
7775
7776/*!
7777 \fn void QRhiGraphicsPipeline::setMultiViewCount(int count)
7778 Sets the view \a count for multiview rendering. The default is 0,
7779 indicating no multiview rendering.
7780 \a count must be 2 or larger to trigger multiview rendering.
7781
7782 Multiview is only available when the \l{QRhi::MultiView}{MultiView feature}
7783 is reported as supported. The render target must be a 2D texture array, and
7784 the color attachment for the render target must have the same \a count set.
7785
7786 See QRhiColorAttachment::setMultiViewCount() for further details on
7787 multiview rendering.
7788
7789 \since 6.7
7790 \sa QRhi::MultiView, QRhiColorAttachment::setMultiViewCount()
7791 */
7792
7793/*!
7794 \class QRhiSwapChain
7795 \inmodule QtGuiPrivate
7796 \inheaderfile rhi/qrhi.h
7797 \since 6.6
7798 \brief Swapchain resource.
7799
7800 A swapchain enables presenting rendering results to a surface. A swapchain
7801 is typically backed by a set of color buffers. Of these, one is displayed
7802 at a time.
7803
7804 Below is a typical pattern for creating and managing a swapchain and some
7805 associated resources in order to render onto a QWindow:
7806
7807 \code
7808 void init()
7809 {
7810 sc = rhi->newSwapChain();
7811 ds = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
7812 QSize(), // no need to set the size here due to UsedWithSwapChainOnly
7813 1,
7814 QRhiRenderBuffer::UsedWithSwapChainOnly);
7815 sc->setWindow(window);
7816 sc->setDepthStencil(ds);
7817 rp = sc->newCompatibleRenderPassDescriptor();
7818 sc->setRenderPassDescriptor(rp);
7819 resizeSwapChain();
7820 }
7821
7822 void resizeSwapChain()
7823 {
7824 hasSwapChain = sc->createOrResize();
7825 }
7826
7827 void render()
7828 {
7829 if (!hasSwapChain || notExposed)
7830 return;
7831
7832 if (sc->currentPixelSize() != sc->surfacePixelSize() || newlyExposed) {
7833 resizeSwapChain();
7834 if (!hasSwapChain)
7835 return;
7836 newlyExposed = false;
7837 }
7838
7839 rhi->beginFrame(sc);
7840 // ...
7841 rhi->endFrame(sc);
7842 }
7843 \endcode
7844
7845 Avoid relying on QWindow resize events to resize swapchains, especially
7846 considering that surface sizes may not always fully match the QWindow
7847 reported dimensions. The safe, cross-platform approach is to do the check
7848 via surfacePixelSize() whenever starting a new frame.
7849
7850 Releasing the swapchain must happen while the QWindow and the underlying
7851 native window is fully up and running. Building on the previous example:
7852
7853 \code
7854 void releaseSwapChain()
7855 {
7856 if (hasSwapChain) {
7857 sc->destroy();
7858 hasSwapChain = false;
7859 }
7860 }
7861
7862 // assuming Window is our QWindow subclass
7863 bool Window::event(QEvent *e)
7864 {
7865 switch (e->type()) {
7866 case QEvent::UpdateRequest: // for QWindow::requestUpdate()
7867 render();
7868 break;
7869 case QEvent::PlatformSurface:
7870 if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
7871 releaseSwapChain();
7872 break;
7873 default:
7874 break;
7875 }
7876 return QWindow::event(e);
7877 }
7878 \endcode
7879
7880 Initializing the swapchain and starting to render the first frame cannot
7881 start at any time. The safe, cross-platform approach is to rely on expose
7882 events. QExposeEvent is a loosely specified event that is sent whenever a
7883 window gets mapped, obscured, and resized, depending on the platform.
7884
7885 \code
7886 void Window::exposeEvent(QExposeEvent *)
7887 {
7888 // initialize and start rendering when the window becomes usable for graphics purposes
7889 if (isExposed() && !running) {
7890 running = true;
7891 init();
7892 }
7893
7894 // stop pushing frames when not exposed or size becomes 0
7895 if ((!isExposed() || (hasSwapChain && sc->surfacePixelSize().isEmpty())) && running)
7896 notExposed = true;
7897
7898 // continue when exposed again and the surface has a valid size
7899 if (isExposed() && running && notExposed && !sc->surfacePixelSize().isEmpty()) {
7900 notExposed = false;
7901 newlyExposed = true;
7902 }
7903
7904 if (isExposed() && !sc->surfacePixelSize().isEmpty())
7905 render();
7906 }
7907 \endcode
7908
7909 Once the rendering has started, a simple way to request a new frame is
7910 QWindow::requestUpdate(). While on some platforms this is merely a small
7911 timer, on others it has a specific implementation: for instance on macOS or
7912 iOS it may be backed by
7913 \l{https://developer.apple.com/documentation/corevideo/cvdisplaylink?language=objc}{CVDisplayLink}.
7914 The example above is already prepared for update requests by handling
7915 QEvent::UpdateRequest.
7916
7917 While acting as a QRhiRenderTarget, QRhiSwapChain also manages a
7918 QRhiCommandBuffer. Calling QRhi::endFrame() submits the recorded commands
7919 and also enqueues a \c present request. The default behavior is to do this
7920 with a swap interval of 1, meaning synchronizing to the display's vertical
7921 refresh is enabled. Thus the rendering thread calling beginFrame() and
7922 endFrame() will get throttled to vsync. On some backends this can be
7923 disabled by passing QRhiSwapChain:NoVSync in flags().
7924
7925 Multisampling (MSAA) is handled transparently to the applications when
7926 requested via setSampleCount(). Where applicable, QRhiSwapChain will take
7927 care of creating additional color buffers and issuing a multisample resolve
7928 command at the end of a frame. For OpenGL, it is necessary to request the
7929 appropriate sample count also via QSurfaceFormat, by calling
7930 QSurfaceFormat::setDefaultFormat() before initializing the QRhi.
7931
7932 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7933 for details.
7934 */
7935
7936/*!
7937 \enum QRhiSwapChain::Flag
7938 Flag values to describe swapchain properties
7939
7940 \value SurfaceHasPreMulAlpha Indicates that the target surface has
7941 transparency with premultiplied alpha. For example, this is what Qt Quick
7942 uses when the alpha channel is enabled on the target QWindow, because the
7943 scenegraph rendrerer always outputs fragments with alpha multiplied into
7944 the red, green, and blue values. To ensure identical behavior across
7945 platforms, always set QSurfaceFormat::alphaBufferSize() to a non-zero value
7946 on the target QWindow whenever this flag is set on the swapchain.
7947
7948 \value SurfaceHasNonPreMulAlpha Indicates the target surface has
7949 transparency with non-premultiplied alpha. Be aware that this may not be
7950 supported on some systems, if the system compositor always expects content
7951 with premultiplied alpha. In that case the behavior with this flag set is
7952 expected to be equivalent to SurfaceHasPreMulAlpha.
7953
7954 \value sRGB Requests to pick an sRGB format for the swapchain's color
7955 buffers and/or render target views, where applicable. Note that this
7956 implies that sRGB framebuffer update and blending will get enabled for all
7957 content targeting this swapchain, and opting out is not possible. For
7958 OpenGL, set \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the
7959 QSurfaceFormat of the QWindow in addition. Applicable only when the
7960 swapchain format is set to QRhiSwapChain::SDR.
7961
7962 \value UsedAsTransferSource Indicates the swapchain will be used as the
7963 source of a readback in QRhiResourceUpdateBatch::readBackTexture().
7964
7965 \value NoVSync Requests disabling waiting for vertical sync, also avoiding
7966 throttling the rendering thread. The behavior is backend specific and
7967 applicable only where it is possible to control this. Some may ignore the
7968 request altogether. For OpenGL, try instead setting the swap interval to 0
7969 on the QWindow via QSurfaceFormat::setSwapInterval().
7970
7971 \value MinimalBufferCount Requests creating the swapchain with the minimum
7972 number of buffers, which is in practice 2, unless the graphics
7973 implementation has a higher minimum number than that. Only applicable with
7974 backends where such control is available via the graphics API, for example,
7975 Vulkan. By default it is up to the backend to decide what number of buffers
7976 it requests (in practice this is almost always either 2 or 3), and it is
7977 not the applications' concern. However, on Vulkan for instance the backend
7978 will likely prefer the higher number (3), for example to avoid odd
7979 performance issues with some Vulkan implementations on mobile devices. It
7980 could be that on some platforms it can prove to be beneficial to force the
7981 lower buffer count (2), so this flag allows forcing that. Note that all
7982 this has no effect on the number of frames kept in flight, so the CPU
7983 (QRhi) will still prepare frames at most \c{N - 1} frames ahead of the GPU,
7984 even when the swapchain image buffer count larger than \c N. (\c{N} =
7985 QRhi::FramesInFlight and typically 2).
7986 */
7987
7988/*!
7989 \enum QRhiSwapChain::Format
7990 Describes the swapchain format. The default format is SDR.
7991
7992 This enum is used with
7993 \l{QRhiSwapChain::isFormatSupported()}{isFormatSupported()} to check
7994 upfront if creating the swapchain with the given format is supported by the
7995 platform and the window's associated screen, and with
7996 \l{QRhiSwapChain::setFormat()}{setFormat()}
7997 to set the requested format in the swapchain before calling
7998 \l{QRhiSwapChain::createOrResize()}{createOrResize()} for the first time.
7999
8000 \value SDR 8-bit RGBA or BGRA, depending on the backend and platform. With
8001 OpenGL ES in particular, it could happen that the platform provides less
8002 than 8 bits (e.g. due to EGL and the QSurfaceFormat choosing a 565 or 444
8003 format - this is outside the control of QRhi). Standard dynamic range. May
8004 be combined with setting the QRhiSwapChain::sRGB flag.
8005
8006 \value HDRExtendedSrgbLinear 16-bit float RGBA, high dynamic range,
8007 extended linear sRGB (scRGB) color space. This involves Rec. 709 primaries
8008 (same as SDR/sRGB) and linear colors. Conversion to the display's native
8009 color space (such as, HDR10) is performed by the windowing system. On
8010 Windows this is the canonical color space of the system compositor, and is
8011 the recommended format for HDR swapchains in general on desktop platforms.
8012
8013 \value HDR10 10-bit unsigned int RGB or BGR with 2 bit alpha, high dynamic
8014 range, HDR10 (Rec. 2020) color space with an ST2084 PQ transfer function.
8015
8016 \value HDRExtendedDisplayP3Linear 16-bit float RGBA, high dynamic range,
8017 extended linear Display P3 color space. The primary choice for HDR on
8018 platforms such as iOS and VisionOS.
8019 */
8020
8021/*!
8022 \internal
8023 */
8024QRhiSwapChain::QRhiSwapChain(QRhiImplementation *rhi)
8025 : QRhiResource(rhi)
8026{
8027}
8028
8029/*!
8030 \return the resource type.
8031 */
8032QRhiResource::Type QRhiSwapChain::resourceType() const
8033{
8034 return SwapChain;
8035}
8036
8037/*!
8038 \fn QSize QRhiSwapChain::currentPixelSize() const
8039
8040 \return the size with which the swapchain was last successfully built. Use
8041 this to decide if createOrResize() needs to be called again: if
8042 \c{currentPixelSize() != surfacePixelSize()} then the swapchain needs to be
8043 resized.
8044
8045 \note Typical rendering logic will call this function to get the output
8046 size when starting to prepare a new frame, and base dependent calculations
8047 (such as, the viewport) on the size returned from this function.
8048
8049 While in many cases the value is the same as \c{QWindow::size() *
8050 QWindow::devicePixelRatio()}, relying on the QWindow-reported size is not
8051 guaranteed to be correct on all platforms and graphics API implementations.
8052 Using this function is therefore strongly recommended whenever there is a
8053 need to identify the dimensions, in pixels, of the output layer or surface.
8054
8055 This also has the added benefit of avoiding potential data races when QRhi
8056 is used on a dedicated rendering thread, because the need to call QWindow
8057 functions, that may then access data updated on the main thread, is
8058 avoided.
8059
8060 \sa surfacePixelSize()
8061 */
8062
8063/*!
8064 \fn virtual QSize QRhiSwapChain::surfacePixelSize() = 0
8065
8066 \return The size of the window's associated surface or layer.
8067
8068 \warning Do not assume this is the same as \c{QWindow::size() *
8069 QWindow::devicePixelRatio()}. With some graphics APIs and windowing system
8070 interfaces (for example, Vulkan) there is a theoretical possibility for a
8071 surface to assume a size different from the associated window. To support
8072 these cases, \b{rendering logic must always base size-derived calculations
8073 (such as, viewports) on the size reported from QRhiSwapChain, and never on
8074 the size queried from QWindow}.
8075
8076 \note \b{Can also be called before createOrResize(), if at least window() is
8077 already set. This in combination with currentPixelSize() allows to detect
8078 when a swapchain needs to be resized.} However, watch out for the fact that
8079 the size of the underlying native object (surface, layer, or similar) is
8080 "live", so whenever this function is called, it returns the latest value
8081 reported by the underlying implementation, without any atomicity guarantee.
8082 Therefore, using this function to determine pixel sizes for graphics
8083 resources that are used in a frame is strongly discouraged. Rely on
8084 currentPixelSize() instead which returns a size that is atomic and will not
8085 change between createOrResize() invocations.
8086
8087 \note For depth-stencil buffers used in combination with the swapchain's
8088 color buffers, it is strongly recommended to rely on the automatic sizing
8089 and rebuilding behavior provided by the
8090 QRhiRenderBuffer:UsedWithSwapChainOnly flag. Avoid querying the surface
8091 size via this function just to get a size that can be passed to
8092 QRhiRenderBuffer::setPixelSize() as that would suffer from the lack of
8093 atomicity as described above.
8094
8095 \sa currentPixelSize()
8096 */
8097
8098/*!
8099 \fn virtual bool QRhiSwapChain::isFormatSupported(Format f) = 0
8100
8101 \return true if the given swapchain format \a f is supported. SDR is always
8102 supported.
8103
8104 \note Can be called independently of createOrResize(), but window() must
8105 already be set. Calling without the window set may lead to unexpected
8106 results depending on the backend and platform (most likely false for any
8107 HDR format), because HDR format support is usually tied to the output
8108 (screen) to which the swapchain's associated window belongs at any given
8109 time. If the result is true for a HDR format, then creating the swapchain
8110 with that format is expected to succeed as long as the window is not moved
8111 to another screen in the meantime.
8112
8113 The main use of this function is to call it before the first
8114 createOrResize() after the window is already set. This allow the QRhi
8115 backends to perform platform or windowing system specific queries to
8116 determine if the window (and the screen it is on) is capable of true HDR
8117 output with the specified format.
8118
8119 When the format is reported as supported, call setFormat() to set the
8120 requested format and call createOrResize(). Be aware of the consequences
8121 however: successfully requesting a HDR format will involve having to deal
8122 with a different color space, possibly doing white level correction for
8123 non-HDR-aware content, adjusting tonemapping methods, adjusting offscreen
8124 render target settings, etc.
8125
8126 \sa setFormat()
8127 */
8128
8129/*!
8130 \fn virtual QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer() = 0
8131
8132 \return a command buffer on which rendering commands and resource updates
8133 can be recorded within a \l{QRhi::beginFrame()}{beginFrame} -
8134 \l{QRhi::endFrame()}{endFrame} block, assuming beginFrame() was called with
8135 this swapchain.
8136
8137 \note The returned object is valid also after endFrame(), up until the next
8138 beginFrame(), but the returned command buffer should not be used to record
8139 any commands then. Rather, it can be used to query data collected during
8140 the frame (or previous frames), for example by calling
8141 \l{QRhiCommandBuffer::lastCompletedGpuTime()}{lastCompletedGpuTime()}.
8142
8143 \note The value must not be cached and reused between frames. The caller
8144 should not hold on to the returned object once
8145 \l{QRhi::beginFrame()}{beginFrame()} is called again. Instead, the command
8146 buffer object should be queried again by calling this function.
8147*/
8148
8149/*!
8150 \fn virtual QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget() = 0
8151
8152 \return a render target that can used with beginPass() in order to render
8153 the swapchain's current backbuffer. Only valid within a
8154 QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called
8155 with this swapchain.
8156
8157 \note the value must not be cached and reused between frames
8158 */
8159
8160/*!
8161 \enum QRhiSwapChain::StereoTargetBuffer
8162 Selects the backbuffer to use with a stereoscopic swapchain.
8163
8164 \value LeftBuffer
8165 \value RightBuffer
8166 */
8167
8168/*!
8169 \return a render target that can be used with beginPass() in order to
8170 render to the swapchain's left or right backbuffer. This overload should be
8171 used only with stereoscopic rendering, that is, when the associated QWindow
8172 is backed by two color buffers, one for each eye, instead of just one.
8173
8174 When stereoscopic rendering is not supported, the return value will be
8175 the default target. It is supported by all hardware backends except for Metal, in
8176 combination with \l QSurfaceFormat::StereoBuffers, assuming it is supported
8177 by the graphics and display driver stack at run time. Metal and Null backends
8178 are going to return the default render target from this overload.
8179
8180 \note the value must not be cached and reused between frames
8181 */
8182QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
8183{
8184 Q_UNUSED(targetBuffer);
8185 return currentFrameRenderTarget();
8186}
8187
8188/*!
8189 \fn virtual bool QRhiSwapChain::createOrResize() = 0
8190
8191 Creates the swapchain if not already done and resizes the swapchain buffers
8192 to match the current size of the targeted surface. Call this whenever the
8193 size of the target surface is different than before.
8194
8195 \note call destroy() only when the swapchain needs to be released
8196 completely, typically upon
8197 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed. To perform resizing, just
8198 call createOrResize().
8199
8200 \return \c true when successful, \c false when a graphics operation failed.
8201 Regardless of the return value, calling destroy() is always safe.
8202 */
8203
8204/*!
8205 \fn QWindow *QRhiSwapChain::window() const
8206 \return the currently set window.
8207 */
8208
8209/*!
8210 \fn void QRhiSwapChain::setWindow(QWindow *window)
8211 Sets the \a window.
8212 */
8213
8214/*!
8215 \fn QRhiSwapChainProxyData QRhiSwapChain::proxyData() const
8216 \return the currently set proxy data.
8217 */
8218
8219/*!
8220 \fn void QRhiSwapChain::setProxyData(const QRhiSwapChainProxyData &d)
8221 Sets the proxy data \a d.
8222
8223 \sa QRhi::updateSwapChainProxyData()
8224 */
8225
8226/*!
8227 \fn QRhiSwapChain::Flags QRhiSwapChain::flags() const
8228 \return the currently set flags.
8229 */
8230
8231/*!
8232 \fn void QRhiSwapChain::setFlags(Flags f)
8233 Sets the flags \a f.
8234 */
8235
8236/*!
8237 \fn QRhiSwapChain::Format QRhiSwapChain::format() const
8238 \return the currently set format.
8239 */
8240
8241/*!
8242 \fn void QRhiSwapChain::setFormat(Format f)
8243 Sets the format \a f.
8244
8245 Avoid setting formats that are reported as unsupported from
8246 isFormatSupported(). Note that support for a given format may depend on the
8247 screen the swapchain's associated window is opened on. On some platforms,
8248 such as Windows and macOS, for HDR output to work it is necessary to have
8249 HDR output enabled in the display settings.
8250
8251 See isFormatSupported(), \l QRhiSwapChainHdrInfo, and \l Format for more
8252 information on high dynamic range output.
8253 */
8254
8255/*!
8256 \fn QRhiRenderBuffer *QRhiSwapChain::depthStencil() const
8257 \return the currently associated renderbuffer for depth-stencil.
8258 */
8259
8260/*!
8261 \fn void QRhiSwapChain::setDepthStencil(QRhiRenderBuffer *ds)
8262 Sets the renderbuffer \a ds for use as a depth-stencil buffer.
8263 */
8264
8265/*!
8266 \fn int QRhiSwapChain::sampleCount() const
8267 \return the currently set sample count. 1 means no multisample antialiasing.
8268 */
8269
8270/*!
8271 \fn void QRhiSwapChain::setSampleCount(int samples)
8272
8273 Sets the sample count. Common values for \a samples are 1 (no MSAA), 4 (4x
8274 MSAA), or 8 (8x MSAA).
8275
8276 \sa QRhi::supportedSampleCounts()
8277 */
8278
8279/*!
8280 \fn QRhiRenderPassDescriptor *QRhiSwapChain::renderPassDescriptor() const
8281 \return the currently associated QRhiRenderPassDescriptor object.
8282 */
8283
8284/*!
8285 \fn void QRhiSwapChain::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
8286 Associates with the QRhiRenderPassDescriptor \a desc.
8287 */
8288
8289/*!
8290 \fn virtual QRhiRenderPassDescriptor *QRhiSwapChain::newCompatibleRenderPassDescriptor() = 0;
8291
8292 \return a new QRhiRenderPassDescriptor that is compatible with this swapchain.
8293
8294 The returned value is used in two ways: it can be passed to
8295 setRenderPassDescriptor() and
8296 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
8297 describes the attachments (color, depth/stencil) and the load/store
8298 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
8299 be used in combination with a swapchain that has a
8300 \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
8301 QRhiRenderPassDescriptor set.
8302
8303 \sa createOrResize()
8304 */
8305
8306/*!
8307 \fn QRhiShadingRateMap *QRhiSwapChain::shadingRateMap() const
8308 \return the currently set QRhiShadingRateMap. By default this is \nullptr.
8309 \since 6.9
8310 */
8311
8312/*!
8313 \fn void QRhiSwapChain::setShadingRateMap(QRhiShadingRateMap *map)
8314
8315 Associates with the specified QRhiShadingRateMap \a map. This is functional
8316 only when the \l QRhi::VariableRateShadingMap feature is reported as
8317 supported.
8318
8319 When QRhiCommandBuffer::setShadingRate() is also called, the higher of the
8320 two shading rates is used for each tile. There is currently no control
8321 offered over the combiner behavior.
8322
8323 \note Setting a shading rate map implies that a different, new
8324 QRhiRenderPassDescriptor is needed and some of the native swapchain objects
8325 must be rebuilt. Therefore, if the swapchain is already set up, call
8326 newCompatibleRenderPassDescriptor() and setRenderPassDescriptor() right
8327 after setShadingRateMap(). Then, createOrResize() must also be called again.
8328 This has rolling consequences, for example for graphics pipelines: those
8329 also need to be associated with the new QRhiRenderPassDescriptor and then
8330 rebuilt. See \l QRhiRenderPassDescriptor::serializedFormat() for some
8331 suggestions on how to deal with this. Remember to set the
8332 QRhiGraphicsPipeline::UsesShadingRate flag for them as well.
8333
8334 \since 6.9
8335 */
8336
8337/*!
8338 \struct QRhiSwapChainHdrInfo
8339 \inmodule QtGuiPrivate
8340 \inheaderfile rhi/qrhi.h
8341 \since 6.6
8342
8343 \brief Describes the high dynamic range related information of the
8344 swapchain's associated output.
8345
8346 To perform HDR-compatible tonemapping, where the target range is not [0,1],
8347 one often needs to know the maximum luminance of the display the
8348 swapchain's window is associated with. While this is often made
8349 user-configurable (think brightness, gamma and similar settings in games),
8350 it can be highly useful to set defaults based on the values reported by the
8351 display itself, thus providing a decent starting point.
8352
8353 There are some problems however: the information is exposed in different
8354 forms on different platforms, whereas with cross-platform graphics APIs
8355 there is often no associated solution at all, because managing such
8356 information is not in the scope of the API (and may rather be retrievable
8357 via other platform-specific means, if any).
8358
8359 With Metal on macOS/iOS, there is no luminance values exposed in the
8360 platform APIs. Instead, the maximum color component value, that would be
8361 1.0 in a non-HDR setup, is provided. The \c limitsType field indicates what
8362 kind of information is available. It is then up to the clients of QRhi to
8363 access the correct data from the \c limits union and use it as they see
8364 fit.
8365
8366 With an API like Vulkan, where there is no way to get such information, the
8367 values are always the built-in defaults.
8368
8369 Therefore, the struct returned from QRhiSwapChain::hdrInfo() contains
8370 either some hard-coded defaults or real values received from an API such as
8371 DXGI (IDXGIOutput6) or Cocoa (NSScreen). When no platform queries are
8372 available (or needs using platform facilities out of scope for QRhi), the
8373 hard-coded defaults are a maximum luminance of 1000 nits and an SDR white
8374 level of 200.
8375
8376 The struct also exposes the presumed luminance behavior of the platform and
8377 its compositor, to indicate what a color component value of 1.0 is treated
8378 as in a HDR color buffer. In some cases it will be necessary to perform
8379 color correction of non-HDR content composited with HDR content. To enable
8380 this, the SDR white level is queried from the system on some platforms
8381 (Windows) and exposed here.
8382
8383 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8384 for details.
8385
8386 \sa QRhiSwapChain::hdrInfo()
8387 */
8388
8389/*!
8390 \enum QRhiSwapChainHdrInfo::LimitsType
8391
8392 \value LuminanceInNits Indicates that the \l limits union has its
8393 \c luminanceInNits struct set
8394
8395 \value ColorComponentValue Indicates that the \l limits union has its
8396 \c colorComponentValue struct set
8397*/
8398
8399/*!
8400 \enum QRhiSwapChainHdrInfo::LuminanceBehavior
8401
8402 \value SceneReferred Indicates that the color value of 1.0 is interpreted
8403 as 80 nits. This is the behavior of HDR-enabled windows with the Windows
8404 compositor. See
8405 \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range}{this
8406 page} for more information on HDR on Windows.
8407
8408 \value DisplayReferred Indicates that the color value of 1.0 is interpreted
8409 as the value of the SDR white. (which can be e.g. 200 nits, but will vary
8410 depending on screen brightness) This is the behavior of HDR-enabled windows
8411 on Apple platforms. See
8412 \l{https://developer.apple.com/documentation/metal/hdr_content/displaying_hdr_content_in_a_metal_layer}{this
8413 page} for more information on Apple's EDR system.
8414*/
8415
8416/*!
8417 \variable QRhiSwapChainHdrInfo::limitsType
8418
8419 With Metal on macOS/iOS, there is no luminance values exposed in the
8420 platform APIs. Instead, the maximum color component value, that would be
8421 1.0 in a non-HDR setup, is provided. This value indicates what kind of
8422 information is available in \l limits.
8423
8424 \sa QRhiSwapChain::hdrInfo()
8425*/
8426
8427/*!
8428 \variable QRhiSwapChainHdrInfo::limits
8429
8430 Contains the actual values queried from the graphics API or the platform.
8431 The type of data is indicated by \l limitsType. This is therefore a union.
8432 There are currently two options:
8433
8434 Luminance values in nits:
8435
8436 \code
8437 struct {
8438 float minLuminance;
8439 float maxLuminance;
8440 } luminanceInNits;
8441 \endcode
8442
8443 On Windows the minimum and maximum luminance depends on the screen
8444 brightness. While not relevant for desktops, on laptops the screen
8445 brightness may change at any time. Increasing brightness implies decreased
8446 maximum luminance. In addition, the results may also be dependent on the
8447 HDR Content Brightness set in Windows Settings' System/Display/HDR view,
8448 if there is such a setting.
8449
8450 Note however that the changes made to the laptop screen's brightness or in
8451 the system settings while the application is running are not necessarily
8452 reflected in the returned values, meaning calling hdrInfo() again may still
8453 return the same luminance range as before for the rest of the process'
8454 lifetime. The exact behavior is up to DXGI and Qt has no control over it.
8455
8456 \note The Windows compositor works in scene-referred mode for HDR content.
8457 A color component value of 1.0 corresponds to a luminance of 80 nits. When
8458 rendering non-HDR content (e.g. 2D UI elements), the correction of the
8459 white level is often necessary. (e.g., outputting the fragment color (1, 1,
8460 1) will likely lead to showing a shade of white that is too dim on-screen)
8461 See \l sdrWhiteLevel.
8462
8463 For macOS/iOS, the current maximum and potential maximum color
8464 component values are provided:
8465
8466 \code
8467 struct {
8468 float maxColorComponentValue;
8469 float maxPotentialColorComponentValue;
8470 } colorComponentValue;
8471 \endcode
8472
8473 The value may depend on the screen brightness, which on laptops means that
8474 the result may change in the next call to hdrInfo() if the brightness was
8475 changed in the meantime. The maximum screen brightness implies a maximum
8476 color value of 1.0.
8477
8478 \note Apple's EDR is display-referred. 1.0 corresponds to a luminance level
8479 of SDR white (e.g. 200 nits), the value of which varies based on the screen
8480 brightness and possibly other settings. The exact luminance value for that,
8481 or the maximum luminance of the display, are not exposed to the
8482 applications.
8483
8484 \note It has been observed that the color component values are not set to
8485 the correct larger-than-1 value right away on startup on some macOS
8486 systems, but the values tend to change during or after the first frame.
8487
8488 \sa QRhiSwapChain::hdrInfo()
8489*/
8490
8491/*!
8492 \variable QRhiSwapChainHdrInfo::luminanceBehavior
8493
8494 Describes the platform's presumed behavior with regards to color values.
8495
8496 \sa sdrWhiteLevel
8497 */
8498
8499/*!
8500 \variable QRhiSwapChainHdrInfo::sdrWhiteLevel
8501
8502 On Windows this is the dynamic SDR white level in nits. The value is
8503 dependent on the screen brightness (on laptops), and the SDR or HDR Content
8504 Brightness settings in the Windows settings' System/Display/HDR view.
8505
8506 To perform white level correction for non-HDR (SDR) content, such as 2D UI
8507 elemenents, multiply the final color with sdrWhiteLevel / 80.0 whenever
8508 \l luminanceBehavior is SceneReferred. (assuming Windows and a linear
8509 extended sRGB (scRGB) color space)
8510
8511 On other platforms the value is always a pre-defined value, 200. This may
8512 not match the system's actual SDR white level, but the value of this
8513 variable is not relevant in practice when the \l luminanceBehavior is
8514 DisplayReferred, because then the color component value of 1.0 refers to
8515 the SDR white by default.
8516
8517 \sa luminanceBehavior
8518*/
8519
8520/*!
8521 \return the HDR information for the associated display.
8522
8523 Do not assume that this is a cheap operation. Depending on the platform,
8524 this function makes various platform queries which may have a performance
8525 impact.
8526
8527 \note Can be called before createOrResize() as long as the window is
8528 \l{setWindow()}{set}.
8529
8530 \note What happens when moving a window with an initialized swapchain
8531 between displays (HDR to HDR with different characteristics, HDR to SDR,
8532 etc.) is not currently well-defined and depends heavily on the windowing
8533 system and compositor, with potentially varying behavior between platforms.
8534 Currently QRhi only guarantees that hdrInfo() returns valid data, if
8535 available, for the display to which the swapchain's associated window
8536 belonged at the time of createOrResize().
8537
8538 \sa QRhiSwapChainHdrInfo
8539 */
8540QRhiSwapChainHdrInfo QRhiSwapChain::hdrInfo()
8541{
8542 QRhiSwapChainHdrInfo info;
8543 info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
8544 info.limits.luminanceInNits.minLuminance = 0.0f;
8545 info.limits.luminanceInNits.maxLuminance = 1000.0f;
8546 info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
8547 info.sdrWhiteLevel = 200.0f;
8548 return info;
8549}
8550
8551#ifndef QT_NO_DEBUG_STREAM
8552QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
8553{
8554 QDebugStateSaver saver(dbg);
8555 dbg.nospace() << "QRhiSwapChainHdrInfo(";
8556 switch (info.limitsType) {
8558 dbg.nospace() << " minLuminance=" << info.limits.luminanceInNits.minLuminance
8559 << " maxLuminance=" << info.limits.luminanceInNits.maxLuminance;
8560 break;
8562 dbg.nospace() << " maxColorComponentValue=" << info.limits.colorComponentValue.maxColorComponentValue;
8563 dbg.nospace() << " maxPotentialColorComponentValue=" << info.limits.colorComponentValue.maxPotentialColorComponentValue;
8564 break;
8565 }
8566 switch (info.luminanceBehavior) {
8568 dbg.nospace() << " scene-referred, SDR white level=" << info.sdrWhiteLevel;
8569 break;
8571 dbg.nospace() << " display-referred";
8572 break;
8573 }
8574 dbg.nospace() << ')';
8575 return dbg;
8576}
8577#endif
8578
8579/*!
8580 \class QRhiComputePipeline
8581 \inmodule QtGuiPrivate
8582 \inheaderfile rhi/qrhi.h
8583 \since 6.6
8584 \brief Compute pipeline state resource.
8585
8586 \note Setting the shader resource bindings is mandatory. The referenced
8587 QRhiShaderResourceBindings must already have created() called on it by the
8588 time create() is called.
8589
8590 \note Setting the shader is mandatory.
8591
8592 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8593 for details.
8594 */
8595
8596/*!
8597 \enum QRhiComputePipeline::Flag
8598
8599 Flag values for describing pipeline options.
8600
8601 \value CompileShadersWithDebugInfo Requests compiling shaders with debug
8602 information enabled, when applicable. See
8603 QRhiGraphicsPipeline::CompileShadersWithDebugInfo for more information.
8604 */
8605
8606/*!
8607 \return the resource type.
8608 */
8609QRhiResource::Type QRhiComputePipeline::resourceType() const
8610{
8611 return ComputePipeline;
8612}
8613
8614/*!
8615 \internal
8616 */
8617QRhiComputePipeline::QRhiComputePipeline(QRhiImplementation *rhi)
8618 : QRhiResource(rhi)
8619{
8620}
8621
8622/*!
8623 \fn QRhiComputePipeline::Flags QRhiComputePipeline::flags() const
8624 \return the currently set flags.
8625 */
8626
8627/*!
8628 \fn void QRhiComputePipeline::setFlags(Flags f)
8629 Sets the flags \a f.
8630 */
8631
8632/*!
8633 \fn QRhiShaderStage QRhiComputePipeline::shaderStage() const
8634 \return the currently set shader.
8635 */
8636
8637/*!
8638 \fn void QRhiComputePipeline::setShaderStage(const QRhiShaderStage &stage)
8639
8640 Sets the shader to use. \a stage can only refer to the
8641 \l{QRhiShaderStage::Compute}{compute stage}.
8642 */
8643
8644/*!
8645 \fn QRhiShaderResourceBindings *QRhiComputePipeline::shaderResourceBindings() const
8646 \return the currently associated QRhiShaderResourceBindings object.
8647 */
8648
8649/*!
8650 \fn void QRhiComputePipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
8651
8652 Associates with \a srb describing the resource binding layout and the
8653 resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional. As
8654 with graphics pipelines, the \a srb passed in here can leave the actual
8655 buffer or texture objects unspecified (\nullptr) as long as there is
8656 another,
8657 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
8658 QRhiShaderResourceBindings bound via
8659 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
8660 recording the dispatch call.
8661 */
8662
8663/*!
8664 \struct QRhiIndirectDrawCommand
8665 \inmodule QtGuiPrivate
8666 \inheaderfile rhi/qrhi.h
8667 \since 6.12
8668 \brief Draw command.
8669
8670 A draw command that can be uploaded to a QRhiBuffer of usage
8671 QRhiBuffer::UsageFlag::IndirectBuffer.
8672
8673 \sa QRhiCommandBuffer::drawIndirect()
8674
8675 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8676 for details.
8677 */
8678
8679/*!
8680 \variable QRhiIndirectDrawCommand::vertexCount
8681*/
8682
8683/*!
8684 \variable QRhiIndirectDrawCommand::instanceCount
8685*/
8686
8687/*!
8688 \variable QRhiIndirectDrawCommand::firstVertex
8689*/
8690
8691/*!
8692 \variable QRhiIndirectDrawCommand::firstInstance
8693*/
8694
8695/*!
8696 \struct QRhiIndexedIndirectDrawCommand
8697 \inmodule QtGuiPrivate
8698 \inheaderfile rhi/qrhi.h
8699 \since 6.12
8700 \brief Indexed draw command.
8701
8702 An indexed draw command that can be uploaded to a QRhiBuffer of usage
8703 QRhiBuffer::UsageFlag::IndirectBuffer.
8704
8705 \sa QRhiCommandBuffer::drawIndexedIndirect()
8706
8707 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8708 for details.
8709 */
8710
8711/*!
8712 \variable QRhiIndexedIndirectDrawCommand::indexCount
8713*/
8714
8715/*!
8716 \variable QRhiIndexedIndirectDrawCommand::instanceCount
8717*/
8718
8719/*!
8720 \variable QRhiIndexedIndirectDrawCommand::firstIndex
8721*/
8722
8723/*!
8724 \variable QRhiIndexedIndirectDrawCommand::vertexOffset
8725*/
8726
8727/*!
8728 \variable QRhiIndexedIndirectDrawCommand::firstInstance
8729*/
8730
8731/*!
8732 \struct QRhiDispatchIndirectCommand
8733 \inmodule QtGuiPrivate
8734 \inheaderfile rhi/qrhi.h
8735 \since 6.13
8736 \brief Compute dispatch command.
8737
8738 A compute dispatch command that can be uploaded to a QRhiBuffer of usage
8739 QRhiBuffer::UsageFlag::IndirectBuffer. The fields specify the number of
8740 local work groups along each dimension and have the same meaning as the
8741 \c x, \c y, \c z parameters of QRhiCommandBuffer::dispatch().
8742
8743 \c y and \c z default to 1, so a one dimensional dispatch only needs \c x
8744 to be set. Note that a count of 0 in any dimension is valid and results in
8745 no work groups being launched at all.
8746
8747 \sa QRhiCommandBuffer::dispatchIndirect()
8748
8749 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8750 for details.
8751 */
8752
8753/*!
8754 \variable QRhiDispatchIndirectCommand::x
8755*/
8756
8757/*!
8758 \variable QRhiDispatchIndirectCommand::y
8759*/
8760
8761/*!
8762 \variable QRhiDispatchIndirectCommand::z
8763*/
8764
8765/*!
8766 \class QRhiIndirectCommandBuffer
8767 \inmodule QtGuiPrivate
8768 \inheaderfile rhi/qrhi.h
8769 \since 6.13
8770 \brief A prerecorded batch of indirect draw commands.
8771
8772 A QRhiIndirectCommandBuffer holds a number of draw commands that are
8773 recorded once and can then be replayed any number of times with a single
8774 QRhiCommandBuffer::executeIndirect() call. It is an alternative to the
8775 buffer-based QRhiCommandBuffer::drawIndirect() family of functions. Under
8776 the hood, it may do exactly the same as does (typical with Vulkan, Direct
8777 3D, and OpenGL), or may be implemented differently (Metal).
8778
8779 Create one with QRhi::newIndirectCommandBuffer(), passing in the type and
8780 the maximum number of commands, and call create(). The (maximum) command
8781 count is mandatory, whichever way the commands are going to be provided: it
8782 is the capacity of the object, and create() fails when it is 0.
8783
8784 \badcode
8785 icb = rhi->newIndirectCommandBuffer(QRhiIndirectCommandBuffer::IndexedDraws, 1024);
8786 if (!icb->create()) { error(); }
8787 \endcode
8788
8789 Record commands with draw() or drawIndexed(), then hand the object to a
8790 resource update batch so that the recorded contents reach the GPU.
8791 commitIndirectCommandBuffer() has to be called after recording and before
8792 the pass that executes the commands. It is a no-op when nothing changed
8793 since the last time, so calling it every frame is cheap.
8794
8795 Executing happens inside a render pass:
8796
8797 \badcode
8798 icb->clear();
8799 for (const Item &item : items)
8800 icb->drawIndexed(item.indexCount, 1, item.firstIndex, item.vertexOffset);
8801
8802 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
8803 u->commitIndirectCommandBuffer(icb);
8804
8805 cb->beginPass(rt, Qt::black, { 1.0f, 0 }, u);
8806 cb->setGraphicsPipeline(ps);
8807 cb->setVertexInput(0, 1, &vbufBinding, ibuf, 0, QRhiCommandBuffer::IndexUInt16);
8808 cb->setShaderResources();
8809 cb->executeIndirect(icb);
8810 cb->endPass();
8811 \endcode
8812
8813 The commands can also be generated on the GPU instead of being recorded on
8814 the CPU. In that case fill a buffer with QRhiIndirectDrawCommand or
8815 QRhiIndexedIndirectDrawCommand entries from a compute shader, and call
8816 QRhiCommandBuffer::buildIndirect() with that buffer. That call must happen
8817 outside of any pass. The CPU-side recording functions of
8818 QRhiIndirectCommandBuffer are not used in this case.
8819
8820 \badcode
8821 cb->beginComputePass();
8822 ... // a cb->dispatch() to invoke a compute shader that writes to indirectBuf
8823 cb->endComputePass();
8824
8825 QRhiIndirectCommandBufferBuildInfo buildInfo;
8826 buildInfo.topology = ps->topology();
8827 buildInfo.sourceBuffer = indirectBuf;
8828 buildInfo.commandCount = itemCount; // as many as the compute shader wrote
8829 buildInfo.indexBuffer = indexBuffer;
8830 buildInfo.indexFormat = QRhiCommandBuffer::IndexUInt16;
8831 cb->buildIndirect(icb, buildInfo);
8832
8833 cb->beginPass(rt, Qt::black, { 1.0f, 0 });
8834 cb->setGraphicsPipeline(ps);
8835 cb->setVertexInput(0, 1, &vbufBinding, ibuf, 0, QRhiCommandBuffer::IndexUInt16);
8836 cb->setShaderResources();
8837 cb->executeIndirect(icb);
8838 cb->endPass();
8839 \endcode
8840
8841 When the number of commands is itself decided on the device, set
8842 QRhiIndirectCommandBufferBuildInfo::countBuffer instead of working out
8843 \c itemCount on the CPU. See \l{Command counts} below.
8844
8845 \section2 Command counts
8846
8847 Three counts are involved, and they are not the same thing:
8848
8849 \list
8850
8851 \li maxCommandCount() is the capacity. It is fixed at create() time and
8852 sizes whatever native object the backend needs. Neither of the two ways of
8853 providing commands can exceed it; attempting to does not grow the object.
8854
8855 \li recordedCommandCount() is how many draw() or drawIndexed() calls were
8856 made since the last clear(). It only concerns the CPU-recorded case.
8857
8858 \li commandCount() is how many commands QRhiCommandBuffer::executeIndirect()
8859 issues by default. For a CPU-recorded indirect command buffer that is
8860 recordedCommandCount(). Once QRhiCommandBuffer::buildIndirect() has been
8861 called, isGpuBuilt() returns true and commandCount() is the count resolved
8862 from QRhiIndirectCommandBufferBuildInfo::commandCount instead (but note that
8863 that value is the actual command count only when no
8864 \l{QRhiIndirectCommandBufferBuildInfo::}countBuffer is set, is just a
8865 maximum with a counter buffer present).
8866
8867 \endlist
8868
8869 The size of QRhiIndirectCommandBufferBuildInfo::sourceBuffer plays no part
8870 in any of this: no count is ever derived from it. The buffer is written by
8871 the GPU and is free to be larger than the number of commands actually in
8872 it, so leaving QRhiIndirectCommandBufferBuildInfo::commandCount at 0 does
8873 not mean "as many as fit", it means maxCommandCount().
8874
8875 A device-side count, via QRhiIndirectCommandBufferBuildInfo::countBuffer,
8876 narrows the count further when the commands are executed, and can only
8877 reduce it: the value in the count buffer is clamped to what
8878 commandCount() returns.
8879
8880 Either way, the indirect command buffer is fully prepared before the render
8881 pass begins. That is what separates it from the buffer-based
8882 QRhiCommandBuffer::drawIndirect() family, where some backends (Metal above a
8883 certain draw count, and always for the count variants) have to interrupt and
8884 restart the render pass in order to encode the commands. Such an
8885 interruption costs a QRhiRenderBuffer depth-stencil buffer its contents
8886 unless QRhiRenderBuffer::NoTransientBacking was set, and may also be degrading
8887 performance due to having to reload the color buffer values. With
8888 executeIndirect() the question does not arise.
8889
8890 For Metal, the buffer-based API implies (ahove a certain draw count, or
8891 whhen using the count variants) having to run a compute kernel to create an
8892 MTLIndirectCommandBuffer from the Vulkan/Direct 3D/OpenGL style indirect
8893 buffer. With QRhiIndirectCommandBuffer this is not always necessary, because
8894 now, at least when the commands are generated on the CPU side, an
8895 MTLIndirectCommandBuffer can be created and set up normally, by calling
8896 MTLIndirectCommandBuffer's Objective-C API, instead of having to inject a
8897 compute pass. When generating the commands on the GPU, the extra compute
8898 pass is still necessary, but at least it will not interrupt the render pass,
8899 by design, unlike with the direct buffer-based API. Note however that using
8900 MTLIndirectCommandBuffer natively from C++/Objective-C to perform repeated
8901 CPU-side draw call generation can prove to be quite expensive (when
8902 frequently re-recording a larger set of draw commands), compared to the
8903 GPU-side draw command generation, even though that involves an extra encoding
8904 compute pass to "convert" the Vulkan/Direct 3D/OpenGL style indirect buffer
8905 to what Metal prefers. See the next section.
8906
8907 \section2 Recording on the CPU or building on the GPU
8908
8909 The two ways of populating an indirect command buffer are not equivalent in
8910 cost, and the difference grows with the number of commands.
8911
8912 Recording with draw() or drawIndexed() is work proportional to the number of
8913 commands, and it is repeated whenever the contents change. Where that work
8914 lands depends on the backend: those that keep the commands in a buffer
8915 upload it from QRhiResourceUpdateBatch::commitIndirectCommandBuffer(),
8916 whereas Metal encodes each command individually into a native
8917 \c MTLIndirectCommandBuffer, one native call per command, and does so from
8918 QRhiCommandBuffer::executeIndirect().
8919
8920 Either way the result is cached and keyed on the recorded contents, so an
8921 indirect command buffer that is recorded once and then executed unchanged
8922 frame after frame costs nothing beyond the first few frames. That is the
8923 case CPU recording is meant for: a command set that is stable, or changes
8924 rarely, relative to how often it is executed.
8925
8926 The opposite case - many commands, cleared and re-recorded every frame - is
8927 the one to avoid. Regenerating tens of thousands of commands per frame that
8928 way can be an order of magnitude more expensive on Apple platforms than
8929 filling a QRhiBuffer and calling QRhiCommandBuffer::drawIndexedIndirect() on
8930 it, because of the per-command native encoding. When the command set is both
8931 large and regenerated every frame, generate it on the GPU and use
8932 QRhiCommandBuffer::buildIndirect(); the alternative is to stay with the
8933 buffer-based drawIndirect() family and accept the render pass interruption
8934 it may cause (which is still not recommended, even if it would perform
8935 better).
8936
8937 A given QRhiIndirectCommandBuffer holds one kind of command: either
8938 non-indexed draws (\c Draws) or indexed draws (\c IndexedDraws), never a
8939 mix of the two. This mirrors what the underlying APIs can express: a single
8940 indirect draw call always has one command type and one stride.
8941
8942 The requirements are the same as for the indirect draws this stands in for:
8943 QRhi::DrawIndirect has to be supported, the graphics pipeline should be
8944 created with \l{QRhiGraphicsPipeline::UsesIndirectDraws}{UsesIndirectDraws},
8945 and a count buffer additionally needs QRhi::DrawIndirectCount to be
8946 supported.
8947
8948 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8949 for details.
8950
8951 \sa QRhiCommandBuffer::executeIndirect(), QRhiCommandBuffer::drawIndirect()
8952 */
8953
8954/*!
8955 \enum QRhiIndirectCommandBuffer::Type
8956 Specifies the kind of commands an indirect command buffer holds.
8957
8958 \value Draws Non-indexed draw commands, recorded with draw().
8959 \value IndexedDraws Indexed draw commands, recorded with drawIndexed().
8960 */
8961
8962/*!
8963 \fn QRhiIndirectCommandBuffer::Type QRhiIndirectCommandBuffer::type() const
8964 \return the type of commands this indirect command buffer holds.
8965 */
8966
8967/*!
8968 \fn void QRhiIndirectCommandBuffer::setType(Type t)
8969
8970 Sets the command type \a t. The type is normally specified in
8971 QRhi::newIndirectCommandBuffer(), so this function is only used when it has
8972 to be changed. As with other setters, it only takes effect when calling
8973 create().
8974 */
8975
8976/*!
8977 \fn quint32 QRhiIndirectCommandBuffer::maxCommandCount() const
8978 \return the capacity, i.e. the maximum number of commands.
8979 */
8980
8981/*!
8982 \fn void QRhiIndirectCommandBuffer::setMaxCommandCount(quint32 count)
8983
8984 Sets the capacity, the maximum number of commands, to \a count. The
8985 capacity is normally specified in QRhi::newIndirectCommandBuffer(), so this
8986 function is only used when it has to be changed. As with other setters, it
8987 only takes effect when calling create(), which fails when \a count is 0.
8988
8989 The capacity applies regardless of how the commands are going to be
8990 provided: recording them with draw() and drawIndexed() and building them
8991 with QRhiCommandBuffer::buildIndirect() are both bounded by it.
8992
8993 draw() and drawIndexed() ignore, with a warning, any command past the first
8994 \a count ones. QRhiCommandBuffer::buildIndirect() clamps, also with a
8995 warning, when QRhiIndirectCommandBufferBuildInfo::commandCount is larger.
8996
8997 \sa commandCount(), recordedCommandCount()
8998 */
8999
9000/*!
9001 \fn quint32 QRhiIndirectCommandBuffer::recordedCommandCount() const
9002
9003 \return the number of commands recorded with draw() or drawIndexed() since
9004 the last clear().
9005
9006 This is unaffected by QRhiCommandBuffer::buildIndirect(): once the commands
9007 come from the GPU, whatever was recorded on the CPU is ignored. Use
9008 commandCount() to get the number of commands that will actually be
9009 executed.
9010 */
9011
9012/*!
9013 \fn bool QRhiIndirectCommandBuffer::isGpuBuilt() const
9014
9015 \return \c true when QRhiCommandBuffer::buildIndirect() has been called on
9016 this indirect command buffer, meaning its contents come from a QRhiBuffer
9017 instead of from draw() and drawIndexed().
9018
9019 Once true, this stays true until the next create().
9020 */
9021
9022/*!
9023 \fn quint32 QRhiIndirectCommandBuffer::commandCount() const
9024
9025 \return the number of commands QRhiCommandBuffer::executeIndirect() issues
9026 by default.
9027
9028 This is recordedCommandCount() for a CPU-recorded indirect command buffer,
9029 and the count resolved from
9030 QRhiIndirectCommandBufferBuildInfo::commandCount once
9031 QRhiCommandBuffer::buildIndirect() has been called.
9032
9033 A count buffer, if there is one, can reduce the number of draws further at
9034 execution time. This function does not, and cannot, account for that.
9035 */
9036
9037/*!
9038 \fn virtual bool QRhiIndirectCommandBuffer::create() = 0
9039
9040 Creates the corresponding native objects.
9041
9042 Fails when maxCommandCount() is 0.
9043
9044 A given QRhiIndirectCommandBuffer takes its commands either from draw() and
9045 drawIndexed() followed by
9046 QRhiResourceUpdateBatch::commitIndirectCommandBuffer(), or from
9047 QRhiCommandBuffer::buildIndirect(), but not from both. Moving to the latter
9048 is one-way: clear() does not undo it, and neither does a subsequent
9049 commitIndirectCommandBuffer(); isGpuBuilt() stays true and the commands keep
9050 coming from the buffer. Call create() again to get an indirect command
9051 buffer that is populated from the CPU once more.
9052
9053 \note Like with every other QRhi resource, destroy() gives up the contents,
9054 and so create() starts from an empty indirect command buffer:
9055 recordedCommandCount() is 0 afterwards. Setting a different type() or
9056 maxCommandCount() and calling create() again therefore needs the commands
9057 to be recorded again as well.
9058
9059 \return \c true when successful, \c false when a graphics operation failed.
9060 */
9061
9062/*!
9063 \internal
9064 */
9065QRhiIndirectCommandBuffer::QRhiIndirectCommandBuffer(QRhiImplementation *rhi, Type type_,
9066 quint32 maxCommandCount_)
9067 : QRhiResource(rhi),
9068 m_type(type_), m_maxCommandCount(maxCommandCount_)
9069{
9070}
9071
9072/*!
9073 \return the resource type.
9074 */
9075QRhiResource::Type QRhiIndirectCommandBuffer::resourceType() const
9076{
9077 return IndirectCommandBuffer;
9078}
9079
9080/*!
9081 Discards all commands recorded so far.
9082
9083 Can be called at any time, also before create(). The recorded contents only
9084 become visible to the GPU once the object is passed to
9085 QRhiResourceUpdateBatch::commitIndirectCommandBuffer().
9086
9087 This resets recordedCommandCount() to 0. It does not undo a
9088 QRhiCommandBuffer::buildIndirect(): an indirect command buffer that gets
9089 its commands from the GPU keeps doing so, and commandCount() is unchanged.
9090
9091 \note Clearing and re-recording invalidates whatever the backend cached for
9092 the previous contents, so the per-command cost of recording is paid again.
9093 Call this only when the commands actually have to change. See
9094 \l{Recording on the CPU or building on the GPU} for why that matters at high
9095 command counts.
9096 */
9097void QRhiIndirectCommandBuffer::clear()
9098{
9099 m_data.clear();
9100 m_commandCount = 0;
9101 m_generation += 1;
9102}
9103
9104/*!
9105 Records a non-indexed draw command with \a vertexCount, \a instanceCount,
9106 \a firstVertex, and \a firstInstance.
9107
9108 The semantics are the same as QRhiCommandBuffer::draw().
9109
9110 \note Only valid on an indirect command buffer of type Draws.
9111 */
9112void QRhiIndirectCommandBuffer::draw(quint32 vertexCount, quint32 instanceCount,
9113 quint32 firstVertex, quint32 firstInstance)
9114{
9115 if (m_type != Draws) {
9116 qWarning("QRhiIndirectCommandBuffer: draw() on an IndexedDraws indirect command buffer; ignored");
9117 return;
9118 }
9119 if (m_commandCount == m_maxCommandCount) {
9120 qWarning("QRhiIndirectCommandBuffer: maxCommandCount (%u) reached; command ignored",
9121 m_maxCommandCount);
9122 return;
9123 }
9124 const QRhiIndirectDrawCommand cmd = { vertexCount, instanceCount, firstVertex, firstInstance };
9125 m_data.append(reinterpret_cast<const char *>(&cmd), sizeof(cmd));
9126 m_commandCount += 1;
9127 m_generation += 1;
9128}
9129
9130/*!
9131 Records an indexed draw command with \a indexCount, \a instanceCount, \a
9132 firstIndex, \a vertexOffset, and \a firstInstance.
9133
9134 The semantics are the same as QRhiCommandBuffer::drawIndexed().
9135
9136 \note Only valid on an indirect command buffer of type IndexedDraws.
9137 */
9138void QRhiIndirectCommandBuffer::drawIndexed(quint32 indexCount, quint32 instanceCount,
9139 quint32 firstIndex, qint32 vertexOffset,
9140 quint32 firstInstance)
9141{
9142 if (m_type != IndexedDraws) {
9143 qWarning("QRhiIndirectCommandBuffer: drawIndexed() on a Draws indirect command buffer; ignored");
9144 return;
9145 }
9146 if (m_commandCount == m_maxCommandCount) {
9147 qWarning("QRhiIndirectCommandBuffer: maxCommandCount (%u) reached; command ignored",
9148 m_maxCommandCount);
9149 return;
9150 }
9151 const QRhiIndexedIndirectDrawCommand cmd = { indexCount, instanceCount, firstIndex,
9152 vertexOffset, firstInstance };
9153 m_data.append(reinterpret_cast<const char *>(&cmd), sizeof(cmd));
9154 m_commandCount += 1;
9155 m_generation += 1;
9156}
9157
9158/*!
9159 \struct QRhiIndirectCommandBufferBuildInfo
9160 \inmodule QtGuiPrivate
9161 \inheaderfile rhi/qrhi.h
9162 \since 6.13
9163 \brief Describes how to build an indirect command buffer from a QRhiBuffer.
9164
9165 \sa QRhiCommandBuffer::buildIndirect()
9166
9167 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9168 for details.
9169 */
9170
9171/*!
9172 \variable QRhiIndirectCommandBufferBuildInfo::topology
9173
9174 The topology the commands will be drawn with. Must match the topology of the
9175 graphics pipeline that is set when QRhiCommandBuffer::executeIndirect() is
9176 called. Some backends need it in order to build their native indirect
9177 command buffer, and it is not available to them outside of a render pass.
9178*/
9179
9180/*!
9181 \variable QRhiIndirectCommandBufferBuildInfo::sourceBuffer
9182
9183 The buffer holding the QRhiIndirectDrawCommand or
9184 QRhiIndexedIndirectDrawCommand entries. Must have IndirectBuffer usage.
9185
9186 Its size is not used to work out how many commands there are, see
9187 commandCount.
9188*/
9189
9190/*!
9191 \variable QRhiIndirectCommandBufferBuildInfo::sourceBufferOffset
9192*/
9193
9194/*!
9195 \variable QRhiIndirectCommandBufferBuildInfo::commandCount
9196
9197 The number of commands to take from sourceBuffer. This is what
9198 QRhiIndirectCommandBuffer::commandCount() reports afterwards, and so how
9199 many draws QRhiCommandBuffer::executeIndirect() issues by default.
9200
9201 0 means QRhiIndirectCommandBuffer::maxCommandCount(). It does not mean "as
9202 many as fit in sourceBuffer": a buffer written by the GPU can be larger
9203 than the number of commands in it, so no count is ever derived from its
9204 size. A value above QRhiIndirectCommandBuffer::maxCommandCount() is clamped
9205 to it, with a warning.
9206
9207 \note Specifying countBuffer changes what this value means: it stops being
9208 the number of commands and becomes the \e maximum number of commands, with
9209 the device-side count in countBuffer deciding the actual number. Without a
9210 countBuffer, exactly this many commands are executed.
9211*/
9212
9213/*!
9214 \variable QRhiIndirectCommandBufferBuildInfo::stride
9215
9216 The byte distance between two commands in sourceBuffer. 0 means the size of
9217 the corresponding command struct.
9218*/
9219
9220/*!
9221 \variable QRhiIndirectCommandBufferBuildInfo::countBuffer
9222
9223 An optional buffer whose first quint32 holds the number of commands to
9224 execute. Requires QRhi::DrawIndirectCount.
9225
9226 \note Setting this turns commandCount into an upper bound. The device-side
9227 value is clamped to it, so a count buffer can only ever reduce the number
9228 of draws, never raise it.
9229*/
9230
9231/*!
9232 \variable QRhiIndirectCommandBufferBuildInfo::countBufferOffset
9233*/
9234
9235/*!
9236 \variable QRhiIndirectCommandBufferBuildInfo::indexBuffer
9237
9238 The index buffer the commands index into. Required for IndexedDraws.
9239*/
9240
9241/*!
9242 \variable QRhiIndirectCommandBufferBuildInfo::indexBufferOffset
9243*/
9244
9245/*!
9246 \variable QRhiIndirectCommandBufferBuildInfo::indexFormat
9247*/
9248
9250 Type type,
9251 quint32 maxCommandCount)
9253{
9254}
9255
9260
9262{
9263 // Unconditionally, also when there is nothing else to do: like with every
9264 // other resource, destroy() gives up the contents. Carrying a recording
9265 // over into the next create() would not survive a changed maxCommandCount
9266 // or type.
9267 clear();
9268
9269 if (!valid)
9270 return;
9271
9272 delete buffer;
9273 buffer = nullptr;
9274 uploadedGeneration = 0;
9275 buildInfo = {};
9276 m_gpuBuilt = false;
9277 m_gpuBuiltCommandCount = 0;
9278 valid = false;
9279
9280 if (m_rhi)
9281 m_rhi->unregisterResource(this);
9282}
9283
9285{
9286 // Either way the recorded commands go: they may not fit maxCommandCount()
9287 // or match type() anymore.
9288 if (valid)
9289 destroy();
9290 else
9291 clear();
9292
9293 if (!m_maxCommandCount) {
9294 qWarning("QRhiIndirectCommandBuffer: maxCommandCount is 0");
9295 return false;
9296 }
9297
9298 valid = true;
9299 m_rhi->registerResource(this);
9300 return true;
9301}
9302
9304{
9305 // m_gpuBuilt: the commands come from the source buffer from now on, so
9306 // there is nothing to upload, as documented for commitIndirectCommandBuffer().
9307 if (!valid || m_gpuBuilt || m_data.isEmpty() || uploadedGeneration == m_generation)
9308 return;
9309
9310 if (!buffer) {
9311 const quint32 commandSize = m_type == IndexedDraws ? sizeof(QRhiIndexedIndirectDrawCommand)
9312 : sizeof(QRhiIndirectDrawCommand);
9313 buffer = m_rhi->createBuffer(QRhiBuffer::Static, QRhiBuffer::IndirectBuffer,
9314 m_maxCommandCount * commandSize);
9315 if (!buffer || !buffer->create()) {
9316 delete buffer;
9317 buffer = nullptr;
9318 return;
9319 }
9320 }
9321
9322 u->uploadStaticBuffer(buffer, 0, quint32(m_data.size()), m_data.constData());
9323 uploadedGeneration = m_generation;
9324}
9325
9326void QRhiBufferBackedIndirectCommandBuffer::build(const QRhiIndirectCommandBufferBuildInfo &info)
9327{
9328 buildInfo = info;
9329 quint32 count = info.commandCount ? info.commandCount : m_maxCommandCount;
9330 if (count > m_maxCommandCount) {
9331 qWarning("QRhiIndirectCommandBuffer: buildIndirect() with commandCount %u exceeds "
9332 "maxCommandCount %u; clamping", count, m_maxCommandCount);
9333 count = m_maxCommandCount;
9334 }
9335 m_gpuBuilt = true;
9336 m_gpuBuiltCommandCount = count;
9337}
9338
9340 quint32 firstCommand,
9341 quint32 commandCount)
9342{
9343 const bool indexed = m_type == IndexedDraws;
9344 const quint32 canonicalStride = m_type == IndexedDraws ? sizeof(QRhiIndexedIndirectDrawCommand)
9345 : sizeof(QRhiIndirectDrawCommand);
9346
9347 if (m_gpuBuilt) {
9348 const quint32 stride = buildInfo.stride ? buildInfo.stride : canonicalStride;
9349 const quint32 available = m_gpuBuiltCommandCount > firstCommand
9350 ? m_gpuBuiltCommandCount - firstCommand : 0;
9351 const quint32 count = qMin(commandCount, available);
9352 if (!count)
9353 return;
9354 const quint32 offset = buildInfo.sourceBufferOffset + firstCommand * stride;
9355 if (buildInfo.countBuffer) {
9356 // Note that a non-zero firstCommand shifts the window, but the
9357 // device-side count is still relative to the start of that window.
9358 if (indexed) {
9359 cb->drawIndexedIndirectCount(buildInfo.sourceBuffer, offset,
9360 buildInfo.countBuffer, buildInfo.countBufferOffset,
9361 count, stride);
9362 } else {
9363 cb->drawIndirectCount(buildInfo.sourceBuffer, offset,
9364 buildInfo.countBuffer, buildInfo.countBufferOffset,
9365 count, stride);
9366 }
9367 } else {
9368 if (indexed)
9369 cb->drawIndexedIndirect(buildInfo.sourceBuffer, offset, count, stride);
9370 else
9371 cb->drawIndirect(buildInfo.sourceBuffer, offset, count, stride);
9372 }
9373 return;
9374 }
9375
9376 if (!buffer) {
9377 // Metal encodes on the spot in executeIndirect() and so needs no
9378 // commit. Everywhere else a missing one means drawing nothing.
9379 if (m_commandCount) {
9380 qWarning("QRhiIndirectCommandBuffer: %u command(s) recorded but never flushed with "
9381 "QRhiResourceUpdateBatch::commitIndirectCommandBuffer(); nothing to draw",
9382 m_commandCount);
9383 }
9384 return;
9385 }
9386 if (!m_commandCount)
9387 return;
9388
9389 const quint32 available = m_commandCount > firstCommand ? m_commandCount - firstCommand : 0;
9390 const quint32 count = qMin(commandCount, available);
9391 if (!count)
9392 return;
9393
9394 const quint32 offset = firstCommand * canonicalStride;
9395 if (indexed)
9396 cb->drawIndexedIndirect(buffer, offset, count, canonicalStride);
9397 else
9398 cb->drawIndirect(buffer, offset, count, canonicalStride);
9399}
9400
9401QRhiIndirectCommandBuffer *QRhiImplementation::createIndirectCommandBuffer(QRhiIndirectCommandBuffer::Type type,
9402 quint32 maxCommandCount)
9403{
9404 return new QRhiBufferBackedIndirectCommandBuffer(this, type, maxCommandCount);
9405}
9406
9407void QRhiImplementation::buildIndirect(QRhiCommandBuffer *cb, QRhiIndirectCommandBuffer *icb,
9408 const QRhiIndirectCommandBufferBuildInfo &info)
9409{
9410 Q_UNUSED(cb);
9411 static_cast<QRhiBufferBackedIndirectCommandBuffer *>(icb)->build(info);
9412}
9413
9414void QRhiImplementation::executeIndirect(QRhiCommandBuffer *cb, QRhiIndirectCommandBuffer *icb,
9415 quint32 firstCommand, quint32 commandCount)
9416{
9417 static_cast<QRhiBufferBackedIndirectCommandBuffer *>(icb)->execute(cb, firstCommand, commandCount);
9418}
9419
9420void QRhiImplementation::commitIndirectCommandBuffer(QRhiResourceUpdateBatch *u,
9421 QRhiIndirectCommandBuffer *icb)
9422{
9423 static_cast<QRhiBufferBackedIndirectCommandBuffer *>(icb)->enqueueUpload(u);
9424}
9425
9426/*!
9427 \class QRhiCommandBuffer
9428 \inmodule QtGuiPrivate
9429 \inheaderfile rhi/qrhi.h
9430 \since 6.6
9431 \brief Command buffer resource.
9432
9433 Not creatable by applications at the moment. The only ways to obtain a
9434 valid QRhiCommandBuffer are to get it from the targeted swapchain via
9435 QRhiSwapChain::currentFrameCommandBuffer(), or, in case of rendering
9436 completely offscreen, initializing one via QRhi::beginOffscreenFrame().
9437
9438 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9439 for details.
9440 */
9441
9442/*!
9443 \enum QRhiCommandBuffer::IndexFormat
9444 Specifies the index data type
9445
9446 \value IndexUInt16 Unsigned 16-bit (quint16)
9447 \value IndexUInt32 Unsigned 32-bit (quint32)
9448 */
9449
9450/*!
9451 \enum QRhiCommandBuffer::BeginPassFlag
9452 Flag values for QRhi::beginPass()
9453
9454 \value ExternalContent Specifies that there will be a call to
9455 QRhiCommandBuffer::beginExternal() in this pass. Some backends, Vulkan in
9456 particular, will fail if this flag is not set and beginExternal() is still
9457 called.
9458
9459 \value DoNotTrackResourcesForCompute Specifies that there is no need to
9460 track resources used in this pass if the only purpose of such tracking is
9461 to generate barriers for compute. Implies that there are no compute passes
9462 in the frame. This is an optimization hint that may be taken into account
9463 by certain backends, OpenGL in particular, allowing them to skip certain
9464 operations. When this flag is set for a render pass in a frame, calling
9465 \l{QRhiCommandBuffer::beginComputePass()}{beginComputePass()} in that frame
9466 may lead to unexpected behavior, depending on the resource dependencies
9467 between the render and compute passes.
9468 */
9469
9470/*!
9471 \typedef QRhiCommandBuffer::DynamicOffset
9472
9473 Synonym for std::pair<int, quint32>. The first entry is the binding, the second
9474 is the offset in the buffer.
9475*/
9476
9477/*!
9478 \typedef QRhiCommandBuffer::VertexInput
9479
9480 Synonym for std::pair<QRhiBuffer *, quint32>. The second entry is an offset in
9481 the buffer specified by the first.
9482*/
9483
9484/*!
9485 \internal
9486 */
9487QRhiCommandBuffer::QRhiCommandBuffer(QRhiImplementation *rhi)
9488 : QRhiResource(rhi)
9489{
9490}
9491
9492/*!
9493 \return the resource type.
9494 */
9495QRhiResource::Type QRhiCommandBuffer::resourceType() const
9496{
9497 return CommandBuffer;
9498}
9499
9500static const char *resourceTypeStr(const QRhiResource *res)
9501{
9502 switch (res->resourceType()) {
9503 case QRhiResource::Buffer:
9504 return "Buffer";
9505 case QRhiResource::Texture:
9506 return "Texture";
9507 case QRhiResource::Sampler:
9508 return "Sampler";
9509 case QRhiResource::RenderBuffer:
9510 return "RenderBuffer";
9511 case QRhiResource::RenderPassDescriptor:
9512 return "RenderPassDescriptor";
9513 case QRhiResource::SwapChainRenderTarget:
9514 return "SwapChainRenderTarget";
9515 case QRhiResource::TextureRenderTarget:
9516 return "TextureRenderTarget";
9517 case QRhiResource::ShaderResourceBindings:
9518 return "ShaderResourceBindings";
9519 case QRhiResource::GraphicsPipeline:
9520 return "GraphicsPipeline";
9521 case QRhiResource::SwapChain:
9522 return "SwapChain";
9523 case QRhiResource::ComputePipeline:
9524 return "ComputePipeline";
9525 case QRhiResource::CommandBuffer:
9526 return "CommandBuffer";
9527 case QRhiResource::ShadingRateMap:
9528 return "ShadingRateMap";
9529 case QRhiResource::IndirectCommandBuffer:
9530 return "IndirectCommandBuffer";
9531 }
9532
9533 Q_UNREACHABLE_RETURN("");
9534}
9535
9536QRhiImplementation::~QRhiImplementation()
9537{
9538 qDeleteAll(resUpdPool);
9539
9540 // Be nice and show something about leaked stuff. Though we may not get
9541 // this far with some backends where the allocator or the api may check
9542 // and freak out for unfreed graphics objects in the derived dtor already.
9543#ifndef QT_NO_DEBUG
9544 // debug builds: just do it always
9545 static bool leakCheck = true;
9546#else
9547 // release builds: opt-in
9548 static bool leakCheck = qEnvironmentVariableIntValue("QT_RHI_LEAK_CHECK");
9549#endif
9550 if (!resources.isEmpty()) {
9551 if (leakCheck) {
9552 qWarning("QRhi %p going down with %d unreleased resources that own native graphics objects. This is not nice.",
9553 q, int(resources.size()));
9554 }
9555 for (auto it = resources.cbegin(), end = resources.cend(); it != end; ++it) {
9556 QRhiResource *res = it.key();
9557 const bool ownsNativeResources = it.value();
9558 if (leakCheck && ownsNativeResources)
9559 qWarning(" %s resource %p (%s)", resourceTypeStr(res), res, res->m_objectName.constData());
9560
9561 // Null out the resource's rhi pointer. This is why it makes sense to do null
9562 // checks in the destroy() implementations of the various resource types. It
9563 // allows to survive in bad applications that somehow manage to destroy a
9564 // resource of a QRhi after the QRhi itself.
9565 res->m_rhi = nullptr;
9566 }
9567 }
9568}
9569
9570bool QRhiImplementation::isCompressedFormat(QRhiTexture::Format format) const
9571{
9572 return (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
9573 || (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
9574 || (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12);
9575}
9576
9577bool QRhiImplementation::compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
9578 quint32 *bpl, quint32 *byteSize,
9579 QSize *blockDim) const
9580{
9581 int xdim = 4;
9582 int ydim = 4;
9583 quint32 blockSize = 0;
9584
9585 switch (format) {
9586 case QRhiTexture::BC1:
9587 blockSize = 8;
9588 break;
9589 case QRhiTexture::BC2:
9590 blockSize = 16;
9591 break;
9592 case QRhiTexture::BC3:
9593 blockSize = 16;
9594 break;
9595 case QRhiTexture::BC4:
9596 blockSize = 8;
9597 break;
9598 case QRhiTexture::BC5:
9599 blockSize = 16;
9600 break;
9601 case QRhiTexture::BC6H:
9602 blockSize = 16;
9603 break;
9604 case QRhiTexture::BC7:
9605 blockSize = 16;
9606 break;
9607
9608 case QRhiTexture::ETC2_RGB8:
9609 blockSize = 8;
9610 break;
9611 case QRhiTexture::ETC2_RGB8A1:
9612 blockSize = 8;
9613 break;
9614 case QRhiTexture::ETC2_RGBA8:
9615 blockSize = 16;
9616 break;
9617
9618 case QRhiTexture::ASTC_4x4:
9619 blockSize = 16;
9620 break;
9621 case QRhiTexture::ASTC_5x4:
9622 blockSize = 16;
9623 xdim = 5;
9624 break;
9625 case QRhiTexture::ASTC_5x5:
9626 blockSize = 16;
9627 xdim = ydim = 5;
9628 break;
9629 case QRhiTexture::ASTC_6x5:
9630 blockSize = 16;
9631 xdim = 6;
9632 ydim = 5;
9633 break;
9634 case QRhiTexture::ASTC_6x6:
9635 blockSize = 16;
9636 xdim = ydim = 6;
9637 break;
9638 case QRhiTexture::ASTC_8x5:
9639 blockSize = 16;
9640 xdim = 8;
9641 ydim = 5;
9642 break;
9643 case QRhiTexture::ASTC_8x6:
9644 blockSize = 16;
9645 xdim = 8;
9646 ydim = 6;
9647 break;
9648 case QRhiTexture::ASTC_8x8:
9649 blockSize = 16;
9650 xdim = ydim = 8;
9651 break;
9652 case QRhiTexture::ASTC_10x5:
9653 blockSize = 16;
9654 xdim = 10;
9655 ydim = 5;
9656 break;
9657 case QRhiTexture::ASTC_10x6:
9658 blockSize = 16;
9659 xdim = 10;
9660 ydim = 6;
9661 break;
9662 case QRhiTexture::ASTC_10x8:
9663 blockSize = 16;
9664 xdim = 10;
9665 ydim = 8;
9666 break;
9667 case QRhiTexture::ASTC_10x10:
9668 blockSize = 16;
9669 xdim = ydim = 10;
9670 break;
9671 case QRhiTexture::ASTC_12x10:
9672 blockSize = 16;
9673 xdim = 12;
9674 ydim = 10;
9675 break;
9676 case QRhiTexture::ASTC_12x12:
9677 blockSize = 16;
9678 xdim = ydim = 12;
9679 break;
9680
9681 default:
9682 Q_UNREACHABLE();
9683 break;
9684 }
9685
9686 const quint32 wblocks = quint32((qint64(qMax(0, size.width())) + xdim - 1) / xdim);
9687 const quint32 hblocks = quint32((qint64(qMax(0, size.height())) + ydim - 1) / ydim);
9688
9689 if (blockDim)
9690 *blockDim = QSize(xdim, ydim);
9691
9692 // Compute in 64-bit, as safety for extreme geometry that would not fit.
9693 // wblocks and hblocks are at most 2^29 and blockSize at most 16.
9694 const quint64 bytesPerLine = quint64(wblocks) * quint64(blockSize);
9695 const quint64 totalSize = quint64(wblocks) * quint64(hblocks) * quint64(blockSize);
9696 if (bytesPerLine > std::numeric_limits<quint32>::max()
9697 || totalSize > std::numeric_limits<quint32>::max())
9698 {
9699 qWarning("Compressed texture of size %dx%d with format %d has a byte size of %llu "
9700 "which is too large to be handled",
9701 size.width(), size.height(), int(format), totalSize);
9702 if (bpl)
9703 *bpl = 0;
9704 if (byteSize)
9705 *byteSize = 0;
9706 return false;
9707 }
9708
9709 if (bpl)
9710 *bpl = quint32(bytesPerLine);
9711 if (byteSize)
9712 *byteSize = quint32(totalSize);
9713
9714 return true;
9715}
9716
9717bool QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSize &size,
9718 quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const
9719{
9720 if (isCompressedFormat(format))
9721 return compressedFormatInfo(format, size, bpl, byteSize, nullptr);
9722
9723 quint32 bpc = 0;
9724 switch (format) {
9725 case QRhiTexture::RGBA8:
9726 bpc = 4;
9727 break;
9728 case QRhiTexture::BGRA8:
9729 bpc = 4;
9730 break;
9731 case QRhiTexture::R8:
9732 bpc = 1;
9733 break;
9734 case QRhiTexture::RG8:
9735 bpc = 2;
9736 break;
9737 case QRhiTexture::R16:
9738 bpc = 2;
9739 break;
9740 case QRhiTexture::RG16:
9741 bpc = 4;
9742 break;
9743 case QRhiTexture::RED_OR_ALPHA8:
9744 bpc = 1;
9745 break;
9746
9747 case QRhiTexture::RGBA16F:
9748 bpc = 8;
9749 break;
9750 case QRhiTexture::RGBA32F:
9751 bpc = 16;
9752 break;
9753 case QRhiTexture::R16F:
9754 bpc = 2;
9755 break;
9756 case QRhiTexture::R32F:
9757 bpc = 4;
9758 break;
9759
9760 case QRhiTexture::RGB10A2:
9761 bpc = 4;
9762 break;
9763
9764 case QRhiTexture::D16:
9765 bpc = 2;
9766 break;
9767 case QRhiTexture::D24:
9768 case QRhiTexture::D24S8:
9769 case QRhiTexture::D32F:
9770 bpc = 4;
9771 break;
9772
9773 case QRhiTexture::D32FS8:
9774 bpc = 8;
9775 break;
9776
9777 case QRhiTexture::R8SI:
9778 case QRhiTexture::R8UI:
9779 bpc = 1;
9780 break;
9781 case QRhiTexture::R32SI:
9782 case QRhiTexture::R32UI:
9783 bpc = 4;
9784 break;
9785 case QRhiTexture::RG32SI:
9786 case QRhiTexture::RG32UI:
9787 bpc = 8;
9788 break;
9789 case QRhiTexture::RGBA32SI:
9790 case QRhiTexture::RGBA32UI:
9791 bpc = 16;
9792 break;
9793
9794 default:
9795 Q_UNREACHABLE();
9796 break;
9797 }
9798
9799 const quint32 width = uint(qMax(0, size.width()));
9800 const quint32 height = uint(qMax(0, size.height()));
9801
9802 if (bytesPerPixel)
9803 *bytesPerPixel = bpc;
9804
9805 // Compute in 64-bit, as safety for extreme geometry that would not fit.
9806 const quint64 bytesPerLine = quint64(width) * quint64(bpc);
9807 const quint64 pixelCount = quint64(width) * quint64(height);
9808 if (bytesPerLine > std::numeric_limits<quint32>::max()
9809 || pixelCount > std::numeric_limits<quint32>::max() / bpc)
9810 {
9811 qWarning("Texture of size %dx%d with format %d has a byte size "
9812 "which is too large to be handled",
9813 size.width(), size.height(), int(format));
9814 if (bpl)
9815 *bpl = 0;
9816 if (byteSize)
9817 *byteSize = 0;
9818 return false;
9819 }
9820
9821 if (bpl)
9822 *bpl = quint32(bytesPerLine);
9823 if (byteSize)
9824 *byteSize = quint32(pixelCount * quint64(bpc));
9825
9826 return true;
9827}
9828
9829bool QRhiImplementation::isStencilSupportingFormat(QRhiTexture::Format format) const
9830{
9831 switch (format) {
9832 case QRhiTexture::D24S8:
9833 case QRhiTexture::D32FS8:
9834 return true;
9835 default:
9836 break;
9837 }
9838 return false;
9839}
9840
9841bool QRhiImplementation::sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps)
9842{
9843 if (ps->cbeginShaderStages() == ps->cendShaderStages()) {
9844 qWarning("Cannot build a graphics pipeline without any stages");
9845 return false;
9846 }
9847
9848 bool hasVertexStage = false;
9849 for (auto it = ps->cbeginShaderStages(), itEnd = ps->cendShaderStages(); it != itEnd; ++it) {
9850 if (!it->shader().isValid()) {
9851 qWarning("Empty shader passed to graphics pipeline");
9852 return false;
9853 }
9854 if (it->type() == QRhiShaderStage::Vertex)
9855 hasVertexStage = true;
9856 }
9857 if (!hasVertexStage) {
9858 qWarning("Cannot build a graphics pipeline without a vertex stage");
9859 return false;
9860 }
9861
9862 if (!ps->renderPassDescriptor()) {
9863 qWarning("Cannot build a graphics pipeline without a QRhiRenderPassDescriptor");
9864 return false;
9865 }
9866
9867 if (!ps->shaderResourceBindings()) {
9868 qWarning("Cannot build a graphics pipeline without QRhiShaderResourceBindings");
9869 return false;
9870 }
9871
9872 return true;
9873}
9874
9875bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb)
9876{
9877#ifndef QT_NO_DEBUG
9878 bool bindingsOk = true;
9879 const int CHECKED_BINDINGS_COUNT = 64;
9880 bool bindingSeen[CHECKED_BINDINGS_COUNT] = {};
9881 for (auto it = srb->cbeginBindings(), end = srb->cendBindings(); it != end; ++it) {
9882 const int binding = shaderResourceBindingData(*it)->binding;
9883 if (binding >= CHECKED_BINDINGS_COUNT)
9884 continue;
9885 if (binding < 0) {
9886 qWarning("Invalid binding number %d", binding);
9887 bindingsOk = false;
9888 continue;
9889 }
9890 switch (shaderResourceBindingData(*it)->type) {
9891 case QRhiShaderResourceBinding::UniformBuffer:
9892 if (!bindingSeen[binding]) {
9893 bindingSeen[binding] = true;
9894 } else {
9895 qWarning("Uniform buffer duplicates an existing binding number %d", binding);
9896 bindingsOk = false;
9897 }
9898 break;
9899 case QRhiShaderResourceBinding::SampledTexture:
9900 if (!bindingSeen[binding]) {
9901 bindingSeen[binding] = true;
9902 } else {
9903 qWarning("Combined image sampler duplicates an existing binding number %d", binding);
9904 bindingsOk = false;
9905 }
9906 break;
9907 case QRhiShaderResourceBinding::Texture:
9908 if (!bindingSeen[binding]) {
9909 bindingSeen[binding] = true;
9910 } else {
9911 qWarning("Texture duplicates an existing binding number %d", binding);
9912 bindingsOk = false;
9913 }
9914 break;
9915 case QRhiShaderResourceBinding::Sampler:
9916 if (!bindingSeen[binding]) {
9917 bindingSeen[binding] = true;
9918 } else {
9919 qWarning("Sampler duplicates an existing binding number %d", binding);
9920 bindingsOk = false;
9921 }
9922 break;
9923 case QRhiShaderResourceBinding::ImageLoad:
9924 case QRhiShaderResourceBinding::ImageStore:
9925 case QRhiShaderResourceBinding::ImageLoadStore:
9926 if (!bindingSeen[binding]) {
9927 bindingSeen[binding] = true;
9928 } else {
9929 qWarning("Image duplicates an existing binding number %d", binding);
9930 bindingsOk = false;
9931 }
9932 break;
9933 case QRhiShaderResourceBinding::BufferLoad:
9934 case QRhiShaderResourceBinding::BufferStore:
9935 case QRhiShaderResourceBinding::BufferLoadStore:
9936 if (!bindingSeen[binding]) {
9937 bindingSeen[binding] = true;
9938 } else {
9939 qWarning("Buffer duplicates an existing binding number %d", binding);
9940 bindingsOk = false;
9941 }
9942 break;
9943 default:
9944 qWarning("Unknown binding type %d", int(shaderResourceBindingData(*it)->type));
9945 bindingsOk = false;
9946 break;
9947 }
9948 }
9949
9950 if (!bindingsOk) {
9951 qWarning() << *srb;
9952 return false;
9953 }
9954#else
9955 Q_UNUSED(srb);
9956#endif
9957 return true;
9958}
9959
9960bool QRhiImplementation::sanityCheckResourceOwnership(QRhiResource *maybeResource)
9961{
9962 if (maybeResource == nullptr || maybeResource->m_rhi == nullptr)
9963 return true;
9964
9965 if (maybeResource->m_rhi->q != q) {
9966 qWarning("%s %p (%s) belongs to QRhi %p, but client code attempted to use it with QRhi %p. This is wrong.",
9967 resourceTypeStr(maybeResource),
9968 maybeResource,
9969 maybeResource->m_objectName.constData(),
9970 maybeResource->m_rhi->q,
9971 q);
9972 return false;
9973 }
9974
9975 return true;
9976}
9977
9978int QRhiImplementation::effectiveSampleCount(int sampleCount) const
9979{
9980 // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
9981 const int s = qBound(1, sampleCount, 64);
9982 const QList<int> supported = supportedSampleCounts();
9983 int result = 1;
9984
9985 // Stay compatible with Qt 5 in that requesting an unsupported sample count
9986 // is not an error (although we still do a categorized debug print about
9987 // this), and rather a supported value, preferably a close one, not just 1,
9988 // is used instead. This is actually deviating from Qt 5 as that performs a
9989 // clamping only and does not handle cases such as when sample count 2 is
9990 // not supported but 4 is. (OpenGL handles things like that gracefully,
9991 // other APIs may not, so improve this by picking the next largest, or in
9992 // absence of that, the largest value; this with the goal to not reduce
9993 // quality by rather picking a larger-than-requested value than a smaller one)
9994
9995 for (int i = 0, ie = supported.count(); i != ie; ++i) {
9996 // assumes the 'supported' list is sorted
9997 if (supported[i] >= s) {
9998 result = supported[i];
9999 break;
10000 }
10001 }
10002
10003 if (result != s) {
10004 if (result == 1 && !supported.isEmpty())
10005 result = supported.last();
10006 qCDebug(QRHI_LOG_INFO, "Attempted to set unsupported sample count %d, using %d instead",
10007 sampleCount, result);
10008 }
10009
10010 return result;
10011}
10012
10013/*!
10014 \internal
10015 */
10016QRhi::QRhi()
10017{
10018}
10019
10020/*!
10021 Destructor. Destroys the backend and releases resources.
10022 */
10023QRhi::~QRhi()
10024{
10025 if (!d)
10026 return;
10027
10028 if (qrhiDebugHooks.rhiAboutToBeDestroyed)
10029 qrhiDebugHooks.rhiAboutToBeDestroyed(d);
10030
10031 d->runCleanup();
10032
10033 qDeleteAll(d->pendingDeleteResources);
10034 d->pendingDeleteResources.clear();
10035
10036 d->destroy();
10037 delete d;
10038}
10039
10040QRhiImplementation *QRhiImplementation::newInstance(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *importDevice)
10041{
10042 QRhiImplementation *d = nullptr;
10043
10044 switch (impl) {
10045 case QRhi::Null:
10046 d = new QRhiNull(static_cast<QRhiNullInitParams *>(params));
10047 break;
10048 case QRhi::Vulkan:
10049#if QT_CONFIG(vulkan)
10050 d = new QRhiVulkan(static_cast<QRhiVulkanInitParams *>(params),
10051 static_cast<QRhiVulkanNativeHandles *>(importDevice));
10052 break;
10053#else
10054 Q_UNUSED(importDevice);
10055 qWarning("This build of Qt has no Vulkan support");
10056 break;
10057#endif
10058 case QRhi::OpenGLES2:
10059#ifndef QT_NO_OPENGL
10060 d = new QRhiGles2(static_cast<QRhiGles2InitParams *>(params),
10061 static_cast<QRhiGles2NativeHandles *>(importDevice));
10062 break;
10063#else
10064 qWarning("This build of Qt has no OpenGL support");
10065 break;
10066#endif
10067 case QRhi::D3D11:
10068#ifdef Q_OS_WIN
10069 d = new QRhiD3D11(static_cast<QRhiD3D11InitParams *>(params),
10070 static_cast<QRhiD3D11NativeHandles *>(importDevice));
10071 break;
10072#else
10073 qWarning("This platform has no Direct3D 11 support");
10074 break;
10075#endif
10076 case QRhi::Metal:
10077#if QT_CONFIG(metal)
10078 d = new QRhiMetal(static_cast<QRhiMetalInitParams *>(params),
10079 static_cast<QRhiMetalNativeHandles *>(importDevice));
10080 break;
10081#else
10082 qWarning("This platform has no Metal support");
10083 break;
10084#endif
10085 case QRhi::D3D12:
10086#ifdef Q_OS_WIN
10087#ifdef QRHI_D3D12_AVAILABLE
10088 d = new QRhiD3D12(static_cast<QRhiD3D12InitParams *>(params),
10089 static_cast<QRhiD3D12NativeHandles *>(importDevice));
10090 break;
10091#else
10092 qWarning("Qt was built without Direct3D 12 support. "
10093 "This is likely due to having ancient SDK headers (such as d3d12.h) in the Qt build environment. "
10094 "Rebuild Qt with an SDK supporting D3D12 features introduced in Windows 10 version 1703, "
10095 "or use an MSVC build as those typically are built with more up-to-date SDKs.");
10096 break;
10097#endif
10098#else
10099 qWarning("This platform has no Direct3D 12 support");
10100 break;
10101#endif
10102 }
10103
10104 return d;
10105}
10106
10107void QRhiImplementation::prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags, QRhiAdapter *adapter)
10108{
10109 q = rhi;
10110
10111 debugMarkers = flags.testFlag(QRhi::EnableDebugMarkers);
10112 timestamps = flags.testFlag(QRhi::EnableTimestamps);
10113
10114 implType = impl;
10115 implThread = QThread::currentThread();
10116
10117 requestedRhiAdapter = adapter;
10118}
10119
10120QRhi::AdapterList QRhiImplementation::enumerateAdaptersBeforeCreate(QRhiNativeHandles *) const
10121{
10122 return {};
10123}
10124
10125/*!
10126 \overload
10127
10128 Equivalent to create(\a impl, \a params, \a flags, \a importDevice, \c nullptr).
10129 */
10130QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice)
10131{
10132 return create(impl, params, flags, importDevice, nullptr);
10133}
10134
10135/*!
10136 \return a new QRhi instance with a backend for the graphics API specified
10137 by \a impl with the specified \a flags. \return \c nullptr if the
10138 function fails.
10139
10140 \a params must point to an instance of one of the backend-specific
10141 subclasses of QRhiInitParams, such as, QRhiVulkanInitParams,
10142 QRhiMetalInitParams, QRhiD3D11InitParams, QRhiD3D12InitParams,
10143 QRhiGles2InitParams. See these classes for examples on creating a QRhi.
10144
10145 QRhi by design does not implement any fallback logic: if the specified API
10146 cannot be initialized, create() will fail, with warnings printed on the
10147 debug output by the backends. The clients of QRhi, for example Qt Quick,
10148 may however provide additional logic that allow falling back to an API
10149 different than what was requested, depending on the platform. If the
10150 intention is just to test if initialization would succeed when calling
10151 create() at later point, it is preferable to use probe() instead of
10152 create(), because with some backends probing can be implemented in a more
10153 lightweight manner as opposed to create(), which performs full
10154 initialization of the infrastructure and is wasteful if that QRhi instance
10155 is then thrown immediately away.
10156
10157 \a importDevice allows using an already existing graphics device, without
10158 QRhi creating its own. When not null, this parameter must point to an
10159 instance of one of the subclasses of QRhiNativeHandles:
10160 QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles,
10161 QRhiMetalNativeHandles, QRhiGles2NativeHandles. The exact details and
10162 semantics depend on the backand and the underlying graphics API.
10163
10164 Specifying a QRhiAdapter in \a adapter offers a transparent, cross-API
10165 alternative to passing in a \c VkPhysicalDevice via QRhiVulkanNativeHandles,
10166 or an adapter LUID via QRhiD3D12NativeHandles. The ownership of \a adapter
10167 is not taken. See enumerateAdapters() for more information on this approach.
10168
10169 \note \a importDevice and \a adapter cannot be both specified.
10170
10171 \sa probe()
10172 */
10173QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice, QRhiAdapter *adapter)
10174{
10175 if (adapter && importDevice)
10176 qWarning("adapter and importDevice should not both be non-null in QRhi::create()");
10177
10178 std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, importDevice));
10179 if (!rd)
10180 return nullptr;
10181
10182 std::unique_ptr<QRhi> r(new QRhi);
10183 r->d = rd.release();
10184 r->d->prepareForCreate(r.get(), impl, flags, adapter);
10185 if (!r->d->create(flags))
10186 return nullptr;
10187
10188 return r.release();
10189}
10190
10191/*!
10192 \return true if create() can be expected to succeed when called the given
10193 \a impl and \a params.
10194
10195 For some backends this is equivalent to calling create(), checking its
10196 return value, and then destroying the resulting QRhi.
10197
10198 For others, in particular with Metal, there may be a specific probing
10199 implementation, which allows testing in a more lightweight manner without
10200 polluting the debug output with warnings upon failures.
10201
10202 \sa create()
10203 */
10204bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)
10205{
10206 bool ok = false;
10207
10208 // The only place currently where this makes sense is Metal, where the API
10209 // is simple enough so that a special probing function - doing nothing but
10210 // a MTLCreateSystemDefaultDevice - is reasonable. Elsewhere, just call
10211 // create() and then drop the result.
10212
10213 if (impl == Metal) {
10214#if QT_CONFIG(metal)
10215 ok = QRhiMetal::probe(static_cast<QRhiMetalInitParams *>(params));
10216#endif
10217 } else {
10218 QRhi *rhi = create(impl, params);
10219 ok = rhi != nullptr;
10220 delete rhi;
10221 }
10222 return ok;
10223}
10224
10225/*!
10226 \typedef QRhi::AdapterList
10227 \relates QRhi
10228 \since 6.10
10229
10230 Synonym for QVector<QRhiAdapter *>.
10231*/
10232
10233/*!
10234 \return the list of adapters (physical devices) present, or an empty list
10235 when such control is not available with a given graphics API.
10236
10237 Backends where such level of control is not available, the returned list is
10238 always empty. Thus an empty list does not indicate there are no graphics
10239 devices in the system, but that fine-grained control over selecting which
10240 one to use is not available.
10241
10242 Backends for Direct 3D 11, Direct 3D 12, and Vulkan can be expected to fully
10243 support enumerating adapters. Others may not. The backend is specified by \a
10244 impl. A QRhiAdapter returned from this function must only be used in a
10245 create() call with the same \a impl. Some underlying APIs may present
10246 further limitations, with Vulkan in particular the QRhiAdapter is specified
10247 to the QVulkanInstance (\c VkInstance).
10248
10249 The caller is expected to destroy the QRhiAdapter objects in the list. Apart
10250 from querying \l{QRhiAdapter::}{info()}, the only purpose of these objects is
10251 to be passed on to create(), or the corresponding functions in higher layers
10252 such as Qt Quick.
10253
10254 The following snippet, written specifically for Vulkan, shows how to
10255 enumerate the available physical devices and request to create a QRhi for
10256 the chosen one. This in practice is equivalent to passing in a \c
10257 VkPhysicalDevice via a QRhiVulkanNativeHandles to create(), but it involves
10258 less API-specific code on the application side:
10259
10260 \code
10261 QRhiVulkanInitParams initParams;
10262 initParams.inst = &vulkanInstance;
10263 QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::Vulkan, &initParams);
10264 QRhiAdapter *chosenAdapter = nullptr;
10265 for (QRhiAdapter *adapter : adapters) {
10266 if (looksGood(adapter->info())) {
10267 chosenAdapter = adapter;
10268 break;
10269 }
10270 }
10271 QRhi *rhi = QRhi::create(QRhi::Vulkan, &initParams, {}, nullptr, chosenAdapter);
10272 qDeleteAll(adapters);
10273 \endcode
10274
10275 Passing in \a params is required due to some of the underlying graphics
10276 APIs' design. With Vulkan in particular, the QVulkanInstance must be
10277 provided, since enumerating is not possible without it. Other fields in the
10278 backend-specific \a params will not actually be used by this function.
10279
10280 \a nativeHandles is optional. When specified, it must be a valid
10281 QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, or QRhiVulkanNativeHandles,
10282 similarly to create(). However, unlike create(), only the physical device
10283 (in case of Vulkan) or the adapter LUID (in case of D3D) fields are used,
10284 all other fields are ignored. This can be used the restrict the results to a
10285 given adapter. The returned list will contain 1 or 0 elements in this case.
10286
10287 Note how in the previous code snippet the looksGood() function
10288 implementation cannot perform any platform-specific filtering based on the
10289 true adapter / physical device identity, such as the adapter LUID on Windows
10290 or the VkPhysicalDevice with Vulkan. This is because QRhiDriverInfo does not
10291 contain platform-specific data. Instead, use \a nativeHandles to get the
10292 results filtered already inside enumerateAdapters().
10293
10294 The following two snippets, using Direct 3D 12 as an example, are equivalent
10295 in practice:
10296
10297 \code
10298 // enumerateAdapters-based approach from Qt 6.10 on
10299 QRhiD3D12InitParams initParams;
10300 QRhiD3D12NativeHandles nativeHandles;
10301 nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
10302 nativeHandles.adapterLuidHigh = luid.HighPart;
10303 QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::D3D12, &initParams, &nativeHandles);
10304 if (adapters.isEmpty()) { qWarning("Requested adapter was not found"); }
10305 QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, nullptr, adapters[0]);
10306 qDeleteAll(adapters);
10307 \endcode
10308
10309 \code
10310 // traditional approach, more lightweight
10311 QRhiD3D12InitParams initParams;
10312 QRhiD3D12NativeHandles nativeHandles;
10313 nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
10314 nativeHandles.adapterLuidHigh = luid.HighPart;
10315 QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, &nativeHandles, nullptr);
10316 \endcode
10317
10318 \since 6.10
10319 \sa create()
10320 */
10321QRhi::AdapterList QRhi::enumerateAdapters(Implementation impl, QRhiInitParams *params, QRhiNativeHandles *nativeHandles)
10322{
10323 std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, nullptr));
10324 if (!rd)
10325 return {};
10326
10327 return rd->enumerateAdaptersBeforeCreate(nativeHandles);
10328}
10329
10330/*!
10331 \struct QRhiSwapChainProxyData
10332 \inmodule QtGuiPrivate
10333 \inheaderfile rhi/qrhi.h
10334 \since 6.6
10335
10336 \brief Opaque data describing native objects needed to set up a swapchain.
10337
10338 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10339 for details.
10340
10341 \sa QRhi::updateSwapChainProxyData()
10342 */
10343
10344/*!
10345 Generates and returns a QRhiSwapChainProxyData struct containing opaque
10346 data specific to the backend and graphics API specified by \a impl. \a
10347 window is the QWindow a swapchain is targeting.
10348
10349 The returned struct can be passed to QRhiSwapChain::setProxyData(). This
10350 makes sense in threaded rendering systems: this static function is expected
10351 to be called on the \b{main (gui) thread}, unlike all QRhi operations, then
10352 transferred to the thread working with the QRhi and QRhiSwapChain and passed
10353 on to the swapchain. This allows doing native platform queries that are
10354 only safe to be called on the main thread, for example to query the
10355 CAMetalLayer from a NSView, and then passing on the data to the
10356 QRhiSwapChain living on the rendering thread. With the Metal example, doing
10357 the view.layer access on a dedicated rendering thread causes a warning in
10358 the Xcode Thread Checker. With the data proxy mechanism, this is avoided.
10359
10360 When threads are not involved, generating and passing on the
10361 QRhiSwapChainProxyData is not required: backends are guaranteed to be able
10362 to query whatever is needed on their own, and if everything lives on the
10363 main (gui) thread, that should be sufficient.
10364
10365 \note \a impl should match what the QRhi is created with. For example,
10366 calling with QRhi::Metal on a non-Apple platform will not generate any
10367 useful data.
10368 */
10369QRhiSwapChainProxyData QRhi::updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)
10370{
10371#if QT_CONFIG(metal)
10372 if (impl == Metal)
10373 return QRhiMetal::updateSwapChainProxyData(window);
10374#else
10375 Q_UNUSED(impl);
10376 Q_UNUSED(window);
10377#endif
10378 return {};
10379}
10380
10381/*!
10382 \return the backend type for this QRhi.
10383 */
10384QRhi::Implementation QRhi::backend() const
10385{
10386 return d->implType;
10387}
10388
10389/*!
10390 \return a friendly name for the backend \a impl, usually the name of the 3D
10391 API in use.
10392 */
10393const char *QRhi::backendName(Implementation impl)
10394{
10395 switch (impl) {
10396 case QRhi::Null:
10397 return "Null";
10398 case QRhi::Vulkan:
10399 return "Vulkan";
10400 case QRhi::OpenGLES2:
10401 return "OpenGL";
10402 case QRhi::D3D11:
10403 return "D3D11";
10404 case QRhi::Metal:
10405 return "Metal";
10406 case QRhi::D3D12:
10407 return "D3D12";
10408 }
10409
10410 Q_UNREACHABLE_RETURN("Unknown");
10411}
10412
10413/*!
10414 \return the backend type as string for this QRhi.
10415 */
10416const char *QRhi::backendName() const
10417{
10418 return backendName(d->implType);
10419}
10420
10421/*!
10422 \enum QRhiDriverInfo::DeviceType
10423 Specifies the graphics device's type, when the information is available.
10424
10425 In practice this is only applicable with Vulkan and Metal. With Direct 3D
10426 11 and 12, using an adapter with the software flag set leads to the value
10427 \c CpuDevice. Otherwise, and with OpenGL, the value is always UnknownDevice.
10428
10429 \value UnknownDevice
10430 \value IntegratedDevice
10431 \value DiscreteDevice
10432 \value ExternalDevice
10433 \value VirtualDevice
10434 \value CpuDevice
10435*/
10436
10437/*!
10438 \struct QRhiDriverInfo
10439 \inmodule QtGuiPrivate
10440 \inheaderfile rhi/qrhi.h
10441 \since 6.6
10442
10443 \brief Describes the physical device, adapter, or graphics API
10444 implementation that is used by an initialized QRhi.
10445
10446 Graphics APIs offer different levels and kinds of information. The only
10447 value that is available across all APIs is the deviceName, which is a
10448 freetext description of the physical device, adapter, or is a combination
10449 of the strings reported for \c{GL_VENDOR} + \c{GL_RENDERER} +
10450 \c{GL_VERSION}. The deviceId is always 0 for OpenGL. vendorId is always 0
10451 for OpenGL and Metal. deviceType is always UnknownDevice for OpenGL and
10452 Direct 3D.
10453
10454 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10455 for details.
10456 */
10457
10458/*!
10459 \variable QRhiDriverInfo::deviceName
10460
10461 \sa QRhi::driverInfo()
10462*/
10463
10464/*!
10465 \variable QRhiDriverInfo::deviceId
10466
10467 \sa QRhi::driverInfo()
10468*/
10469
10470/*!
10471 \variable QRhiDriverInfo::vendorId
10472
10473 \sa QRhi::driverInfo()
10474*/
10475
10476/*!
10477 \variable QRhiDriverInfo::deviceType
10478
10479 \sa QRhi::driverInfo(), QRhiDriverInfo::DeviceType
10480*/
10481
10482#ifndef QT_NO_DEBUG_STREAM
10483static inline const char *deviceTypeStr(QRhiDriverInfo::DeviceType type)
10484{
10485 switch (type) {
10486 case QRhiDriverInfo::UnknownDevice:
10487 return "Unknown";
10488 case QRhiDriverInfo::IntegratedDevice:
10489 return "Integrated";
10490 case QRhiDriverInfo::DiscreteDevice:
10491 return "Discrete";
10492 case QRhiDriverInfo::ExternalDevice:
10493 return "External";
10494 case QRhiDriverInfo::VirtualDevice:
10495 return "Virtual";
10496 case QRhiDriverInfo::CpuDevice:
10497 return "Cpu";
10498 }
10499
10500 Q_UNREACHABLE_RETURN(nullptr);
10501}
10502QDebug operator<<(QDebug dbg, const QRhiDriverInfo &info)
10503{
10504 QDebugStateSaver saver(dbg);
10505 dbg.nospace() << "QRhiDriverInfo(deviceName=" << info.deviceName
10506 << " deviceId=0x" << Qt::hex << info.deviceId
10507 << " vendorId=0x" << info.vendorId
10508 << " deviceType=" << deviceTypeStr(info.deviceType)
10509 << ')';
10510 return dbg;
10511}
10512#endif
10513
10514/*!
10515 \return metadata for the graphics device used by this successfully
10516 initialized QRhi instance.
10517 */
10518QRhiDriverInfo QRhi::driverInfo() const
10519{
10520 return d->driverInfo();
10521}
10522
10523/*!
10524 \class QRhiAdapter
10525 \inmodule QtGuiPrivate
10526 \inheaderfile rhi/qrhi.h
10527 \since 6.10
10528
10529 \brief Represents a physical graphics device.
10530
10531 Some QRhi backends target graphics APIs that expose the concept of \c
10532 adapters or \c{physical devices}. Call the static \l
10533 {QRhi::}{enumerateAdapters()} function to retrieve a list of the adapters
10534 present in the system. Pass one of the returned QRhiAdapter objects to \l
10535 {QRhi::}{create()} in order to request using the adapter or physical device
10536 the QRhiAdapter corresponds to. Other than exposing the QRhiDriverInfo,
10537 QRhiAdapter is to be treated as an opaque handle.
10538
10539 \note With Vulkan, the QRhiAdapter is valid only as long as the
10540 QVulkanInstance that was used for \l{QRhi::}{enumerateAdapters()} is valid.
10541 This also means that a QRhiAdapter is tied to the Vulkan instance
10542 (QVulkanInstance, \c VkInstance) and cannot be used in the context of
10543 another Vulkan instance.
10544
10545 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10546 for details.
10547 */
10548
10549/*!
10550 \fn virtual QRhiDriverInfo QRhiAdapter::info() const = 0
10551
10552 \return the corresponding QRhiDriverInfo.
10553 */
10554
10555/*!
10556 \internal
10557 */
10558QRhiAdapter::~QRhiAdapter()
10559{
10560}
10561
10562/*!
10563 \return the thread on which the QRhi was \l{QRhi::create()}{initialized}.
10564 */
10565QThread *QRhi::thread() const
10566{
10567 return d->implThread;
10568}
10569
10570/*!
10571 Registers a \a callback that is invoked when the QRhi is destroyed.
10572
10573 The callback will run with the graphics resource still available, so this
10574 provides an opportunity for the application to cleanly release QRhiResource
10575 instances belonging to the QRhi. This is particularly useful for managing
10576 the lifetime of resources stored in \c cache type of objects, where the
10577 cache holds QRhiResources or objects containing QRhiResources.
10578
10579 \sa ~QRhi()
10580 */
10581void QRhi::addCleanupCallback(const CleanupCallback &callback)
10582{
10583 d->addCleanupCallback(callback);
10584}
10585
10586/*!
10587 \overload
10588
10589 Registers \a callback to be invoked when the QRhi is destroyed. This
10590 overload takes an opaque pointer, \a key, that is used to ensure that a
10591 given callback is registered (and so called) only once.
10592
10593 \sa removeCleanupCallback()
10594 */
10595void QRhi::addCleanupCallback(const void *key, const CleanupCallback &callback)
10596{
10597 d->addCleanupCallback(key, callback);
10598}
10599
10600/*!
10601 Deregisters the callback with \a key. If no cleanup callback was registered
10602 with \a key, the function does nothing. Callbacks registered without a key
10603 cannot be removed.
10604
10605 \sa addCleanupCallback()
10606 */
10607void QRhi::removeCleanupCallback(const void *key)
10608{
10609 d->removeCleanupCallback(key);
10610}
10611
10612void QRhiImplementation::runCleanup()
10613{
10614 for (const QRhi::CleanupCallback &f : std::as_const(cleanupCallbacks))
10615 f(q);
10616
10617 cleanupCallbacks.clear();
10618
10619 for (auto it = keyedCleanupCallbacks.cbegin(), end = keyedCleanupCallbacks.cend(); it != end; ++it)
10620 it.value()(q);
10621
10622 keyedCleanupCallbacks.clear();
10623}
10624
10625/*!
10626 \class QRhiResourceUpdateBatch
10627 \inmodule QtGuiPrivate
10628 \inheaderfile rhi/qrhi.h
10629 \since 6.6
10630 \brief Records upload and copy type of operations.
10631
10632 With QRhi it is no longer possible to perform copy type of operations at
10633 arbitrary times. Instead, all such operations are recorded into batches
10634 that are then passed, most commonly, to QRhiCommandBuffer::beginPass().
10635 What then happens under the hood is hidden from the application: the
10636 underlying implementations can defer and implement these operations in
10637 various different ways.
10638
10639 A resource update batch owns no graphics resources and does not perform any
10640 actual operations on its own. It should rather be viewed as a command
10641 buffer for update, upload, and copy type of commands.
10642
10643 To get an available, empty batch from the pool, call
10644 QRhi::nextResourceUpdateBatch().
10645
10646 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
10647 for details.
10648 */
10649
10650/*!
10651 \internal
10652 */
10653QRhiResourceUpdateBatch::QRhiResourceUpdateBatch(QRhiImplementation *rhi)
10654 : d(new QRhiResourceUpdateBatchPrivate)
10655{
10656 d->q = this;
10657 d->rhi = rhi;
10658}
10659
10660QRhiResourceUpdateBatch::~QRhiResourceUpdateBatch()
10661{
10662 delete d;
10663}
10664
10665/*!
10666 \return the batch to the pool. This should only be used when the batch is
10667 not passed to one of QRhiCommandBuffer::beginPass(),
10668 QRhiCommandBuffer::endPass(), or QRhiCommandBuffer::resourceUpdate()
10669 because these implicitly call destroy().
10670
10671 \note QRhiResourceUpdateBatch instances must never by \c deleted by
10672 applications.
10673 */
10674void QRhiResourceUpdateBatch::release()
10675{
10676 d->free();
10677}
10678
10679/*!
10680 Copies all queued operations from the \a other batch into this one.
10681
10682 \note \a other may no longer contain valid data after the merge operation,
10683 and must not be submitted, but it will still need to be released by calling
10684 release().
10685
10686 This allows for a convenient pattern where resource updates that are
10687 already known during the initialization step are collected into a batch
10688 that is then merged into another when starting to first render pass later
10689 on:
10690
10691 \code
10692 void init()
10693 {
10694 initialUpdates = rhi->nextResourceUpdateBatch();
10695 initialUpdates->uploadStaticBuffer(vbuf, vertexData);
10696 initialUpdates->uploadStaticBuffer(ibuf, indexData);
10697 // ...
10698 }
10699
10700 void render()
10701 {
10702 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
10703 if (initialUpdates) {
10704 resUpdates->merge(initialUpdates);
10705 initialUpdates->release();
10706 initialUpdates = nullptr;
10707 }
10708 // resUpdates->updateDynamicBuffer(...);
10709 cb->beginPass(rt, clearCol, clearDs, resUpdates);
10710 }
10711 \endcode
10712 */
10713void QRhiResourceUpdateBatch::merge(QRhiResourceUpdateBatch *other)
10714{
10715 d->merge(other->d);
10716}
10717
10718/*!
10719 \return true until the number of buffer and texture operations enqueued
10720 onto this batch is below a reasonable limit.
10721
10722 The return value is false when the number of buffer and/or texture
10723 operations added to this batch have reached, or are about to reach, a
10724 certain limit. The batch is fully functional afterwards as well, but may
10725 need to allocate additional memory. Therefore, a renderer that collects
10726 lots of buffer and texture updates in a single batch when preparing a frame
10727 may want to consider \l{QRhiCommandBuffer::resourceUpdate()}{submitting the
10728 batch} and \l{QRhi::nextResourceUpdateBatch()}{starting a new one} when
10729 this function returns false.
10730 */
10731bool QRhiResourceUpdateBatch::hasOptimalCapacity() const
10732{
10733 return d->hasOptimalCapacity();
10734}
10735
10736/*!
10737 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10738 QRhiBuffer::Dynamic.
10739
10740 The region is specified \a offset and \a size. The actual bytes to write
10741 are specified by \a data which must have at least \a size bytes available.
10742
10743 \a data is copied and can safely be destroyed or changed once this function
10744 returns.
10745
10746 \note If host writes are involved, which is the case with
10747 updateDynamicBuffer() typically as such buffers are backed by host visible
10748 memory with most backends, they may accumulate within a frame. Thus pass 1
10749 reading a region changed by a batch passed to pass 2 may see the changes
10750 specified in pass 2's update batch.
10751
10752 \note QRhi transparently manages double buffering in order to prevent
10753 stalling the graphics pipeline. The fact that a QRhiBuffer may have
10754 multiple native buffer objects underneath can be safely ignored when using
10755 the QRhi and QRhiResourceUpdateBatch.
10756 */
10757void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
10758{
10759 if (size > 0) {
10760 const int idx = d->activeBufferOpCount++;
10761 const int opListSize = d->bufferOps.size();
10762 if (idx < opListSize)
10763 QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, size, data);
10764 else
10765 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, size, data));
10766 }
10767}
10768
10769/*!
10770 \overload
10771 \since 6.10
10772
10773 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10774 QRhiBuffer::Dynamic.
10775
10776 \a data is moved into the batch instead of copied with this overload.
10777 */
10778void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
10779{
10780 if (!data.isEmpty()) {
10781 const int idx = d->activeBufferOpCount++;
10782 const int opListSize = d->bufferOps.size();
10783 if (idx < opListSize)
10784 QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, std::move(data));
10785 else
10786 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, std::move(data)));
10787 }
10788}
10789
10790/*!
10791 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10792 QRhiBuffer::Immutable or QRhiBuffer::Static.
10793
10794 The region is specified \a offset and \a size. The actual bytes to write
10795 are specified by \a data which must have at least \a size bytes available.
10796
10797 \a data is copied and can safely be destroyed or changed once this function
10798 returns.
10799
10800 \note Whether the upload is performed on the GPU timeline, and so is ordered
10801 against the other operations recorded in the same batch, is indicated by the
10802 \l QRhi::StaticBuffersOnGpuTimeline feature. This only matters when
10803 combining uploads with
10804 \l{QRhiResourceUpdateBatch::copyBuffer()}{copyBuffer()} on the same buffer.
10805
10806 \sa copyBuffer()
10807 */
10808void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
10809{
10810 if (size > 0) {
10811 const int idx = d->activeBufferOpCount++;
10812 if (idx < d->bufferOps.size())
10813 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, size, data);
10814 else
10815 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, size, data));
10816 }
10817}
10818
10819/*!
10820 \overload
10821 \since 6.10
10822
10823 Enqueues updating a region of a QRhiBuffer \a buf created with the type
10824 QRhiBuffer::Immutable or QRhiBuffer::Static.
10825
10826 \a data is moved into the batch instead of copied with this overload.
10827 */
10828void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
10829{
10830 if (!data.isEmpty()) {
10831 const int idx = d->activeBufferOpCount++;
10832 if (idx < d->bufferOps.size())
10833 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, std::move(data));
10834 else
10835 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, std::move(data)));
10836 }
10837}
10838
10839/*!
10840 \overload
10841
10842 Enqueues updating the entire QRhiBuffer \a buf created with the type
10843 QRhiBuffer::Immutable or QRhiBuffer::Static.
10844 */
10845void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *data)
10846{
10847 if (buf->size() > 0) {
10848 const int idx = d->activeBufferOpCount++;
10849 if (idx < d->bufferOps.size())
10850 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, 0, data);
10851 else
10852 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, 0, data));
10853 }
10854}
10855
10856/*!
10857 \overload
10858 \since 6.10
10859
10860 Enqueues updating the entire QRhiBuffer \a buf created with the type
10861 QRhiBuffer::Immutable or QRhiBuffer::Static.
10862
10863 \a data is moved into the batch instead of copied with this overload.
10864
10865 \a data size must equal the size of \a buf.
10866 */
10867void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, QByteArray data)
10868{
10869 if (buf->size() > 0 && quint32(data.size()) == buf->size()) {
10870 const int idx = d->activeBufferOpCount++;
10871 if (idx < d->bufferOps.size())
10872 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, std::move(data));
10873 else
10874 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, std::move(data)));
10875 }
10876}
10877
10878/*!
10879 Enqueues reading back a region of the QRhiBuffer \a buf. The size of the
10880 region is specified by \a size in bytes, \a offset is the offset in bytes
10881 to start reading from.
10882
10883 A readback is asynchronous. \a result contains a callback that is invoked
10884 when the operation has completed. The data is provided in
10885 QRhiReadbackResult::data. Upon successful completion that QByteArray
10886 will have a size equal to \a size. On failure the QByteArray will be empty.
10887
10888 \note Reading buffers with a usage different than QRhiBuffer::UniformBuffer
10889 is supported only when the QRhi::ReadBackNonUniformBuffer feature is
10890 reported as supported.
10891
10892 \note The asynchronous readback is guaranteed to have completed when one of
10893 the following conditions is met: \l{QRhi::finish()}{finish()} has been
10894 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
10895 including the frame that issued the readback operation, and the
10896 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
10897 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
10898 QRhi::MaxAsyncReadbackFrames.
10899
10900 \sa readBackTexture(), QRhi::isFeatureSupported(), QRhi::resourceLimit()
10901 */
10902void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
10903{
10904 const int idx = d->activeBufferOpCount++;
10905 if (idx < d->bufferOps.size())
10906 d->bufferOps[idx] = QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result);
10907 else
10908 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result));
10909}
10910
10911/*!
10912 Enqueues a buffer-to-buffer copy operation from \a src into \a dst as
10913 described by \a desc.
10914
10915 The copy is performed on the GPU, without involving the CPU. This is the
10916 preferred way of moving data between two non-Dynamic QRhiBuffer objects.
10917
10918 Availability is indicated by the \l QRhi::BufferToBufferCopy feature. When
10919 that is reported as not supported, which in practice means OpenGL ES 2.0 and
10920 old desktop OpenGL versions, calling this function has no effect.
10921
10922 A \l{QRhiBufferCopyDescription::size()}{size} of 0 in \a desc, which is what
10923 a default constructed description has, means the entire \a src buffer. Watch
10924 out for this when \a dst is smaller than \a src, because the copy then does
10925 not fit and gets dropped, as described below.
10926
10927 \note Neither buffer can be of the type QRhiBuffer::Dynamic, and neither can
10928 have QRhiBuffer::UniformBuffer usage. With some of the underlying 3D APIs
10929 such buffers are backed by host visible memory, or are not real GPU buffers
10930 at all, and so cannot take part in a GPU-side copy.
10931
10932 \note The size and offsets in \a desc should all be multiples of 4. This is a
10933 requirement of the blit encoder in Metal, and it applies on macOS on
10934 Intel-based devices. Other platforms and 3D APIs, including Metal on Apple
10935 Silicon and on iOS, have no such restriction, but portable code has to assume
10936 the strictest of these. Keep in mind that a
10937 \l{QRhiBufferCopyDescription::size()}{size} of 0 leads to using the full size
10938 of \a src, which is not necessarily a multiple of 4 either.
10939
10940 \note Mixing GPU-side copies with host-side updates
10941 (\l{QRhiResourceUpdateBatch::uploadStaticBuffer()}{uploadStaticBuffer()}) on
10942 the same buffer within the same frame follows the order in which the
10943 operations were recorded in the batch, but only when the
10944 \l QRhi::StaticBuffersOnGpuTimeline feature is reported as supported. Where
10945 it is not, which in practice means Metal on macOS on devices without an
10946 Apple GPU, buffer uploads are implemented by writing to host visible memory,
10947 and so the ordering between the two kinds of updates is not defined.
10948 Portable applications need to either avoid the pattern or check the feature
10949 flag.
10950
10951 \since 6.13
10952 \sa copyTexture(), QRhi::isFeatureSupported()
10953 */
10954void QRhiResourceUpdateBatch::copyBuffer(QRhiBuffer *dst, QRhiBuffer *src, const QRhiBufferCopyDescription &desc)
10955{
10956 if (!dst || !src) {
10957 qWarning("Buffer copy with a null source or destination is not supported");
10958 return;
10959 }
10960 if (dst == src) {
10961 qWarning("Buffer copy with matching source and destination is not supported");
10962 return;
10963 }
10964 // Dynamic buffers are host visible, or shadowed on the CPU, with some of
10965 // the backends, and so cannot be the source or the destination of a
10966 // GPU-side copy. UniformBuffer is not necessarily backed by a real GPU
10967 // buffer either.
10968 if (dst->usage().testFlag(QRhiBuffer::UniformBuffer) || src->usage().testFlag(QRhiBuffer::UniformBuffer)) {
10969 qWarning("Buffer copy is not supported for buffers with UniformBuffer usage");
10970 return;
10971 }
10972 if (dst->type() == QRhiBuffer::Dynamic || src->type() == QRhiBuffer::Dynamic) {
10973 qWarning("Buffer copy is not supported for Dynamic buffers");
10974 return;
10975 }
10976
10977 const quint32 size = desc.size() ? desc.size() : src->size();
10978 if (!size)
10979 return;
10980 if (quint64(desc.sourceOffset()) + size > src->size() || quint64(desc.destinationOffset()) + size > dst->size()) {
10981 qWarning("Buffer copy of %u bytes (source offset %u, destination offset %u) "
10982 "does not fit the source (%u bytes) or destination (%u bytes) buffer",
10983 size, desc.sourceOffset(), desc.destinationOffset(),
10984 src->size(), dst->size());
10985 return;
10986 }
10987
10988 const int idx = d->activeBufferOpCount++;
10989 const QRhiResourceUpdateBatchPrivate::BufferOp op = QRhiResourceUpdateBatchPrivate::BufferOp::copy(dst, src,
10990 desc.destinationOffset(), desc.sourceOffset(), size);
10991
10992 if (idx < d->bufferOps.size())
10993 d->bufferOps[idx] = op;
10994 else
10995 d->bufferOps.append(op);
10996}
10997
10998/*!
10999 Enqueues filling \a size bytes of the buffer \a buf, starting at \a offset,
11000 with the byte \a value.
11001
11002 The buffer must have been created with the QRhiBuffer::StorageBuffer usage.
11003 Such buffers are only available when the \l QRhi::Compute feature is
11004 reported as supported, and are never of the type QRhiBuffer::Dynamic. The
11005 clear is performed on the GPU, and it takes effect in the order it was
11006 recorded in, relative to the compute and render passes, and to the other
11007 buffer operations in the batch that are performed on the GPU, such as
11008 copyBuffer(). This makes it suitable for resetting storage buffers
11009 (counters, accumulators) between compute dispatches.
11010
11011 \note \a offset must be a multiple of 4, otherwise the clear is ignored,
11012 with a warning. When \a size is not a multiple of 4, it is rounded down to
11013 the previous multiple of 4, again with a warning, which means the
11014 remaining one to three bytes are left untouched. These are restrictions of
11015 some of the underlying 3D APIs.
11016
11017 \note The clear maps to the native buffer fill or clear operation of the
11018 underlying 3D API, such as \c vkCmdFillBuffer or
11019 \c ClearUnorderedAccessViewUint, without transferring data from the CPU.
11020 The exception is OpenGL ES, which has no way of clearing the contents of a
11021 buffer on the GPU. There the clear is implemented by uploading \a size
11022 bytes of data.
11023
11024 \note Mixing clears with host-side updates
11025 (\l{QRhiResourceUpdateBatch::uploadStaticBuffer()}{uploadStaticBuffer()}) on
11026 the same buffer within the same frame follows the order in which the
11027 operations were recorded in the batch only when the
11028 \l QRhi::StaticBuffersOnGpuTimeline feature is reported as supported. See
11029 copyBuffer() for details.
11030
11031 \since 6.13
11032 \sa copyBuffer()
11033 */
11034void QRhiResourceUpdateBatch::clearStorageBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, quint8 value)
11035{
11036 if (!buf) {
11037 qWarning("Buffer clear with a null buffer is not supported");
11038 return;
11039 }
11040 if (!buf->usage().testFlag(QRhiBuffer::StorageBuffer)) {
11041 qWarning("Buffer clear is only supported for buffers with StorageBuffer usage");
11042 return;
11043 }
11044 // StorageBuffer is not supposed to be combined with Dynamic, but not all
11045 // backends reject it
11046 if (buf->type() == QRhiBuffer::Dynamic) {
11047 qWarning("Buffer clear is not supported for Dynamic buffers");
11048 return;
11049 }
11050 if (offset % 4u) {
11051 qWarning("Buffer clear offset %u is not a multiple of 4", offset);
11052 return;
11053 }
11054 if (quint64(offset) + size > buf->size()) {
11055 qWarning("Buffer clear of %u bytes at offset %u does not fit the buffer (%u bytes)",
11056 size, offset, buf->size());
11057 return;
11058 }
11059 if (size % 4u) {
11060 qWarning("Buffer clear size %u is not a multiple of 4, rounding down", size);
11061 size &= ~3u;
11062 }
11063 if (!size)
11064 return;
11065
11066 const int idx = d->activeBufferOpCount++;
11067 const QRhiResourceUpdateBatchPrivate::BufferOp op = QRhiResourceUpdateBatchPrivate::BufferOp::clear(buf,
11068 offset, size, value);
11069
11070 if (idx < d->bufferOps.size())
11071 d->bufferOps[idx] = op;
11072 else
11073 d->bufferOps.append(op);
11074}
11075
11076/*!
11077 \overload
11078
11079 Enqueues filling the entire buffer \a buf with the byte \a value. When the
11080 size of \a buf is not a multiple of 4, the last one to three bytes are left
11081 untouched, and a warning is printed.
11082
11083 \since 6.13
11084 */
11085void QRhiResourceUpdateBatch::clearStorageBuffer(QRhiBuffer *buf, quint8 value)
11086{
11087 clearStorageBuffer(buf, 0, buf ? buf->size() : 0, value);
11088}
11089
11090/*!
11091 Enqueues uploading the image data for one or more mip levels in one or more
11092 layers of the texture \a tex.
11093
11094 The details of the copy (source QImage or compressed texture data, regions,
11095 target layers and levels) are described in \a desc.
11096 */
11097void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
11098{
11099 if (desc.cbeginEntries() != desc.cendEntries()) {
11100 const int idx = d->activeTextureOpCount++;
11101 if (idx < d->textureOps.size())
11102 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc);
11103 else
11104 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc));
11105 }
11106}
11107
11108/*!
11109 Enqueues uploading the image data for mip level 0 of layer 0 of the texture
11110 \a tex.
11111
11112 \a tex must have an uncompressed format. Its format must also be compatible
11113 with the QImage::format() of \a image. The source data is given in \a
11114 image.
11115 */
11116void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &image)
11117{
11118 uploadTexture(tex,
11119 QRhiTextureUploadEntry(0, 0, QRhiTextureSubresourceUploadDescription(image)));
11120}
11121
11122/*!
11123 Enqueues a texture-to-texture copy operation from \a src into \a dst as
11124 described by \a desc.
11125
11126 \note The source texture \a src must be created with
11127 QRhiTexture::UsedAsTransferSource.
11128
11129 \note The format of the textures must match. With most graphics
11130 APIs the data is copied as-is without any format conversions. If
11131 \a dst and \a src are created with different formats, unspecified
11132 issues may arise.
11133 */
11134void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
11135{
11136 const int idx = d->activeTextureOpCount++;
11137 if (idx < d->textureOps.size())
11138 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc);
11139 else
11140 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc));
11141}
11142
11143/*!
11144 Enqueues a texture-to-host copy operation as described by \a rb.
11145
11146 Normally \a rb will specify a QRhiTexture as the source. However, when the
11147 swapchain in the current frame was created with
11148 QRhiSwapChain::UsedAsTransferSource, it can also be the source of the
11149 readback. For this, leave the texture set to null in \a rb.
11150
11151 Unlike other operations, the results here need to be processed by the
11152 application. Therefore, \a result provides not just the data but also a
11153 callback as operations on the batch are asynchronous by nature:
11154
11155 \code
11156 rhi->beginFrame(swapchain);
11157 cb->beginPass(swapchain->currentFrameRenderTarget(), colorClear, dsClear);
11158 // ...
11159 QRhiReadbackResult *rbResult = new QRhiReadbackResult;
11160 rbResult->completed = [rbResult] {
11161 {
11162 const QImage::Format fmt = QImage::Format_RGBA8888_Premultiplied; // fits QRhiTexture::RGBA8
11163 const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
11164 QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
11165 image.save("result.png");
11166 }
11167 delete rbResult;
11168 };
11169 QRhiResourceUpdateBatch *u = nextResourceUpdateBatch();
11170 QRhiReadbackDescription rb; // no texture -> uses the current backbuffer of sc
11171 u->readBackTexture(rb, rbResult);
11172 cb->endPass(u);
11173 rhi->endFrame(swapchain);
11174 \endcode
11175
11176 \note The texture must be created with QRhiTexture::UsedAsTransferSource.
11177
11178 \note Multisample textures cannot be read back.
11179
11180 \note The readback returns raw byte data, in order to allow the applications
11181 to interpret it in any way they see fit. Be aware of the blending settings
11182 of rendering code: if the blending is set up to rely on premultiplied alpha,
11183 the results of the readback must also be interpreted as Premultiplied.
11184
11185 \note When interpreting the resulting raw data, be aware that the readback
11186 happens with a byte ordered format. A \l{QRhiTexture::RGBA8}{RGBA8} texture
11187 maps therefore to byte ordered QImage formats, such as,
11188 QImage::Format_RGBA8888.
11189
11190 The data of a depth or depth-stencil texture is returned in the following
11191 layout, in native byte order, regardless of the backend. Any bits not
11192 mentioned are zero.
11193
11194 \list
11195 \li \l{QRhiTexture::D16}{D16}: 2 bytes per pixel, a 16-bit normalized unsigned integer.
11196 \li \l{QRhiTexture::D24}{D24}: 4 bytes per pixel, the 24-bit normalized
11197 unsigned integer depth in the upper 24 bits.
11198 \li \l{QRhiTexture::D24S8}{D24S8}: 4 bytes per pixel, the 24-bit
11199 normalized unsigned integer depth in the upper 24 bits and the stencil in
11200 the lower 8 bits.
11201 \li \l{QRhiTexture::D32F}{D32F}: 4 bytes per pixel, a 32-bit float.
11202 \li \l{QRhiTexture::D32FS8}{D32FS8}: 8 bytes per pixel, a 32-bit float
11203 depth, followed by a 32-bit unsigned integer with the stencil in the lower 8
11204 bits.
11205 \endlist
11206
11207 \note With OpenGL ES, reading back a depth or depth-stencil texture is not
11208 supported, see QRhi::ReadBackAnyTextureFormat.
11209
11210 \note The asynchronous readback is guaranteed to have completed when one of
11211 the following conditions is met: \l{QRhi::finish()}{finish()} has been
11212 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
11213 including the frame that issued the readback operation, and the
11214 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
11215 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
11216 QRhi::MaxAsyncReadbackFrames.
11217
11218 A single readback operation copies one mip level of one layer (cubemap face
11219 or 3D slice or texture array element) at a time. The level and layer are
11220 specified by the respective fields in \a rb.
11221
11222 \sa readBackBuffer(), QRhi::resourceLimit()
11223 */
11224void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
11225{
11226 const int idx = d->activeTextureOpCount++;
11227 if (idx < d->textureOps.size())
11228 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result);
11229 else
11230 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result));
11231}
11232
11233/*!
11234 Enqueues a mipmap generation operation for the specified texture \a tex.
11235
11236 2D and cube textures are supported. 1D and 3D textures are supported when
11237 the QRhi::OneDimensionalTextureMipmaps or QRhi::ThreeDimensionalTextureMipmaps
11238 feature is reported as supported, respectively.
11239
11240 \note The texture must be created with QRhiTexture::MipMapped and
11241 QRhiTexture::UsedWithGenerateMips.
11242
11243 \warning QRhi cannot guarantee that mipmaps can be generated for all
11244 supported texture formats. For example, QRhiTexture::RGBA32F is not a \c
11245 filterable format in OpenGL ES 3.0 and Metal on iOS, and therefore the
11246 mipmap generation request may fail. RGBA8 and RGBA16F are typically
11247 filterable, so it is recommended to use these formats when mipmap generation
11248 is desired.
11249 */
11250void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex)
11251{
11252 const int idx = d->activeTextureOpCount++;
11253 if (idx < d->textureOps.size())
11254 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex);
11255 else
11256 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex));
11257}
11258
11259/*!
11260 Enqueues updating the contents of the indirect command buffer \a icb from
11261 the commands recorded on it with QRhiIndirectCommandBuffer::draw() or
11262 QRhiIndirectCommandBuffer::drawIndexed().
11263
11264 Has to be called after recording and before the render pass that executes
11265 the commands. Does nothing when nothing changed since the last time, so
11266 calling it once per frame is inexpensive.
11267
11268 Has no effect on an indirect command buffer that was populated with
11269 QRhiCommandBuffer::buildIndirect() instead.
11270
11271 \note This is where backends that keep the commands in a buffer perform the
11272 upload, but it is not necessarily where the cost of a CPU-recorded indirect
11273 command buffer is: Metal has nothing to upload here and does its per-command
11274 encoding in QRhiCommandBuffer::executeIndirect() instead. An inexpensive
11275 commitIndirectCommandBuffer() therefore does not by itself mean that
11276 recording the commands was inexpensive. See \l QRhiIndirectCommandBuffer for
11277 how the cost of CPU recording scales.
11278
11279 \since 6.13
11280 */
11281void QRhiResourceUpdateBatch::commitIndirectCommandBuffer(QRhiIndirectCommandBuffer *icb)
11282{
11283 Q_ASSERT(icb);
11284 d->rhi->commitIndirectCommandBuffer(this, icb);
11285}
11286
11287/*!
11288 \return an available, empty batch to which copy type of operations can be
11289 recorded.
11290
11291 \note the return value is not owned by the caller and must never be
11292 destroyed. Instead, the batch is returned the pool for reuse by passing
11293 it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or
11294 QRhiCommandBuffer::resourceUpdate(), or by calling
11295 QRhiResourceUpdateBatch::release() on it.
11296
11297 \note Can be called outside beginFrame() - endFrame() as well since a batch
11298 instance just collects data on its own, it does not perform any operations.
11299
11300 Due to not being tied to a frame being recorded, the following sequence is
11301 valid for example:
11302
11303 \code
11304 rhi->beginFrame(swapchain);
11305 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
11306 u->uploadStaticBuffer(buf, data);
11307 // ... do not commit the batch
11308 rhi->endFrame();
11309 // u stays valid (assuming buf stays valid as well)
11310 rhi->beginFrame(swapchain);
11311 swapchain->currentFrameCommandBuffer()->resourceUpdate(u);
11312 // ... draw with buf
11313 rhi->endFrame();
11314 \endcode
11315
11316 \warning The maximum number of batches per QRhi is 64. When this limit is
11317 reached, the function will return null until a batch is returned to the
11318 pool.
11319 */
11320QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
11321{
11322 // By default we prefer spreading out the utilization of the worst case 64
11323 // (but typically 4) batches as much as possible, meaning we won't pick the
11324 // first one even if it's free, but prefer picking one after the last picked
11325 // one. Relevant due to implicit sharing (the backend may hold on to the
11326 // QRhiBufferData until frame no. current+FramesInFlight-1, but
11327 // implementations may vary), combined with the desire to reuse container
11328 // and QRhiBufferData allocations in bufferOps instead of flooding every
11329 // frame with allocs. See free(). In typical Qt Quick scenes this leads to
11330 // eventually seeding all 4 (or more) resource batches with buffer operation
11331 // data allocations which may (*) then be reused in subsequent frames. This
11332 // comes at the expense of using more memory, but has proven good results
11333 // when (CPU) profiling typical Quick/Quick3D apps.
11334 //
11335 // (*) Due to implicit sharing(ish), the exact behavior is unpredictable. If
11336 // a backend holds on to the QRhiBufferData for, e.g., a dynamic buffer
11337 // update, and then there is a new assign() for that same QRhiBufferData
11338 // while the refcount is still 2, it will "detach" (without contents) and
11339 // there is no reuse of the alloc. This is mitigated by the 'choose the one
11340 // afer the last picked one' logic when handing out batches.
11341
11342 auto nextFreeBatch = [this]() -> QRhiResourceUpdateBatch * {
11343 auto isFree = [this](int i) -> QRhiResourceUpdateBatch * {
11344 const quint64 mask = 1ULL << quint64(i);
11345 if (!(d->resUpdPoolMap & mask)) {
11346 d->resUpdPoolMap |= mask;
11347 QRhiResourceUpdateBatch *u = d->resUpdPool[i];
11348 QRhiResourceUpdateBatchPrivate::get(u)->poolIndex = i;
11349 d->lastResUpdIdx = i;
11350 return u;
11351 }
11352 return nullptr;
11353 };
11354 const int poolSize = d->resUpdPool.size();
11355 for (int i = d->lastResUpdIdx + 1; i < poolSize; ++i) {
11356 if (QRhiResourceUpdateBatch *u = isFree(i))
11357 return u;
11358 }
11359 for (int i = 0; i <= d->lastResUpdIdx; ++i) {
11360 if (QRhiResourceUpdateBatch *u = isFree(i))
11361 return u;
11362 }
11363 return nullptr;
11364 };
11365
11366 QRhiResourceUpdateBatch *u = nextFreeBatch();
11367 if (!u) {
11368 const int oldSize = d->resUpdPool.size();
11369 // 4, 8, 12, ..., up to 64
11370 const int newSize = oldSize + qMin(4, qMax(0, 64 - oldSize));
11371 d->resUpdPool.resize(newSize);
11372 for (int i = oldSize; i < newSize; ++i)
11373 d->resUpdPool[i] = new QRhiResourceUpdateBatch(d);
11374 u = nextFreeBatch();
11375 if (!u)
11376 qWarning("Resource update batch pool exhausted (max is 64)");
11377 }
11378
11379 return u;
11380}
11381
11383{
11384 Q_ASSERT(poolIndex >= 0 && rhi->resUpdPool[poolIndex] == q);
11385
11386 quint32 bufferDataTotal = 0;
11387 quint32 bufferLargeAllocTotal = 0;
11388 for (const BufferOp &op : std::as_const(bufferOps)) {
11389 bufferDataTotal += op.data.size();
11390 bufferLargeAllocTotal += op.data.largeAlloc(); // alloc when > 1 KB
11391 }
11392
11393 if (QRHI_LOG_RUB().isDebugEnabled()) {
11394 qDebug() << "[rub] release to pool upd.batch #" << poolIndex
11395 << "/ bufferOps active" << activeBufferOpCount
11396 << "of" << bufferOps.count()
11397 << "data" << bufferDataTotal
11398 << "largeAlloc" << bufferLargeAllocTotal
11399 << "textureOps active" << activeTextureOpCount
11400 << "of" << textureOps.count();
11401 }
11402
11405
11406 const quint64 mask = 1ULL << quint64(poolIndex);
11407 rhi->resUpdPoolMap &= ~mask;
11408 poolIndex = -1;
11409
11410 // textureOps is cleared, to not keep the potentially large image pixel
11411 // data alive, but it is expected that the container keeps the list alloc
11412 // at least. Only trimOpList() goes for the more aggressive route with squeeze.
11413 textureOps.clear();
11414
11415 // bufferOps is not touched in many cases, to allow reusing allocations
11416 // (incl. in the elements' QRhiBufferData) as much as possible when this
11417 // batch is used again in the future, which is important for performance, in
11418 // particular with Qt Quick where it is easy for scenes to produce lots of,
11419 // typically small buffer changes on every frame.
11420 //
11421 // However, ensure that even in the unlikely case of having the max number
11422 // of batches (64) created in resUpdPool, no more than 64 MB in total is
11423 // used up by buffer data just to help future reuse. For simplicity, if
11424 // there is more than 1 MB data -> clear. Applications with frequent, huge
11425 // buffer updates probably have other bottlenecks anyway.
11426 if (bufferLargeAllocTotal > 1024 * 1024)
11427 bufferOps.clear();
11428}
11429
11431{
11432 int combinedSize = activeBufferOpCount + other->activeBufferOpCount;
11433 if (bufferOps.size() < combinedSize)
11434 bufferOps.resize(combinedSize);
11435 for (int i = activeBufferOpCount; i < combinedSize; ++i)
11436 bufferOps[i] = std::move(other->bufferOps[i - activeBufferOpCount]);
11438
11439 combinedSize = activeTextureOpCount + other->activeTextureOpCount;
11440 if (textureOps.size() < combinedSize)
11441 textureOps.resize(combinedSize);
11442 for (int i = activeTextureOpCount; i < combinedSize; ++i)
11443 textureOps[i] = std::move(other->textureOps[i - activeTextureOpCount]);
11445}
11446
11452
11454{
11455 // Unlike free(), this is expected to aggressively deallocate all memory
11456 // used by both the buffer and texture operation lists. (i.e. using
11457 // squeeze() to only keep the stack prealloc of the QVLAs)
11458 //
11459 // This (e.g. just the destruction of bufferOps elements) may have a
11460 // non-negligible performance impact e.g. with Qt Quick with scenes where
11461 // there are lots of buffer operations per frame.
11462
11464 bufferOps.clear();
11465 bufferOps.squeeze();
11466
11468 textureOps.clear();
11469 textureOps.squeeze();
11470}
11471
11472/*!
11473 Sometimes committing resource updates is necessary or just more convenient
11474 without starting a render pass. Calling this function with \a
11475 resourceUpdates is an alternative to passing \a resourceUpdates to a
11476 beginPass() call (or endPass(), which would be typical in case of readbacks).
11477
11478 \note Cannot be called inside a pass.
11479 */
11480void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
11481{
11482 if (resourceUpdates)
11483 m_rhi->resourceUpdate(this, resourceUpdates);
11484}
11485
11486/*!
11487 Records starting a new render pass targeting the render target \a rt.
11488
11489 \a resourceUpdates, when not null, specifies a resource update batch that
11490 is to be committed and then released.
11491
11492 The color and depth/stencil buffers of the render target are normally
11493 cleared. The clear values are specified in \a colorClearValue and \a
11494 depthStencilClearValue. The exception is when the render target was created
11495 with QRhiTextureRenderTarget::PreserveColorContents and/or
11496 QRhiTextureRenderTarget::PreserveDepthStencilContents. The clear values are
11497 ignored then.
11498
11499 \note Enabling preserved color or depth contents leads to decreased
11500 performance depending on the underlying hardware. Mobile GPUs with tiled
11501 architecture benefit from not having to reload the previous contents into
11502 the tile buffer. Similarly, a QRhiTextureRenderTarget with a QRhiTexture as
11503 the depth buffer is less efficient than a QRhiRenderBuffer since using a
11504 depth texture triggers requiring writing the data out to it, while with
11505 renderbuffers this is not needed (as the API does not allow sampling or
11506 reading from a renderbuffer).
11507
11508 \note Do not assume that any state or resource bindings persist between
11509 passes.
11510
11511 \note The QRhiCommandBuffer's \c set and \c draw functions can only be
11512 called inside a pass. Also, with the exception of setGraphicsPipeline(),
11513 they expect to have a pipeline set already on the command buffer.
11514 Unspecified issues may arise otherwise, depending on the backend.
11515
11516 If \a rt is a QRhiTextureRenderTarget, beginPass() performs a check to see
11517 if the texture and renderbuffer objects referenced from the render target
11518 are up-to-date. This is similar to what setShaderResources() does for
11519 QRhiShaderResourceBindings. If any of the attachments had been rebuilt
11520 since QRhiTextureRenderTarget::create(), an implicit call to create() is
11521 made on \a rt. Therefore, if \a rt has a QRhiTexture color attachment \c
11522 texture, and one needs to make the texture a different size, the following
11523 is then valid:
11524 \code
11525 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ { texture } });
11526 rt->create();
11527 // ...
11528 texture->setPixelSize(new_size);
11529 texture->create();
11530 cb->beginPass(rt, colorClear, dsClear); // this is ok, no explicit rt->create() is required before
11531 \endcode
11532
11533 \a flags allow controlling certain advanced functionality. One commonly used
11534 flag is \c ExternalContents. This should be specified whenever
11535 beginExternal() will be called within the pass started by this function.
11536
11537 \sa endPass(), BeginPassFlags
11538 */
11539void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
11540 const QColor &colorClearValue,
11541 const QRhiDepthStencilClearValue &depthStencilClearValue,
11542 QRhiResourceUpdateBatch *resourceUpdates,
11543 BeginPassFlags flags)
11544{
11545 m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates, flags);
11546}
11547
11548/*!
11549 Records ending the current render pass.
11550
11551 \a resourceUpdates, when not null, specifies a resource update batch that
11552 is to be committed and then released.
11553
11554 \sa beginPass()
11555 */
11556void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates)
11557{
11558 m_rhi->endPass(this, resourceUpdates);
11559}
11560
11561/*!
11562 Records setting a new graphics pipeline \a ps.
11563
11564 \note This function must be called before recording other \c set or \c draw
11565 commands on the command buffer.
11566
11567 \note QRhi will optimize out unnecessary invocations within a pass, so
11568 therefore overoptimizing to avoid calls to this function is not necessary
11569 on the applications' side.
11570
11571 \note This function can only be called inside a render pass, meaning
11572 between a beginPass() and endPass() call.
11573
11574 \note The new graphics pipeline \a ps must be a valid pointer.
11575
11576 Setting a graphics pipeline that does not have the
11577 \l{QRhiGraphicsPipeline::}{UsesScissor} flag will either disable scissoring,
11578 with graphics APIs where that is applicable, or set the scissor rectangle to
11579 match the viewport that was last set (with graphics APIs where scissoring is
11580 effectively always active), in order to ensure a uniform behavior across QRhi
11581 backends.
11582 */
11583void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)
11584{
11585 Q_ASSERT(ps != nullptr);
11586 m_rhi->setGraphicsPipeline(this, ps);
11587}
11588
11589/*!
11590 Records binding a set of shader resources, such as, uniform buffers or
11591 textures, that are made visible to one or more shader stages.
11592
11593 \a srb can be null in which case the current graphics or compute pipeline's
11594 associated QRhiShaderResourceBindings is used. When \a srb is non-null, it
11595 must be
11596 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible},
11597 meaning the layout (number of bindings, the type and binding number of each
11598 binding) must fully match the QRhiShaderResourceBindings that was
11599 associated with the pipeline at the time of calling the pipeline's create().
11600
11601 There are cases when a seemingly unnecessary setShaderResources() call is
11602 mandatory: when rebuilding a resource referenced from \a srb, for example
11603 changing the size of a QRhiBuffer followed by a QRhiBuffer::create(), this
11604 is the place where associated native objects (such as descriptor sets in
11605 case of Vulkan) are updated to refer to the current native resources that
11606 back the QRhiBuffer, QRhiTexture, QRhiSampler objects referenced from \a
11607 srb. In this case setShaderResources() must be called even if \a srb is
11608 the same as in the last call.
11609
11610 When \a srb is not null, the QRhiShaderResourceBindings object the pipeline
11611 was built with in create() is guaranteed to be not accessed in any form. In
11612 fact, it does not need to be valid even at this point: destroying the
11613 pipeline's associated srb after create() and instead explicitly specifying
11614 another, \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout
11615 compatible} one in every setShaderResources() call is valid.
11616
11617 \a dynamicOffsets allows specifying buffer offsets for uniform buffers that
11618 were associated with \a srb via
11619 QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(). This is
11620 different from providing the offset in the \a srb itself: dynamic offsets
11621 do not require building a new QRhiShaderResourceBindings for every
11622 different offset, can avoid writing the underlying descriptors (with
11623 backends where applicable), and so they may be more efficient. Each element
11624 of \a dynamicOffsets is a \c binding - \c offset pair.
11625 \a dynamicOffsetCount specifies the number of elements in \a dynamicOffsets.
11626
11627 \note All offsets in \a dynamicOffsets must be byte aligned to the value
11628 returned from QRhi::ubufAlignment().
11629
11630 \note Some backends may limit the number of supported dynamic offsets.
11631 Avoid using a \a dynamicOffsetCount larger than 8.
11632
11633 \note QRhi will optimize out unnecessary invocations within a pass (taking
11634 the conditions described above into account), so therefore overoptimizing
11635 to avoid calls to this function is not necessary on the applications' side.
11636
11637 \note This function can only be called inside a render or compute pass,
11638 meaning between a beginPass() and endPass(), or beginComputePass() and
11639 endComputePass().
11640 */
11641void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb,
11642 int dynamicOffsetCount,
11643 const DynamicOffset *dynamicOffsets)
11644{
11645 m_rhi->setShaderResources(this, srb, dynamicOffsetCount, dynamicOffsets);
11646}
11647
11648/*!
11649 Records vertex input bindings.
11650
11651 The index buffer used by subsequent drawIndexed() commands is specified by
11652 \a indexBuf, \a indexOffset, and \a indexFormat. \a indexBuf can be set to
11653 null when indexed drawing is not needed.
11654
11655 Vertex buffer bindings are batched. \a startBinding specifies the first
11656 binding number. The recorded command then binds each buffer from \a
11657 bindings to the binding point \c{startBinding + i} where \c i is the index
11658 in \a bindings. Each element in \a bindings specifies a QRhiBuffer and an
11659 offset.
11660
11661 \note Some backends may limit the number of vertex buffer bindings. Avoid
11662 using a \a bindingCount larger than 8.
11663
11664 Superfluous vertex input and index changes in the same pass are ignored
11665 automatically with most backends and therefore applications do not need to
11666 overoptimize to avoid calls to this function.
11667
11668 \note This function can only be called inside a render pass, meaning
11669 between a beginPass() and endPass() call.
11670
11671 As a simple example, take a vertex shader with two inputs:
11672
11673 \badcode
11674 layout(location = 0) in vec4 position;
11675 layout(location = 1) in vec3 color;
11676 \endcode
11677
11678 and assume we have the data available in interleaved format, using only 2
11679 floats for position (so 5 floats per vertex: x, y, r, g, b). A QRhiGraphicsPipeline for
11680 this shader can then be created using the input layout:
11681
11682 \code
11683 QRhiVertexInputLayout inputLayout;
11684 inputLayout.setBindings({
11685 { 5 * sizeof(float) }
11686 });
11687 inputLayout.setAttributes({
11688 { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
11689 { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
11690 });
11691 \endcode
11692
11693 Here there is one buffer binding (binding number 0), with two inputs
11694 referencing it. When recording the pass, once the pipeline is set, the
11695 vertex bindings can be specified simply like the following, assuming vbuf
11696 is the QRhiBuffer with all the interleaved position+color data:
11697
11698 \code
11699 const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
11700 cb->setVertexInput(0, 1, &vbufBinding);
11701 \endcode
11702 */
11703void QRhiCommandBuffer::setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
11704 QRhiBuffer *indexBuf, quint32 indexOffset,
11705 IndexFormat indexFormat)
11706{
11707 m_rhi->setVertexInput(this, startBinding, bindingCount, bindings, indexBuf, indexOffset, indexFormat);
11708}
11709
11710/*!
11711 Records setting the active viewport rectangle specified in \a viewport.
11712
11713 With backends where the underlying graphics API has scissoring always
11714 enabled, this function also sets the scissor to match the viewport whenever
11715 the active QRhiGraphicsPipeline does not have
11716 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set.
11717
11718 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
11719 bottom-left.
11720
11721 \note This function can only be called inside a render pass, meaning
11722 between a beginPass() and endPass() call.
11723 */
11724void QRhiCommandBuffer::setViewport(const QRhiViewport &viewport)
11725{
11726 m_rhi->setViewport(this, viewport);
11727}
11728
11729/*!
11730 Records setting the active scissor rectangle specified in \a scissor.
11731
11732 This can only be called when the bound pipeline has
11733 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set. When the flag is
11734 set on the active pipeline, this function must be called because scissor
11735 testing will get enabled and so a scissor rectangle must be provided.
11736
11737 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
11738 bottom-left.
11739
11740 \note This function can only be called inside a render pass, meaning
11741 between a beginPass() and endPass() call.
11742 */
11743void QRhiCommandBuffer::setScissor(const QRhiScissor &scissor)
11744{
11745 m_rhi->setScissor(this, scissor);
11746}
11747
11748/*!
11749 Records setting the active blend constants to \a c.
11750
11751 This can only be called when the bound pipeline has
11752 QRhiGraphicsPipeline::UsesBlendConstants set.
11753
11754 \note This function can only be called inside a render pass, meaning
11755 between a beginPass() and endPass() call.
11756 */
11757void QRhiCommandBuffer::setBlendConstants(const QColor &c)
11758{
11759 m_rhi->setBlendConstants(this, c);
11760}
11761
11762/*!
11763 Records setting the active stencil reference value to \a refValue.
11764
11765 This can only be called when the bound pipeline has
11766 QRhiGraphicsPipeline::UsesStencilRef set.
11767
11768 \note This function can only be called inside a render pass, meaning between
11769 a beginPass() and endPass() call.
11770 */
11771void QRhiCommandBuffer::setStencilRef(quint32 refValue)
11772{
11773 m_rhi->setStencilRef(this, refValue);
11774}
11775
11776/*!
11777 Records setting the push constant data for the currently bound graphics or
11778 compute pipeline. \a size bytes are taken from \a data and placed at byte
11779 offset \a offset within the push constant block. Both \a offset and \a
11780 size must be a multiple of 4.
11781
11782 Push constants are a small, pipeline-layout-resident block of data that can
11783 be updated between draw calls without touching any
11784 QRhiShaderResourceBindings. This makes them suitable for per-draw values
11785 such as an index into a storage buffer, avoiding a setShaderResources()
11786 call per draw.
11787
11788 The shaders declare the block in the usual way, for example:
11789
11790 \badcode
11791 layout(push_constant) uniform PC { uint objectIndex; } pc;
11792 \endcode
11793
11794 \note A push constant block defaults to the std430 layout, unlike a
11795 uniform block. There an array of scalars or of \c vec2 is tightly packed,
11796 and so are the columns of a matrix with two rows (\c mat2, \c mat3x2,
11797 \c mat4x2). Neither can be expressed in a Direct3D constant buffer, so a
11798 block that has such a member has to be declared with
11799 \c{layout(push_constant, std140)} in order to be usable with the D3D
11800 backends. (qsb reports an error when baking such a shader for HLSL) Blocks
11801 with only scalars, vectors, and \c mat3 or \c mat4 matrices, which is what
11802 push constants are mostly used for, are unaffected.
11803
11804 QRhi derives the push constant range from the shader reflection data of the
11805 pipeline's shader stages, so no extra declaration is needed on the
11806 QRhiGraphicsPipeline or QRhiComputePipeline.
11807
11808 \note This is only functional when the PushConstants feature is reported as
11809 supported. The maximum size of the block is reported by the
11810 MaxPushConstantsSize resource limit.
11811
11812 \note With Metal, push constants are not supported with a graphics pipeline
11813 that uses tessellation. Calling this function while such a pipeline is
11814 bound has no effect, apart from a warning.
11815
11816 \note Must be called inside a pass, after setGraphicsPipeline() or
11817 setComputePipeline().
11818
11819 \note The data does not persist. It has to be set again in every pass and
11820 after every change of pipeline. The backends differ in how much they would
11821 otherwise retain, so relying on anything else is not portable.
11822
11823 \since 6.13
11824 */
11825void QRhiCommandBuffer::setPushConstants(quint32 offset, quint32 size, const void *data)
11826{
11827 m_rhi->setPushConstants(this, offset, size, data);
11828}
11829
11830/*!
11831 Sets the shading rate for the following draw calls to \a coarsePixelSize.
11832
11833 The default is 1x1.
11834
11835 Functional only when the \l QRhi::VariableRateShading feature is reported as
11836 supported and the QRhiGraphicsPipeline(s) bound on the command buffer were
11837 declaring \l QRhiGraphicsPipeline::UsesShadingRate when creating them.
11838
11839 Call \l QRhi::supportedShadingRates() to check what shading rates are
11840 supported for a given sample count.
11841
11842 When both a QRhiShadingRateMap and this function are in use, the higher of
11843 the two shading rates is used for each tile. There is currently no control
11844 offered over the combiner behavior.
11845
11846 \since 6.9
11847 */
11848void QRhiCommandBuffer::setShadingRate(const QSize &coarsePixelSize)
11849{
11850 m_rhi->setShadingRate(this, coarsePixelSize);
11851}
11852
11853/*!
11854 Records a non-indexed draw.
11855
11856 The number of vertices is specified in \a vertexCount. For instanced
11857 drawing set \a instanceCount to a value other than 1. \a firstVertex is the
11858 index of the first vertex to draw. When drawing multiple instances, the
11859 first instance ID is specified by \a firstInstance.
11860
11861 \note \a firstInstance may not be supported, and is ignored when the
11862 QRhi::BaseInstance feature is reported as not supported. The first instance
11863 ID is always 0 in that case. QRhi::BaseInstance is never supported with
11864 OpenGL ES, and therefore portable applications should not be designed to
11865 rely on this argument.
11866
11867 \note Shaders that need to access the index of the current vertex or
11868 instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
11869 Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
11870 gl_InstanceID.
11871
11872 \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
11873 include the base value with some of the underlying 3D APIs. This is
11874 indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
11875 on a base instance value cannot be avoided, applications are advised to pass
11876 in the value as a uniform conditionally based on what that feature reports,
11877 and add it to \c gl_InstanceIndex in the shader.
11878
11879 \note This function can only be called inside a render pass, meaning
11880 between a beginPass() and endPass() call.
11881 */
11882void QRhiCommandBuffer::draw(quint32 vertexCount,
11883 quint32 instanceCount,
11884 quint32 firstVertex,
11885 quint32 firstInstance)
11886{
11887 m_rhi->draw(this, vertexCount, instanceCount, firstVertex, firstInstance);
11888}
11889
11890/*!
11891 Records an indexed draw.
11892
11893 The number of vertices is specified in \a indexCount. \a firstIndex is the
11894 base index. The effective offset in the index buffer is given by
11895 \c{indexOffset + firstIndex * n} where \c n is 2 or 4 depending on the
11896 index element type. \c indexOffset is specified in setVertexInput().
11897
11898 \note The effective offset in the index buffer must be 4 byte aligned with
11899 some backends (for example, Metal). With these backends the
11900 \l{QRhi::NonFourAlignedEffectiveIndexBufferOffset}{NonFourAlignedEffectiveIndexBufferOffset}
11901 feature will be reported as not-supported.
11902
11903 \a vertexOffset (also called \c{base vertex}) is a signed value that is
11904 added to the element index before indexing into the vertex buffer. Support
11905 for this is not always available, and the value is ignored when the feature
11906 QRhi::BaseVertex is reported as unsupported.
11907
11908 For instanced drawing set \a instanceCount to a value other than 1. When
11909 drawing multiple instances, the first instance ID is specified by \a
11910 firstInstance.
11911
11912 \note \a firstInstance may not be supported, and is ignored when the
11913 QRhi::BaseInstance feature is reported as not supported. The first instance
11914 ID is always 0 in that case. QRhi::BaseInstance is never supported with
11915 OpenGL ES, and therefore portable applications should not be designed to
11916 rely on this argument.
11917
11918 \note Shaders that need to access the index of the current vertex or
11919 instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
11920 Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
11921 gl_InstanceID.
11922
11923 \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
11924 include the base value with some of the underlying 3D APIs. This is
11925 indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
11926 on a base instance value cannot be avoided, applications are advised to pass
11927 in the value as a uniform conditionally based on what that feature reports,
11928 and add it to \c gl_InstanceIndex in the shader.
11929
11930 \note This function can only be called inside a render pass, meaning
11931 between a beginPass() and endPass() call.
11932 */
11933void QRhiCommandBuffer::drawIndexed(quint32 indexCount,
11934 quint32 instanceCount,
11935 quint32 firstIndex,
11936 qint32 vertexOffset,
11937 quint32 firstInstance)
11938{
11939 m_rhi->drawIndexed(this, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
11940}
11941
11942/*!
11943 Records a non-indexed, indirect draw.
11944
11945 The draw parameters are provided by the buffer specified in \a indirectBuffer,
11946 which must contain an array of elements of type QRhiIndirectDrawCommand.
11947 The parameters in QRhiIndirectDrawCommand have the same meaning as in draw().
11948
11949 The offset, in bytes, from which the parameters are read in the buffer is specified
11950 by \a indirectBufferOffset.
11951
11952 \a drawCount specifies the number of such draw commands to issue.
11953
11954 \a stride indicates the byte size of each individual draw command structure
11955 in the buffer. This allows interleaving custom data between commands if needed.
11956 The value must be a multiple of 4 and greater than or equal to sizeof(QRhiIndirectDrawCommand).
11957
11958 \note A \a drawCount value greater than 1 is only natively supported if the
11959 QRhi::DrawIndirectMulti feature is reported as supported.
11960 Otherwise, this function emulates multi-draw by recording multiple draw calls,
11961 offering no performance benefit over repeated draw() calls.
11962
11963 \note Leaving \a stride at its default is recommended whenever performance
11964 matters. With Direct 3D 12 a non-default stride prevents issuing a single
11965 native multi-draw, forcing the backend to record one command per draw
11966 instead. For a large \a drawCount this can be an order of magnitude slower,
11967 which defeats the purpose of the indirect draw. Vulkan, OpenGL, and Metal
11968 pass the stride on to their native multi-draw entry points and are not
11969 affected. Rather than interleaving custom data between the commands, keep
11970 that data in a separate buffer and index into it.
11971
11972 \note The render pass interruption and the render target consequences and
11973 limitations described for drawIndexedIndirect() apply here as well.
11974
11975 \note Therefore, portable applications should consider always using
11976 QRhiIndirectCommandBuffer and executeIndirect() instead of the
11977 draw*Indirect*() family of functions.
11978
11979 \note This function can only be called inside a render pass, meaning
11980 between a beginPass() and endPass() call.
11981
11982 \since 6.12
11983
11984 \sa drawIndexedIndirect(), drawIndirectCount(), drawIndexedIndirectCount()
11985 */
11986void QRhiCommandBuffer::drawIndirect(QRhiBuffer *indirectBuffer,
11987 quint32 indirectBufferOffset,
11988 quint32 drawCount,
11989 quint32 stride)
11990{
11991 Q_ASSERT(indirectBuffer);
11992 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
11993 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
11994 Q_ASSERT(stride >= sizeof(QRhiIndirectDrawCommand));
11995 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
11996 m_rhi->drawIndirect(this, indirectBuffer, indirectBufferOffset, drawCount, stride);
11997}
11998
11999/*!
12000 Records an indexed, indirect draw.
12001
12002 The draw parameters are provided by the buffer specified in \a indirectBuffer,
12003 which must contain an array of elements of type QRhiIndexedIndirectDrawCommand.
12004 The parameters in QRhiIndexedIndirectDrawCommand have the same meaning as in drawIndexed().
12005
12006 The offset, in bytes, from which the parameters are read in the buffer is specified
12007 by \a indirectBufferOffset.
12008
12009 \a drawCount specifies the number of such draw commands to issue.
12010
12011 \a stride indicates the byte size of each individual draw command structure
12012 in the buffer. This allows interleaving custom data between commands if needed.
12013 The value must be a multiple of 4 and greater than or equal to sizeof(QRhiIndexedIndirectDrawCommand).
12014
12015 \note A \a drawCount value greater than 1 is only natively supported if the
12016 QRhi::DrawIndirectMulti feature is reported as supported.
12017 Otherwise, this function emulates multi-draw by recording multiple draw calls,
12018 offering no performance benefit over repeated drawIndexed() calls.
12019
12020 \note Leaving \a stride at its default is recommended whenever performance
12021 matters. With Direct 3D 12 a non-default stride prevents issuing a single
12022 native multi-draw, forcing the backend to record one command per draw
12023 instead. For a large \a drawCount this can be an order of magnitude slower,
12024 which defeats the purpose of the indirect draw. Vulkan, OpenGL, and Metal
12025 pass the stride on to their native multi-draw entry points and are not
12026 affected. Rather than interleaving custom data between the commands, keep
12027 that data in a separate buffer and index into it.
12028
12029 \note With some backends a large \a drawCount is implemented by interrupting
12030 and then restarting the render pass internally due to launching a compute
12031 kernel to encode commands into an indirect command buffer. With Metal this
12032 happens above a certain \a drawCount (e.g., 128). This has consequences for
12033 the render targets: color attachment contents are preserved automatically,
12034 but a QRhiRenderBuffer serving as the depth-stencil buffer only keeps its
12035 contents if it was created with QRhiRenderBuffer::NoTransientBacking, which
12036 means that, with Metal, rendering errors may occur if the depth-stencil
12037 buffer is a QRhiRenderBuffer without the NoTransientBacking flag and the \a
12038 drawCount is above the threshold. Recording the same commands into a
12039 QRhiIndirectCommandBuffer and issuing them with executeIndirect() avoids
12040 this altogether: that never interrupts the pass.
12041
12042 \note Therefore, portable applications should consider always using
12043 QRhiIndirectCommandBuffer and executeIndirect() instead of the
12044 draw*Indirect*() family of functions.
12045
12046 \note This function can only be called inside a render pass, meaning
12047 between a beginPass() and endPass() call.
12048
12049 \since 6.12
12050
12051 \sa drawIndirect(), drawIndirectCount(), drawIndexedIndirectCount()
12052 */
12053void QRhiCommandBuffer::drawIndexedIndirect(QRhiBuffer *indirectBuffer,
12054 quint32 indirectBufferOffset,
12055 quint32 drawCount,
12056 quint32 stride)
12057{
12058 Q_ASSERT(indirectBuffer);
12059 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12060 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12061 Q_ASSERT(stride >= sizeof(QRhiIndexedIndirectDrawCommand));
12062 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
12063 m_rhi->drawIndexedIndirect(this, indirectBuffer, indirectBufferOffset, drawCount, stride);
12064}
12065
12066/*!
12067 Records a non-indexed, indirect draw, with the draw count itself read
12068 from a buffer at execution time.
12069
12070 Draw parameters are read from \a indirectBuffer at byte offset
12071 \a indirectBufferOffset as an array of QRhiIndirectDrawCommand entries
12072 spaced \a stride bytes apart. The number of draws issued is the 32-bit
12073 unsigned integer stored at \a countBufferOffset in \a countBuffer, clamped
12074 to \a maxDrawCount.
12075
12076 Both buffers must have QRhiBuffer::IndirectBuffer usage. Offsets must be
12077 4-byte aligned; \a stride must be 4-byte aligned and at least
12078 sizeof(QRhiIndirectDrawCommand).
12079
12080 Only available when \l QRhi::DrawIndirectCount is reported as supported.
12081 On other backends this is a no-op and a warning is logged. With Metal there
12082 are additional requirements, see QRhi::DrawIndirectCount.
12083
12084 \note Unlike with drawIndirect(), a non-default \a stride does not prevent
12085 the use of a single native multi-draw here. With Direct 3D 12 it does mean
12086 that an additional command signature is created and cached for each
12087 distinct stride value, so sticking to one stride is still preferable.
12088
12089 \note The value in \a countBuffer is read as a \e signed 32-bit integer by
12090 OpenGL, unlike the other backends. Counts above \c INT_MAX are therefore
12091 not portable, and neither is relying on any particular behavior for a count
12092 that exceeds \a maxDrawCount, beyond the clamping described above.
12093
12094 \note With some backends, Metal in particular, the render pass is always
12095 interrupted and restarted internally because the draw commands have to be
12096 encoded on the GPU. Color attachment contents are preserved automatically,
12097 but a QRhiRenderBuffer serving as the depth-stencil buffer only keeps its
12098 contents if it was created with QRhiRenderBuffer::NoTransientBacking.
12099 Building a QRhiIndirectCommandBuffer with buildIndirect(),
12100 which happens before the pass begins, and issuing it with
12101 executeIndirect() avoids this: that never interrupts the pass, and supports
12102 a device-side count just the same.
12103
12104 \note Therefore, portable applications should consider always using
12105 QRhiIndirectCommandBuffer and executeIndirect() instead of the
12106 draw*Indirect*() family of functions.
12107
12108 \note \a maxDrawCount is not a free upper bound. With Metal it sizes the
12109 indirect command buffer that the draw commands are encoded into, and that
12110 buffer is shared, grows on demand, and is never shrunk again for the
12111 lifetime of the QRhi. It also determines how many encoding threads are
12112 dispatched every time. Passing the capacity of \a indirectBuffer instead of
12113 a realistic upper bound therefore has a real cost.
12114
12115 \note Only valid inside a render pass.
12116
12117 \since 6.13
12118
12119 \sa drawIndirect(), drawIndexedIndirect(), drawIndexedIndirectCount()
12120 */
12121void QRhiCommandBuffer::drawIndirectCount(QRhiBuffer *indirectBuffer,
12122 quint32 indirectBufferOffset,
12123 QRhiBuffer *countBuffer,
12124 quint32 countBufferOffset,
12125 quint32 maxDrawCount,
12126 quint32 stride)
12127{
12128 Q_ASSERT(indirectBuffer);
12129 Q_ASSERT(countBuffer);
12130 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12131 Q_ASSERT(countBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12132 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12133 Q_ASSERT_X((countBufferOffset & 3u) == 0u, Q_FUNC_INFO, "countBufferOffset must be a multiple of 4");
12134 Q_ASSERT(stride >= sizeof(QRhiIndirectDrawCommand));
12135 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
12136 m_rhi->drawIndirectCount(this, indirectBuffer, indirectBufferOffset,
12137 countBuffer, countBufferOffset, maxDrawCount, stride);
12138}
12139
12140/*!
12141 Indexed variant of drawIndirectCount(). \a indirectBuffer contains, at byte
12142 offset \a indirectBufferOffset, QRhiIndexedIndirectDrawCommand entries,
12143 spaced \a stride bytes apart, and \a stride must be at least
12144 sizeof(QRhiIndexedIndirectDrawCommand). All other requirements, including
12145 how \a countBuffer, \a countBufferOffset and \a maxDrawCount are
12146 interpreted, are as described for drawIndirectCount().
12147
12148 \note The render pass interruption described for drawIndirectCount() applies
12149 here as well.
12150
12151 \note Therefore, portable applications should consider always using
12152 QRhiIndirectCommandBuffer and executeIndirect() instead of the
12153 draw*Indirect*() family of functions.
12154
12155 \note Only valid inside a render pass.
12156
12157 \since 6.13
12158
12159 \sa drawIndirect(), drawIndexedIndirect(), drawIndirectCount()
12160 */
12161void QRhiCommandBuffer::drawIndexedIndirectCount(QRhiBuffer *indirectBuffer,
12162 quint32 indirectBufferOffset,
12163 QRhiBuffer *countBuffer,
12164 quint32 countBufferOffset,
12165 quint32 maxDrawCount,
12166 quint32 stride)
12167{
12168 Q_ASSERT(indirectBuffer);
12169 Q_ASSERT(countBuffer);
12170 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12171 Q_ASSERT(countBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12172 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12173 Q_ASSERT_X((countBufferOffset & 3u) == 0u, Q_FUNC_INFO, "countBufferOffset must be a multiple of 4");
12174 Q_ASSERT(stride >= sizeof(QRhiIndexedIndirectDrawCommand));
12175 Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
12176 m_rhi->drawIndexedIndirectCount(this, indirectBuffer, indirectBufferOffset,
12177 countBuffer, countBufferOffset, maxDrawCount, stride);
12178}
12179
12180/*!
12181 Records populating the indirect command buffer \a icb from the buffer and
12182 parameters described by \a info.
12183
12184 This is the GPU-driven counterpart of recording draw() or drawIndexed()
12185 calls on the QRhiIndirectCommandBuffer: the commands come from
12186 \c{info.sourceBuffer}, which is typically written by a compute shader
12187 earlier in the frame. Any commands recorded on the CPU side are ignored
12188 from this point on.
12189
12190 \c{info.topology} and, for an indirect command buffer of type
12191 QRhiIndirectCommandBuffer::IndexedDraws, \c{info.indexBuffer} have to be
12192 specified because some backends need them in order to build their native
12193 indirect command buffer object, and neither is available outside of a
12194 render pass. They must match what is set on the command buffer when
12195 executeIndirect() is called.
12196
12197 \c{info.commandCount} is the number of commands to take from
12198 \c{info.sourceBuffer}, and becomes what
12199 QRhiIndirectCommandBuffer::commandCount() reports from here on. Leaving it
12200 at 0 means \a{icb}'s QRhiIndirectCommandBuffer::maxCommandCount(); a larger
12201 value is clamped to that, with a warning. The size of
12202 \c{info.sourceBuffer} is not consulted. When \c{info.countBuffer} is set,
12203 \c{info.commandCount} becomes an upper bound instead, with the device-side
12204 count deciding how many commands are executed.
12205
12206 \note This function must be called outside of any pass. That is the entire
12207 point: it gives backends that need to run a compute shader in order to
12208 build their native indirect command buffer a place to do so without having
12209 to interrupt and restart the render pass.
12210
12211 \sa executeIndirect(), QRhiIndirectCommandBuffer
12212 */
12213void QRhiCommandBuffer::buildIndirect(QRhiIndirectCommandBuffer *icb,
12214 const QRhiIndirectCommandBufferBuildInfo &info)
12215{
12216 Q_ASSERT(icb);
12217 Q_ASSERT(info.sourceBuffer);
12218 Q_ASSERT(info.sourceBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12219 Q_ASSERT_X((info.sourceBufferOffset & 3u) == 0u, Q_FUNC_INFO,
12220 "sourceBufferOffset must be a multiple of 4");
12221 Q_ASSERT_X((info.stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
12222 Q_ASSERT(!info.countBuffer || info.countBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12223 Q_ASSERT_X((info.countBufferOffset & 3u) == 0u, Q_FUNC_INFO,
12224 "countBufferOffset must be a multiple of 4");
12225 m_rhi->buildIndirect(this, icb, info);
12226}
12227
12228/*!
12229 Records executing the commands held by the indirect command buffer \a icb,
12230 starting at \a firstCommand and executing at most \a commandCount of them.
12231 By default all commands are executed.
12232
12233 Everything else - the graphics pipeline, the vertex and index buffers, the
12234 shader resources, the viewport, the scissor - is taken from the current
12235 state of the command buffer, exactly like with drawIndirect().
12236
12237 The number of draws issued is \c{qMin(commandCount, icb->commandCount() -
12238 firstCommand)}, so leaving \a commandCount at its default executes
12239 everything from \a firstCommand onwards. What
12240 QRhiIndirectCommandBuffer::commandCount() means depends on how \a icb was
12241 populated: it is the number of draw() and drawIndexed() calls recorded on
12242 it, or, after a buildIndirect(), the count resolved from
12243 QRhiIndirectCommandBufferBuildInfo::commandCount. Nothing is drawn when \a
12244 firstCommand is at or past that count.
12245
12246 When \a icb was populated by recording draw() or drawIndexed() calls on it,
12247 the recorded contents must have been flushed with
12248 QRhiResourceUpdateBatch::commitIndirectCommandBuffer() beforehand. When it
12249 was populated with buildIndirect(), and a count buffer was specified there,
12250 the device-side count reduces the number of draws further: the number
12251 actually executed is the smallest of that, \a commandCount, and what is
12252 left in \a icb after \a firstCommand.
12253
12254 \warning With a count buffer some backends, Metal in particular, cannot combine
12255 the device-side count with a subrange. \a firstCommand and \a commandCount
12256 are then ignored, printing a warning, and all commands up to the device-side
12257 count are executed.
12258
12259 \note An indirect command buffer that was populated by recording draw() or
12260 drawIndexed() calls on it can be executed any number of times, but within
12261 one frame all those executions must use the same topology, index buffer,
12262 index buffer offset and index format: some backends bake these into their
12263 native indirect command buffer at the first executeIndirect() of the frame.
12264 A mismatch is reported with a warning, and handled by falling back to
12265 ordinary draw calls.
12266
12267 \note Unlike drawIndirect(), drawIndexedIndirect(), drawIndirectCount() and
12268 drawIndexedIndirectCount(), this never causes the render pass to be
12269 interrupted and restarted internally, whatever the number of commands.
12270 Commands built with buildIndirect() were prepared before the pass began, and
12271 CPU-recorded ones need no compute work to encode. The consequences described
12272 for those functions therefore do not apply here. Color attachment contents
12273 are not at risk, and a QRhiRenderBuffer serving as the depth-stencil buffer
12274 keeps its contents without needing QRhiRenderBuffer::NoTransientBacking.
12275
12276 \note The CPU cost of this call is not constant for a CPU-recorded indirect
12277 command buffer. When the recorded contents changed since the last execution,
12278 some backends do their per-command native encoding here rather than in
12279 QRhiResourceUpdateBatch::commitIndirectCommandBuffer(), which for a large
12280 command set re-recorded every frame can dominate the time spent between
12281 beginPass() and endPass(). See \l QRhiIndirectCommandBuffer for how the cost
12282 of CPU recording scales.
12283
12284 \note This function can only be called inside a render pass.
12285
12286 \sa buildIndirect(), drawIndirect(), QRhiIndirectCommandBuffer
12287 */
12288void QRhiCommandBuffer::executeIndirect(QRhiIndirectCommandBuffer *icb,
12289 quint32 firstCommand,
12290 quint32 commandCount)
12291{
12292 Q_ASSERT(icb);
12293 m_rhi->executeIndirect(this, icb, firstCommand, commandCount);
12294}
12295
12296/*!
12297 Records a named debug group on the command buffer with the specified \a
12298 name. This is shown in graphics debugging tools such as
12299 \l{https://renderdoc.org/}{RenderDoc} and
12300 \l{https://developer.apple.com/xcode/}{XCode}. The end of the grouping is
12301 indicated by debugMarkEnd().
12302
12303 \note Ignored when QRhi::DebugMarkers are not supported or
12304 QRhi::EnableDebugMarkers is not set.
12305
12306 \note Can be called anywhere within the frame, both inside and outside of passes.
12307 */
12308void QRhiCommandBuffer::debugMarkBegin(const QByteArray &name)
12309{
12310 m_rhi->debugMarkBegin(this, name);
12311}
12312
12313/*!
12314 Records the end of a debug group.
12315
12316 \note Ignored when QRhi::DebugMarkers are not supported or
12317 QRhi::EnableDebugMarkers is not set.
12318
12319 \note Can be called anywhere within the frame, both inside and outside of passes.
12320 */
12321void QRhiCommandBuffer::debugMarkEnd()
12322{
12323 m_rhi->debugMarkEnd(this);
12324}
12325
12326/*!
12327 Inserts a debug message \a msg into the command stream.
12328
12329 \note Ignored when QRhi::DebugMarkers are not supported or
12330 QRhi::EnableDebugMarkers is not set.
12331
12332 \note With some backends debugMarkMsg() is only supported inside a pass and
12333 is ignored when called outside a pass. With others it is recorded anywhere
12334 within the frame.
12335 */
12336void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)
12337{
12338 m_rhi->debugMarkMsg(this, msg);
12339}
12340
12341/*!
12342 Records starting a new compute pass.
12343
12344 \a resourceUpdates, when not null, specifies a resource update batch that
12345 is to be committed and then released.
12346
12347 \note Do not assume that any state or resource bindings persist between
12348 passes.
12349
12350 \note A compute pass can record setComputePipeline(), setShaderResources(),
12351 and dispatch() calls, not graphics ones. General functionality, such as,
12352 debug markers and beginExternal() is available both in render and compute
12353 passes.
12354
12355 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
12356 is reported as supported.
12357
12358 \a flags is not currently used.
12359 */
12360void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates, BeginPassFlags flags)
12361{
12362 m_rhi->beginComputePass(this, resourceUpdates, flags);
12363}
12364
12365/*!
12366 Records ending the current compute pass.
12367
12368 \a resourceUpdates, when not null, specifies a resource update batch that
12369 is to be committed and then released.
12370 */
12371void QRhiCommandBuffer::endComputePass(QRhiResourceUpdateBatch *resourceUpdates)
12372{
12373 m_rhi->endComputePass(this, resourceUpdates);
12374}
12375
12376/*!
12377 Records setting a new compute pipeline \a ps.
12378
12379 \note This function must be called before recording setShaderResources() or
12380 dispatch() commands on the command buffer.
12381
12382 \note QRhi will optimize out unnecessary invocations within a pass, so
12383 therefore overoptimizing to avoid calls to this function is not necessary
12384 on the applications' side.
12385
12386 \note This function can only be called inside a compute pass, meaning
12387 between a beginComputePass() and endComputePass() call.
12388 */
12389void QRhiCommandBuffer::setComputePipeline(QRhiComputePipeline *ps)
12390{
12391 m_rhi->setComputePipeline(this, ps);
12392}
12393
12394/*!
12395 Records dispatching compute work items, with \a x, \a y, and \a z
12396 specifying the number of local workgroups in the corresponding dimension.
12397
12398 \note This function can only be called inside a compute pass, meaning
12399 between a beginComputePass() and endComputePass() call.
12400
12401 \note \a x, \a y, and \a z must fit the limits from the underlying graphics
12402 API implementation at run time. The maximum values are typically 65535.
12403
12404 \note Watch out for possible limits on the local workgroup size as well.
12405 This is specified in the shader, for example: \c{layout(local_size_x = 16,
12406 local_size_y = 16) in;}. For example, with OpenGL the minimum value mandated
12407 by the specification for the number of invocations in a single local work
12408 group (the product of \c local_size_x, \c local_size_y, and \c local_size_z)
12409 is 1024, while with OpenGL ES (3.1) the value may be as low as 128. This
12410 means that the example given above may be rejected by some OpenGL ES
12411 implementations as the number of invocations is 256.
12412 */
12413void QRhiCommandBuffer::dispatch(int x, int y, int z)
12414{
12415 m_rhi->dispatch(this, x, y, z);
12416}
12417
12418/*!
12419 Records an indirect compute dispatch.
12420
12421 The work group counts are read by the device from \a indirectBuffer at
12422 \a indirectBufferOffset, as a single QRhiDispatchIndirectCommand.
12423 \a indirectBuffer must have QRhiBuffer::IndirectBuffer usage and
12424 \a indirectBufferOffset must be 4-byte aligned.
12425
12426 Only one dispatch per call; no native multi-dispatch variant exists.
12427 Requires \l QRhi::DispatchIndirect.
12428
12429 \note Only valid inside a compute pass.
12430
12431 \since 6.13
12432 */
12433void QRhiCommandBuffer::dispatchIndirect(QRhiBuffer *indirectBuffer,
12434 quint32 indirectBufferOffset)
12435{
12436 Q_ASSERT(indirectBuffer);
12437 Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
12438 Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
12439 m_rhi->dispatchIndirect(this, indirectBuffer, indirectBufferOffset);
12440}
12441
12442/*!
12443 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
12444 QRhiVulkanCommandBufferNativeHandles. The returned value is \nullptr when
12445 exposing the underlying native resources is not supported by, or not
12446 applicable to, the backend.
12447
12448 \sa QRhiVulkanCommandBufferNativeHandles,
12449 QRhiMetalCommandBufferNativeHandles, beginExternal(), endExternal()
12450 */
12451const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
12452{
12453 return m_rhi->nativeHandles(this);
12454}
12455
12456/*!
12457 To be called when the application before the application is about to
12458 enqueue commands to the current pass' command buffer by calling graphics
12459 API functions directly.
12460
12461 \note This is only available when the intent was declared upfront in
12462 beginPass() or beginComputePass(). Therefore this function must only be
12463 called when the pass recording was started with specifying
12464 QRhiCommandBuffer::ExternalContent.
12465
12466 With Vulkan, Metal, or Direct3D 12 one can query the native command buffer
12467 or encoder objects via nativeHandles() and enqueue commands to them. With
12468 OpenGL or Direct3D 11 the (device) context can be retrieved from
12469 QRhi::nativeHandles(). However, this must never be done without ensuring
12470 the QRhiCommandBuffer's state stays up-to-date. Hence the requirement for
12471 wrapping any externally added command recording between beginExternal() and
12472 endExternal(). Conceptually this is the same as QPainter's
12473 \l{QPainter::beginNativePainting()}{beginNativePainting()} and
12474 \l{QPainter::endNativePainting()}{endNativePainting()} functions.
12475
12476 For OpenGL in particular, this function has an additional task: it makes
12477 sure the context is made current on the current thread.
12478
12479 \note Once beginExternal() is called, no other render pass specific
12480 functions (\c set* or \c draw*) must be called on the
12481 QRhiCommandBuffer until endExternal().
12482
12483 \warning Some backends may return a native command buffer object from
12484 QRhiCommandBuffer::nativeHandles() that is different from the primary one
12485 when inside a beginExternal() - endExternal() block. Therefore it is
12486 important to (re)query the native command buffer object after calling
12487 beginExternal(). In practical terms this means that with Vulkan for example
12488 the externally recorded Vulkan commands are placed onto a secondary command
12489 buffer (with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT).
12490 nativeHandles() returns this secondary command buffer when called between
12491 begin/endExternal.
12492
12493 \sa endExternal(), nativeHandles()
12494 */
12495void QRhiCommandBuffer::beginExternal()
12496{
12497 m_rhi->beginExternal(this);
12498}
12499
12500/*!
12501 To be called once the externally added commands are recorded to the command
12502 buffer or context.
12503
12504 \note All QRhiCommandBuffer state must be assumed as invalid after calling
12505 this function. Pipelines, vertex and index buffers, and other state must be
12506 set again if more draw calls are recorded after the external commands.
12507
12508 \sa beginExternal(), nativeHandles()
12509 */
12510void QRhiCommandBuffer::endExternal()
12511{
12512 m_rhi->endExternal(this);
12513}
12514
12515/*!
12516 \return the last available timestamp, in seconds, when
12517 \l QRhi::EnableTimestamps was enabled when creating the QRhi. The value
12518 indicates the elapsed time on the GPU during the last completed frame.
12519
12520 \note Do not expect results other than 0 when the QRhi::Timestamps feature
12521 is not reported as supported, or when QRhi::EnableTimestamps was not passed
12522 to QRhi::create(). There are exceptions to this, because with some graphics
12523 APIs (Metal) timings are available without having to perform extra
12524 operations (timestamp queries), but portable applications should always
12525 consciously opt-in to timestamp collection when they know it is needed, and
12526 call this function accordingly.
12527
12528 Care must be exercised with the interpretation of the value, as its
12529 precision and granularity is often not controlled by Qt, and depends on the
12530 underlying graphics API and its implementation. In particular, comparing
12531 the values between different graphics APIs and hardware is discouraged and
12532 may be meaningless.
12533
12534 The timing values will likely become available asynchronously. The returned
12535 value may therefore be 0 (e.g., for the first 1-2 frames) or the last known
12536 value referring to some previous frame. The value my also become 0 again
12537 under certain conditions, such as when resizing the window. It can be
12538 expected that the most up-to-date available value is retrieved in
12539 beginFrame() and becomes queriable via this function once beginFrame()
12540 returns.
12541
12542 \note Do not assume that the value refers to the previous
12543 (\c{currently_recorded - 1}) frame. It may refer to \c{currently_recorded -
12544 2} or \c{currently_recorded - 3} as well. The exact behavior may depend on
12545 the graphics API and its implementation.
12546
12547 Watch out for the consequences of GPU frequency scaling and GPU clock
12548 changes, depending on the platform. For example, on Windows the returned
12549 timing may vary in a quite wide range between frames with modern graphics
12550 cards, even when submitting frames with a similar, or the same workload.
12551 This is out of scope for Qt to control and solve, generally speaking.
12552 However, the D3D12 backend automatically calls
12553 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-setstablepowerstate}{ID3D12Device::SetStablePowerState()}
12554 whenever the environment variable \c QT_D3D_STABLE_POWER_STATE is set to a
12555 non-zero value. This can greatly stabilize the result. It can also have a
12556 non-insignificant effect on the CPU-side timings measured via QElapsedTimer
12557 for example, especially when offscreen frames are involved.
12558
12559 \note Do not and never ship applications to production with
12560 \c QT_D3D_STABLE_POWER_STATE set. See the Windows API documentation for details.
12561
12562 \sa QRhi::Timestamps, QRhi::EnableTimestamps
12563 */
12564double QRhiCommandBuffer::lastCompletedGpuTime()
12565{
12566 return m_rhi->lastCompletedGpuTime(this);
12567}
12568
12569/*!
12570 \return the value (typically an offset) \a v aligned to the uniform buffer
12571 alignment given by ubufAlignment().
12572 */
12573int QRhi::ubufAligned(int v) const
12574{
12575 const int byteAlign = ubufAlignment();
12576 return (v + byteAlign - 1) & ~(byteAlign - 1);
12577}
12578
12579/*!
12580 \return the number of mip levels for a given \a size.
12581 */
12582int QRhi::mipLevelsForSize(const QSize &size)
12583{
12584 return qFloor(std::log2(qMax(size.width(), size.height()))) + 1;
12585}
12586
12587/*!
12588 \return the texture image size for a given \a mipLevel, calculated based on
12589 the level 0 size given in \a baseLevelSize.
12590 */
12591QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)
12592{
12593 const int w = qMax(1, baseLevelSize.width() >> mipLevel);
12594 const int h = qMax(1, baseLevelSize.height() >> mipLevel);
12595 return QSize(w, h);
12596}
12597
12598/*!
12599 \return \c true if the underlying graphics API has the Y axis pointing up
12600 in framebuffers and images.
12601
12602 In practice this is \c true for OpenGL only.
12603 */
12604bool QRhi::isYUpInFramebuffer() const
12605{
12606 return d->isYUpInFramebuffer();
12607}
12608
12609/*!
12610 \return \c true if the underlying graphics API has the Y axis pointing up
12611 in its normalized device coordinate system.
12612
12613 In practice this is \c false for Vulkan only.
12614
12615 \note clipSpaceCorrMatrix() includes the corresponding adjustment (to make
12616 Y point up) in its returned matrix.
12617 */
12618bool QRhi::isYUpInNDC() const
12619{
12620 return d->isYUpInNDC();
12621}
12622
12623/*!
12624 \return \c true if the underlying graphics API uses depth range [0, 1] in
12625 clip space.
12626
12627 In practice this is \c false for OpenGL only, because OpenGL uses a
12628 post-projection depth range of [-1, 1]. (not to be confused with the
12629 NDC-to-window mapping controlled by glDepthRange(), which uses a range of
12630 [0, 1], unless overridden by the QRhiViewport) In some OpenGL versions
12631 glClipControl() could be used to change this, but the OpenGL backend of
12632 QRhi does not use that function as it is not available in OpenGL ES or
12633 OpenGL versions lower than 4.5.
12634
12635 \note clipSpaceCorrMatrix() includes the corresponding adjustment in its
12636 returned matrix. Therefore, many users of QRhi do not need to take any
12637 further measures apart from pre-multiplying their projection matrices with
12638 clipSpaceCorrMatrix(). However, some graphics techniques, such as, some
12639 types of shadow mapping, involve working with and outputting depth values
12640 in the shaders. These will need to query and take the value of this
12641 function into account as appropriate.
12642 */
12643bool QRhi::isClipDepthZeroToOne() const
12644{
12645 return d->isClipDepthZeroToOne();
12646}
12647
12648/*!
12649 \return a matrix that can be used to allow applications keep using
12650 OpenGL-targeted vertex data and perspective projection matrices (such as,
12651 the ones generated by QMatrix4x4::perspective()), regardless of the active
12652 QRhi backend.
12653
12654 In a typical renderer, once \c{this_matrix * mvp} is used instead of just
12655 \c mvp, vertex data with Y up and viewports with depth range 0 - 1 can be
12656 used without considering what backend (and so graphics API) is going to be
12657 used at run time. This way branching based on isYUpInNDC() and
12658 isClipDepthZeroToOne() can be avoided (although such logic may still become
12659 required when implementing certain advanced graphics techniques).
12660
12661 See
12662 \l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this
12663 page} for a discussion of the topic from Vulkan perspective.
12664 */
12665QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
12666{
12667 return d->clipSpaceCorrMatrix();
12668}
12669
12670/*!
12671 \return \c true if the specified texture \a format modified by \a flags is
12672 supported.
12673
12674 The query is supported both for uncompressed and compressed formats.
12675 */
12676bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
12677{
12678 return d->isTextureFormatSupported(format, flags);
12679}
12680
12681/*!
12682 \return \c true if the specified \a feature is supported
12683 */
12684bool QRhi::isFeatureSupported(QRhi::Feature feature) const
12685{
12686 return d->isFeatureSupported(feature);
12687}
12688
12689/*!
12690 \return the value for the specified resource \a limit.
12691
12692 The values are expected to be queried by the backends upon initialization,
12693 meaning calling this function is a light operation.
12694 */
12695int QRhi::resourceLimit(ResourceLimit limit) const
12696{
12697 return d->resourceLimit(limit);
12698}
12699
12700/*!
12701 \return a pointer to the backend-specific collection of native objects
12702 for the device, context, and similar concepts used by the backend.
12703
12704 Cast to QRhiVulkanNativeHandles, QRhiD3D11NativeHandles,
12705 QRhiD3D12NativeHandles, QRhiGles2NativeHandles, or QRhiMetalNativeHandles
12706 as appropriate.
12707
12708 \note No ownership is transferred, neither for the returned pointer nor for
12709 any native objects.
12710 */
12711const QRhiNativeHandles *QRhi::nativeHandles()
12712{
12713 return d->nativeHandles();
12714}
12715
12716/*!
12717 With OpenGL this makes the OpenGL context current on the current thread.
12718 The function has no effect with other backends.
12719
12720 Calling this function is relevant typically in Qt framework code, when one
12721 has to ensure external OpenGL code provided by the application can still
12722 run like it did before with direct usage of OpenGL, as long as the QRhi is
12723 using the OpenGL backend.
12724
12725 \return false when failed, similarly to QOpenGLContext::makeCurrent(). When
12726 the operation failed, isDeviceLost() can be called to determine if there
12727 was a loss of context situation. Such a check is equivalent to checking via
12728 QOpenGLContext::isValid().
12729
12730 \sa QOpenGLContext::makeCurrent(), QOpenGLContext::isValid()
12731 */
12732bool QRhi::makeThreadLocalNativeContextCurrent()
12733{
12734 return d->makeThreadLocalNativeContextCurrent();
12735}
12736
12737/*!
12738 With backends and graphics APIs where applicable, this function allows to
12739 provide additional arguments to the \b next submission of commands to the
12740 graphics command queue.
12741
12742 In particular, with Vulkan this allows passing in a list of Vulkan semaphore
12743 objects for \c vkQueueSubmit() to signal and wait on. \a params must then be
12744 a \l QRhiVulkanQueueSubmitParams. This becomes essential in certain advanced
12745 use cases, such as when performing native Vulkan calls that involve having
12746 to wait on and signal VkSemaphores that the application's custom Vulkan
12747 rendering or compute code manages. In addition, this also allows specifying
12748 additional semaphores to wait on in the next \c vkQueuePresentKHR().
12749
12750 \note This function affects the next queue submission only, which will
12751 happen in endFrame(), endOffscreenFrame(), or finish(). The enqueuing of
12752 present happens in endFrame().
12753
12754 With many other backends the implementation of this function is a no-op.
12755
12756 \since 6.9
12757 */
12758void QRhi::setQueueSubmitParams(QRhiNativeHandles *params)
12759{
12760 d->setQueueSubmitParams(params);
12761}
12762
12763/*!
12764 Attempts to release resources in the backend's caches. This can include both
12765 CPU and GPU resources. Only memory and resources that can be recreated
12766 automatically are in scope. As an example, if the backend's
12767 QRhiGraphicsPipeline implementation maintains a cache of shader compilation
12768 results, calling this function leads to emptying that cache, thus
12769 potentially freeing up memory and graphics resources.
12770
12771 Calling this function makes sense in resource constrained environments,
12772 where at a certain point there is a need to ensure minimal resource usage,
12773 at the expense of performance.
12774 */
12775void QRhi::releaseCachedResources()
12776{
12777 d->releaseCachedResources();
12778
12779 for (QRhiResourceUpdateBatch *u : d->resUpdPool) {
12780 if (u->d->poolIndex < 0)
12781 u->d->trimOpLists();
12782 }
12783}
12784
12785/*!
12786 \return true if the graphics device was lost.
12787
12788 The loss of the device is typically detected in beginFrame(), endFrame() or
12789 QRhiSwapChain::createOrResize(), depending on the backend and the underlying
12790 native APIs. The most common is endFrame() because that is where presenting
12791 happens. With some backends QRhiSwapChain::createOrResize() can also fail
12792 due to a device loss. Therefore this function is provided as a generic way
12793 to check if a device loss was detected by a previous operation.
12794
12795 When the device is lost, no further operations should be done via the QRhi.
12796 Rather, all QRhi resources should be released, followed by destroying the
12797 QRhi. A new QRhi can then be attempted to be created. If successful, all
12798 graphics resources must be reinitialized. If not, try again later,
12799 repeatedly.
12800
12801 While simple applications may decide to not care about device loss,
12802 on the commonly used desktop platforms a device loss can happen
12803 due to a variety of reasons, including physically disconnecting the
12804 graphics adapter, disabling the device or driver, uninstalling or upgrading
12805 the graphics driver, or due to errors that lead to a graphics device reset.
12806 Some of these can happen under perfectly normal circumstances as well, for
12807 example the upgrade of the graphics driver to a newer version is a common
12808 task that can happen at any time while a Qt application is running. Users
12809 may very well expect applications to be able to survive this, even when the
12810 application is actively using an API like OpenGL or Direct3D.
12811
12812 Qt's own frameworks built on top of QRhi, such as, Qt Quick, can be
12813 expected to handle and take appropriate measures when a device loss occurs.
12814 If the data for graphics resources, such as textures and buffers, are still
12815 available on the CPU side, such an event may not be noticeable on the
12816 application level at all since graphics resources can seamlessly be
12817 reinitialized then. However, applications and libraries working directly
12818 with QRhi are expected to be prepared to check and handle device loss
12819 situations themselves.
12820
12821 \note With OpenGL, applications may need to opt-in to context reset
12822 notifications by setting QSurfaceFormat::ResetNotification on the
12823 QOpenGLContext. This is typically done by enabling the flag in
12824 QRhiGles2InitParams::format. Keep in mind however that some systems may
12825 generate context resets situations even when this flag is not set.
12826 */
12827bool QRhi::isDeviceLost() const
12828{
12829 return d->isDeviceLost();
12830}
12831
12832/*!
12833 \return a binary data blob with data collected from the
12834 QRhiGraphicsPipeline and QRhiComputePipeline successfully created during
12835 the lifetime of this QRhi.
12836
12837 By saving and then, in subsequent runs of the same application, reloading
12838 the cache data, pipeline and shader creation times can potentially be
12839 reduced. What exactly the cache and its serialized version includes is not
12840 specified, is always specific to the backend used, and in some cases also
12841 dependent on the particular implementation of the graphics API.
12842
12843 When the PipelineCacheDataLoadSave is reported as unsupported, the returned
12844 QByteArray is empty.
12845
12846 When the EnablePipelineCacheDataSave flag was not specified when calling
12847 create(), the returned QByteArray may be empty, even when the
12848 PipelineCacheDataLoadSave feature is supported.
12849
12850 When the returned data is non-empty, it is always specific to the Qt
12851 version and QRhi backend. In addition, in some cases there is a strong
12852 dependency to the graphics device and the exact driver version used. QRhi
12853 takes care of adding the appropriate header and safeguards that ensure that
12854 the data can always be passed safely to setPipelineCacheData(), therefore
12855 attempting to load data from a run on another version of a driver will be
12856 handled safely and gracefully.
12857
12858 \note Calling releaseCachedResources() may, depending on the backend, clear
12859 the pipeline data collected. A subsequent call to this function may then
12860 not return any data.
12861
12862 See EnablePipelineCacheDataSave for further details about this feature.
12863
12864 \note Minimize the number of calls to this function. Retrieving the blob is
12865 not always a cheap operation, and therefore this function should only be
12866 called at a low frequency, ideally only once e.g. when closing the
12867 application.
12868
12869 \sa setPipelineCacheData(), create(), isFeatureSupported()
12870 */
12871QByteArray QRhi::pipelineCacheData()
12872{
12873 return d->pipelineCacheData();
12874}
12875
12876/*!
12877 Loads \a data into the pipeline cache, when applicable.
12878
12879 When the PipelineCacheDataLoadSave is reported as unsupported, the function
12880 is safe to call, but has no effect.
12881
12882 The blob returned by pipelineCacheData() is always specific to the Qt
12883 version, the QRhi backend, and, in some cases, also to the graphics device,
12884 and a given version of the graphics driver. QRhi takes care of adding the
12885 appropriate header and safeguards that ensure that the data can always be
12886 passed safely to this function. If there is a mismatch, e.g. because the
12887 driver has been upgraded to a newer version, or because the data was
12888 generated from a different QRhi backend, a warning is printed and \a data
12889 is safely ignored.
12890
12891 With Vulkan, this maps directly to VkPipelineCache. Calling this function
12892 creates a new Vulkan pipeline cache object, with its initial data sourced
12893 from \a data. The pipeline cache object is then used by all subsequently
12894 created QRhiGraphicsPipeline and QRhiComputePipeline objects, thus
12895 accelerating, potentially, the pipeline creation.
12896
12897 With other APIs there is no real pipeline cache, but they may provide a
12898 cache with bytecode from shader compilations (D3D) or program binaries
12899 (OpenGL). In applications that perform a lot of shader compilation from
12900 source at run time this can provide a significant boost in subsequent runs
12901 if the "pipeline cache" is pre-seeded from an earlier run using this
12902 function.
12903
12904 \note QRhi cannot give any guarantees that \a data has an effect on the
12905 pipeline and shader creation performance. With APIs like Vulkan, it is up
12906 to the driver to decide if \a data is used for some purpose, or if it is
12907 ignored.
12908
12909 See EnablePipelineCacheDataSave for further details about this feature.
12910
12911 \note This mechanism offered by QRhi is independent of the drivers' own
12912 internal caching mechanism, if any. This means that, depending on the
12913 graphics API and its implementation, the exact effects of retrieving and
12914 then reloading \a data are not predictable. Improved performance may not be
12915 visible at all in case other caching mechanisms outside of Qt's control are
12916 already active.
12917
12918 \note Minimize the number of calls to this function. Loading the blob is
12919 not always a cheap operation, and therefore this function should only be
12920 called at a low frequency, ideally only once e.g. when starting the
12921 application.
12922
12923 \warning Serialized pipeline cache data is assumed to be trusted content. Qt
12924 performs robust parsing of the header and metadata included in \a data,
12925 application developers are however advised to never pass in data from
12926 untrusted sources.
12927
12928 \sa pipelineCacheData(), isFeatureSupported()
12929 */
12930void QRhi::setPipelineCacheData(const QByteArray &data)
12931{
12932 d->setPipelineCacheData(data);
12933}
12934
12935/*!
12936 \struct QRhiStats
12937 \inmodule QtGuiPrivate
12938 \inheaderfile rhi/qrhi.h
12939 \since 6.6
12940
12941 \brief Statistics provided from the underlying memory allocator.
12942
12943 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
12944 for details.
12945 */
12946
12947/*!
12948 \variable QRhiStats::totalPipelineCreationTime
12949
12950 The total time in milliseconds spent in graphics and compute pipeline
12951 creation, which usually involves shader compilation or cache lookups, and
12952 potentially expensive processing.
12953
12954 \note The value should not be compared between different backends since the
12955 concept of "pipelines" and what exactly happens under the hood during, for
12956 instance, a call to QRhiGraphicsPipeline::create(), differ greatly between
12957 graphics APIs and their implementations.
12958
12959 \sa QRhi::statistics()
12960*/
12961
12962/*!
12963 \variable QRhiStats::blockCount
12964
12965 Statistic reported from the Vulkan or D3D12 memory allocator.
12966
12967 \sa QRhi::statistics()
12968*/
12969
12970/*!
12971 \variable QRhiStats::allocCount
12972
12973 Statistic reported from the Vulkan or D3D12 memory allocator.
12974
12975 \sa QRhi::statistics()
12976*/
12977
12978/*!
12979 \variable QRhiStats::usedBytes
12980
12981 Statistic reported from the Vulkan or D3D12 memory allocator.
12982
12983 \sa QRhi::statistics()
12984*/
12985
12986/*!
12987 \variable QRhiStats::unusedBytes
12988
12989 Statistic reported from the Vulkan or D3D12 memory allocator.
12990
12991 \sa QRhi::statistics()
12992*/
12993
12994/*!
12995 \variable QRhiStats::totalUsageBytes
12996
12997 Valid only with D3D12 currently. Matches IDXGIAdapter3::QueryVideoMemoryInfo().
12998
12999 \sa QRhi::statistics()
13000*/
13001
13002#ifndef QT_NO_DEBUG_STREAM
13003QDebug operator<<(QDebug dbg, const QRhiStats &info)
13004{
13005 QDebugStateSaver saver(dbg);
13006 dbg.nospace() << "QRhiStats("
13007 << "totalPipelineCreationTime=" << info.totalPipelineCreationTime
13008 << " blockCount=" << info.blockCount
13009 << " allocCount=" << info.allocCount
13010 << " usedBytes=" << info.usedBytes
13011 << " unusedBytes=" << info.unusedBytes
13012 << " totalUsageBytes=" << info.totalUsageBytes
13013 << ')';
13014 return dbg;
13015}
13016#endif
13017
13018/*!
13019 Gathers and returns statistics about the timings and allocations of
13020 graphics resources.
13021
13022 Data about memory allocations is only available with some backends, where
13023 such operations are under Qt's control. With graphics APIs where there is
13024 no lower level control over resource memory allocations, this will never be
13025 supported and all relevant fields in the results are 0.
13026
13027 With Vulkan in particular, the values are valid always, and are queried
13028 from the underlying memory allocator library. This gives an insight into
13029 the memory requirements of the active buffers and textures.
13030
13031 The same is true for Direct 3D 12. In addition to the memory allocator
13032 library's statistics, here the result also includes a \c totalUsageBytes
13033 field which reports the total size including additional resources that are
13034 not under the memory allocator library's control (swapchain buffers,
13035 descriptor heaps, etc.), as reported by DXGI.
13036
13037 The values correspond to all types of memory used, combined. (i.e. video +
13038 system in case of a discreet GPU)
13039
13040 Additional data, such as the total time in milliseconds spent in graphics
13041 and compute pipeline creation (which usually involves shader compilation or
13042 cache lookups, and potentially expensive processing) is available with most
13043 backends.
13044
13045 \note The elapsed times for operations such as pipeline creation may be
13046 affected by various factors. The results should not be compared between
13047 different backends since the concept of "pipelines" and what exactly
13048 happens under the hood during, for instance, a call to
13049 QRhiGraphicsPipeline::create(), differ greatly between graphics APIs and
13050 their implementations.
13051
13052 \note Additionally, many drivers will likely employ various caching
13053 strategies for shaders, programs, pipelines. (independently of Qt's own
13054 similar facilities, such as setPipelineCacheData() or the OpenGL-specific
13055 program binary disk cache). Because such internal behavior is transparent
13056 to the API client, Qt and QRhi have no knowledge or control over the exact
13057 caching strategy, persistency, invalidation of the cached data, etc. When
13058 reading timings, such as the time spent on pipeline creation, the potential
13059 presence and unspecified behavior of driver-level caching mechanisms should
13060 be kept in mind.
13061 */
13062QRhiStats QRhi::statistics() const
13063{
13064 return d->statistics();
13065}
13066
13067/*!
13068 \return a new graphics pipeline resource.
13069
13070 \sa QRhiResource::destroy()
13071 */
13072QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
13073{
13074 return d->createGraphicsPipeline();
13075}
13076
13077/*!
13078 \return a new compute pipeline resource.
13079
13080 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
13081 is reported as supported.
13082
13083 \sa QRhiResource::destroy()
13084 */
13085QRhiComputePipeline *QRhi::newComputePipeline()
13086{
13087 return d->createComputePipeline();
13088}
13089
13090/*!
13091 \return a new shader resource binding collection resource.
13092
13093 \sa QRhiResource::destroy()
13094 */
13095QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
13096{
13097 return d->createShaderResourceBindings();
13098}
13099
13100/*!
13101 \return a new buffer with the specified \a type, \a usage, and \a size.
13102
13103 \note Some \a usage and \a type combinations may not be supported by all
13104 backends. See \l{QRhiBuffer::UsageFlag}{UsageFlags} and
13105 \l{QRhi::NonDynamicUniformBuffers}{the feature flags}.
13106
13107 \note Backends may choose to allocate buffers bigger than \a size. This is
13108 done transparently to applications, so there are no special restrictions on
13109 the value of \a size. QRhiBuffer::size() will always report back the value
13110 that was requested in \a size.
13111
13112 \sa QRhiResource::destroy()
13113 */
13114QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type,
13115 QRhiBuffer::UsageFlags usage,
13116 quint32 size)
13117{
13118 return d->createBuffer(type, usage, size);
13119}
13120
13121/*!
13122 \return a new renderbuffer with the specified \a type, \a pixelSize, \a
13123 sampleCount, and \a flags.
13124
13125 When \a backingFormatHint is set to a texture format other than
13126 QRhiTexture::UnknownFormat, it may be used by the backend to decide what
13127 format to use for the storage backing the renderbuffer.
13128
13129 \note \a backingFormatHint becomes relevant typically when multisampling
13130 and floating point texture formats are involved: rendering into a
13131 multisample QRhiRenderBuffer and then resolving into a non-RGBA8
13132 QRhiTexture implies (with some graphics APIs) that the storage backing the
13133 QRhiRenderBuffer uses the matching non-RGBA8 format. That means that
13134 passing a format like QRhiTexture::RGBA32F is important, because backends
13135 will typically opt for QRhiTexture::RGBA8 by default, which would then
13136 break later on due to attempting to set up RGBA8->RGBA32F multisample
13137 resolve in the color attachment(s) of the QRhiTextureRenderTarget.
13138
13139 \sa QRhiResource::destroy()
13140 */
13141QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type,
13142 const QSize &pixelSize,
13143 int sampleCount,
13144 QRhiRenderBuffer::Flags flags,
13145 QRhiTexture::Format backingFormatHint)
13146{
13147 return d->createRenderBuffer(type, pixelSize, sampleCount, flags, backingFormatHint);
13148}
13149
13150/*!
13151 \return a new 1D or 2D texture with the specified \a format, \a pixelSize, \a
13152 sampleCount, and \a flags.
13153
13154 A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This
13155 function will implicitly set this flag if the \a pixelSize height is 0.
13156
13157 \note \a format specifies the requested internal and external format,
13158 meaning the data to be uploaded to the texture will need to be in a
13159 compatible format, while the native texture may (but is not guaranteed to,
13160 in case of OpenGL at least) use this format internally.
13161
13162 \note 1D textures are only functional when the OneDimensionalTextures feature is
13163 reported as supported at run time. Further, mipmaps on 1D textures are only
13164 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
13165
13166 \sa QRhiResource::destroy()
13167 */
13168QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
13169 const QSize &pixelSize,
13170 int sampleCount,
13171 QRhiTexture::Flags flags)
13172{
13173 if (pixelSize.height() == 0)
13174 flags |= QRhiTexture::OneDimensional;
13175
13176 return d->createTexture(format, pixelSize, 1, 0, sampleCount, flags);
13177}
13178
13179/*!
13180 \return a new 1D, 2D or 3D texture with the specified \a format, \a width, \a
13181 height, \a depth, \a sampleCount, and \a flags.
13182
13183 This overload is suitable for 3D textures because it allows specifying \a
13184 depth. A 3D texture must have QRhiTexture::ThreeDimensional set in \a
13185 flags, but using this overload that can be omitted because the flag is set
13186 implicitly whenever \a depth is greater than 0. For 1D, 2D and cube textures \a
13187 depth should be set to 0.
13188
13189 A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This overload
13190 will implicitly set this flag if both \a height and \a depth are 0.
13191
13192 \note 3D textures are only functional when the ThreeDimensionalTextures
13193 feature is reported as supported at run time.
13194
13195 \note 1D textures are only functional when the OneDimensionalTextures feature is
13196 reported as supported at run time. Further, mipmaps on 1D textures are only
13197 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
13198
13199 \overload
13200 */
13201QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
13202 int width, int height, int depth,
13203 int sampleCount,
13204 QRhiTexture::Flags flags)
13205{
13206 if (depth > 0)
13207 flags |= QRhiTexture::ThreeDimensional;
13208
13209 if (height == 0 && depth == 0)
13210 flags |= QRhiTexture::OneDimensional;
13211
13212 return d->createTexture(format, QSize(width, height), depth, 0, sampleCount, flags);
13213}
13214
13215/*!
13216 \return a new 1D or 2D texture array with the specified \a format, \a arraySize,
13217 \a pixelSize, \a sampleCount, and \a flags.
13218
13219 This function implicitly sets QRhiTexture::TextureArray in \a flags.
13220
13221 A 1D texture array must have QRhiTexture::OneDimensional set in \a flags. This
13222 function will implicitly set this flag if the \a pixelSize height is 0.
13223
13224 \note Do not confuse texture arrays with arrays of textures. A QRhiTexture
13225 created by this function is usable with 1D or 2D array samplers in the shader, for
13226 example: \c{layout(binding = 1) uniform sampler2DArray texArr;}. Arrays of
13227 textures refers to a list of textures that are exposed to the shader via
13228 QRhiShaderResourceBinding::sampledTextures() and a count > 1, and declared
13229 in the shader for example like this: \c{layout(binding = 1) uniform
13230 sampler2D textures[4];}
13231
13232 \note This is only functional when the TextureArrays feature is reported as
13233 supported at run time.
13234
13235 \note 1D textures are only functional when the OneDimensionalTextures feature is
13236 reported as supported at run time. Further, mipmaps on 1D textures are only
13237 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
13238
13239
13240 \sa newTexture()
13241 */
13242QRhiTexture *QRhi::newTextureArray(QRhiTexture::Format format,
13243 int arraySize,
13244 const QSize &pixelSize,
13245 int sampleCount,
13246 QRhiTexture::Flags flags)
13247{
13248 flags |= QRhiTexture::TextureArray;
13249
13250 if (pixelSize.height() == 0)
13251 flags |= QRhiTexture::OneDimensional;
13252
13253 return d->createTexture(format, pixelSize, 1, arraySize, sampleCount, flags);
13254}
13255
13256/*!
13257 \return a new sampler with the specified magnification filter \a magFilter,
13258 minification filter \a minFilter, mipmapping mode \a mipmapMode, and the
13259 addressing (wrap) modes \a addressU, \a addressV, and \a addressW.
13260
13261 \note Setting \a mipmapMode to a value other than \c None implies that
13262 images for all relevant mip levels will be provided either via
13263 \l{QRhiResourceUpdateBatch::uploadTexture()}{texture uploads} or by calling
13264 \l{QRhiResourceUpdateBatch::generateMips()}{generateMips()} on the texture
13265 that is used with this sampler. Attempting to use the sampler with a
13266 texture that has no data for all relevant mip levels will lead to rendering
13267 errors, with the exact behavior dependent on the underlying graphics API.
13268
13269 \sa QRhiResource::destroy()
13270 */
13271QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter,
13272 QRhiSampler::Filter minFilter,
13273 QRhiSampler::Filter mipmapMode,
13274 QRhiSampler::AddressMode addressU,
13275 QRhiSampler::AddressMode addressV,
13276 QRhiSampler::AddressMode addressW)
13277{
13278 return d->createSampler(magFilter, minFilter, mipmapMode, addressU, addressV, addressW);
13279}
13280
13281/*!
13282 \return a new shading rate map object.
13283
13284 \since 6.9
13285 */
13286QRhiShadingRateMap *QRhi::newShadingRateMap()
13287{
13288 return d->createShadingRateMap();
13289}
13290
13291/*!
13292 \return a new indirect command buffer that holds commands of the specified
13293 \a type, with room for \a maxCommandCount of them.
13294
13295 \a maxCommandCount cannot be 0, otherwise create() fails. It is the upper
13296 bound for both ways of providing commands: recording them with
13297 QRhiIndirectCommandBuffer::draw() or
13298 QRhiIndirectCommandBuffer::drawIndexed(), and generating them on the GPU
13299 and calling QRhiCommandBuffer::buildIndirect(). Backends allocate their
13300 native objects, and the QRhiBuffer holding the recorded commands, based on
13301 it, which is why it is fixed up front instead of growing on demand.
13302
13303 \sa QRhiIndirectCommandBuffer::setMaxCommandCount(), QRhiIndirectCommandBuffer
13304
13305 \since 6.13
13306 */
13307QRhiIndirectCommandBuffer *QRhi::newIndirectCommandBuffer(QRhiIndirectCommandBuffer::Type type,
13308 quint32 maxCommandCount)
13309{
13310 return d->createIndirectCommandBuffer(type, maxCommandCount);
13311}
13312
13313/*!
13314 \return a new texture render target with color and depth/stencil
13315 attachments given in \a desc, and with the specified \a flags.
13316
13317 \sa QRhiResource::destroy()
13318 */
13319
13320QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
13321 QRhiTextureRenderTarget::Flags flags)
13322{
13323 return d->createTextureRenderTarget(desc, flags);
13324}
13325
13326/*!
13327 \return a new swapchain.
13328
13329 \sa QRhiResource::destroy(), QRhiSwapChain::createOrResize()
13330 */
13331QRhiSwapChain *QRhi::newSwapChain()
13332{
13333 return d->createSwapChain();
13334}
13335
13336/*!
13337 Starts a new frame targeting the next available buffer of \a swapChain.
13338
13339 A frame consists of resource updates and one or more render and compute
13340 passes.
13341
13342 \a flags can indicate certain special cases.
13343
13344 The high level pattern of rendering into a QWindow using a swapchain:
13345
13346 \list
13347
13348 \li Create a swapchain.
13349
13350 \li Call QRhiSwapChain::createOrResize() whenever the surface size is
13351 different than before.
13352
13353 \li Call QRhiSwapChain::destroy() on
13354 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed.
13355
13356 \li Then on every frame:
13357 \badcode
13358 beginFrame(sc);
13359 updates = nextResourceUpdateBatch();
13360 updates->...
13361 QRhiCommandBuffer *cb = sc->currentFrameCommandBuffer();
13362 cb->beginPass(sc->currentFrameRenderTarget(), colorClear, dsClear, updates);
13363 ...
13364 cb->endPass();
13365 ... // more passes as necessary
13366 endFrame(sc);
13367 \endcode
13368
13369 \endlist
13370
13371 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
13372 value on failure. Some of these should be treated as soft, "try again
13373 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
13374 the swapchain is to be resized or updated by calling
13375 QRhiSwapChain::createOrResize(). The application should then attempt to
13376 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
13377 lost but this may also be recoverable by releasing all resources, including
13378 the QRhi itself, and then recreating all resources. See isDeviceLost() for
13379 further discussion.
13380
13381 \sa endFrame(), beginOffscreenFrame(), isDeviceLost()
13382 */
13383QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
13384{
13385 if (d->inFrame)
13386 qWarning("Attempted to call beginFrame() within a still active frame; ignored");
13387
13388 qCDebug(QRHI_LOG_RUB) << "[rub] new frame";
13389
13390 QRhi::FrameOpResult r = !d->inFrame ? d->beginFrame(swapChain, flags) : FrameOpSuccess;
13391 if (r == FrameOpSuccess)
13392 d->inFrame = true;
13393
13394 return r;
13395}
13396
13397/*!
13398 Ends, commits, and presents a frame that was started in the last
13399 beginFrame() on \a swapChain.
13400
13401 Double (or triple) buffering is managed internally by the QRhiSwapChain and
13402 QRhi.
13403
13404 \a flags can optionally be used to change the behavior in certain ways.
13405 Passing QRhi::SkipPresent skips queuing the Present command or calling
13406 swapBuffers.
13407
13408 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
13409 value on failure. Some of these should be treated as soft, "try again
13410 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
13411 the swapchain is to be resized or updated by calling
13412 QRhiSwapChain::createOrResize(). The application should then attempt to
13413 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
13414 lost but this may also be recoverable by releasing all resources, including
13415 the QRhi itself, and then recreating all resources. See isDeviceLost() for
13416 further discussion.
13417
13418 \sa beginFrame(), isDeviceLost()
13419 */
13420QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags)
13421{
13422 const bool wasInFrame = d->inFrame;
13423 if (!wasInFrame)
13424 qWarning("Attempted to call endFrame() without an active frame; ignored");
13425
13426 QRhi::FrameOpResult r = wasInFrame ? d->endFrame(swapChain, flags) : FrameOpSuccess;
13427 d->inFrame = false;
13428 // deleteLater is a high level QRhi concept the backends know
13429 // nothing about - handle it here.
13430 qDeleteAll(d->pendingDeleteResources);
13431 d->pendingDeleteResources.clear();
13432
13433 if (wasInFrame && qrhiDebugHooks.frameEnd) {
13434 QRhiCommandBuffer *cb = (r == FrameOpSuccess && swapChain)
13435 ? swapChain->currentFrameCommandBuffer() : nullptr;
13436 qrhiDebugHooks.frameEnd(d, swapChain, cb);
13437 }
13438
13439 return r;
13440}
13441
13442/*!
13443 \return true when there is an active frame, meaning there was a
13444 beginFrame() (or beginOffscreenFrame()) with no corresponding endFrame()
13445 (or endOffscreenFrame()) yet.
13446
13447 \sa currentFrameSlot(), beginFrame(), endFrame()
13448 */
13449bool QRhi::isRecordingFrame() const
13450{
13451 return d->inFrame;
13452}
13453
13454/*!
13455 \return the current frame slot index while recording a frame. Unspecified
13456 when called outside an active frame (that is, when isRecordingFrame() is \c
13457 false).
13458
13459 With backends like Vulkan or Metal, it is the responsibility of the QRhi
13460 backend to block whenever starting a new frame and finding the CPU is
13461 already \c{FramesInFlight - 1} frames ahead of the GPU (because the command
13462 buffer submitted in frame no. \c{current} - \c{FramesInFlight} has not yet
13463 completed).
13464
13465 Resources that tend to change between frames (such as, the native buffer
13466 object backing a QRhiBuffer with type QRhiBuffer::Dynamic) exist in
13467 multiple versions, so that each frame, that can be submitted while a
13468 previous one is still being processed, works with its own copy, thus
13469 avoiding the need to stall the pipeline when preparing the frame. (The
13470 contents of a resource that may still be in use in the GPU should not be
13471 touched, but simply always waiting for the previous frame to finish would
13472 reduce GPU utilization and ultimately, performance and efficiency.)
13473
13474 Conceptually this is somewhat similar to copy-on-write schemes used by some
13475 C++ containers and other types. It may also be similar to what an OpenGL or
13476 Direct 3D 11 implementation performs internally for certain type of objects.
13477
13478 In practice, such double (or triple) buffering resources is realized in
13479 the Vulkan, Metal, and similar QRhi backends by having a fixed number of
13480 native resource (such as, VkBuffer) \c slots behind a QRhiResource. That
13481 can then be indexed by a frame slot index running 0, 1, ..,
13482 FramesInFlight-1, and then wrapping around.
13483
13484 All this is managed transparently to the users of QRhi. However,
13485 applications that integrate rendering done directly with the graphics API
13486 may want to perform a similar double or triple buffering of their own
13487 graphics resources. That is then most easily achieved by knowing the values
13488 of the maximum number of in-flight frames (retrievable via resourceLimit())
13489 and the current frame (slot) index (returned by this function).
13490
13491 \sa isRecordingFrame(), beginFrame(), endFrame()
13492 */
13493int QRhi::currentFrameSlot() const
13494{
13495 return d->currentFrameSlot;
13496}
13497
13498/*!
13499 Starts a new offscreen frame. Provides a command buffer suitable for
13500 recording rendering commands in \a cb. \a flags is used to indicate
13501 certain special cases, just like with beginFrame().
13502
13503 \note The QRhiCommandBuffer stored to *cb is not owned by the caller.
13504
13505 Rendering without a swapchain is possible as well. The typical use case is
13506 to use it in completely offscreen applications, e.g. to generate image
13507 sequences by rendering and reading back without ever showing a window.
13508
13509 Usage in on-screen applications (so beginFrame, endFrame,
13510 beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) is possible too.
13511
13512 When a \l{QRhiResourceUpdateBatch::readBackTexture()}{texture} or
13513 \l{QRhiResourceUpdateBatch::readBackBuffer()}{buffer} readback was
13514 scheduled, offscreen frames do not let the CPU potentially generate another
13515 frame while the GPU is still processing the previous one. This has the side
13516 effect that if readbacks are scheduled, the results are guaranteed to be
13517 available once endOffscreenFrame() returns. That is not the case with frames
13518 targeting a swapchain: there the GPU is potentially better utilized, but
13519 working with readback operations needs more care from the application
13520 because endFrame(), unlike endOffscreenFrame(), does not guarantee that the
13521 results from the readback are available at that point.
13522
13523 The skeleton of rendering a frame without a swapchain and then reading the
13524 frame contents back could look like the following:
13525
13526 \code
13527 QRhiReadbackResult rbResult;
13528 QRhiCommandBuffer *cb;
13529 rhi->beginOffscreenFrame(&cb);
13530 cb->beginPass(rt, colorClear, dsClear);
13531 // ...
13532 u = nextResourceUpdateBatch();
13533 u->readBackTexture(rb, &rbResult);
13534 cb->endPass(u);
13535 rhi->endOffscreenFrame();
13536 // image data available in rbResult
13537 \endcode
13538
13539 \sa endOffscreenFrame(), beginFrame()
13540 */
13541QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags)
13542{
13543 const bool wasInFrame = d->inFrame;
13544 if (wasInFrame)
13545 qWarning("Attempted to call beginOffscreenFrame() within a still active frame; ignored");
13546
13547 qCDebug(QRHI_LOG_RUB) << "[rub] new offscreen frame";
13548
13549 QRhi::FrameOpResult r = !wasInFrame ? d->beginOffscreenFrame(cb, flags) : FrameOpSuccess;
13550 if (r == FrameOpSuccess) {
13551 d->inFrame = true;
13552 if (!wasInFrame)
13553 d->currentOffscreenCb = *cb;
13554 }
13555
13556 return r;
13557}
13558
13559/*!
13560 Ends, submits, and potentially waits for the offscreen frame.
13561
13562 Unlike endFrame(), this function will block and wait for completion of the
13563 GPU-side work when there are active buffer or texture readbacks.
13564
13565 \a flags is not currently used.
13566
13567 \sa beginOffscreenFrame()
13568 */
13569QRhi::FrameOpResult QRhi::endOffscreenFrame(EndFrameFlags flags)
13570{
13571 const bool wasInFrame = d->inFrame;
13572 if (!wasInFrame)
13573 qWarning("Attempted to call endOffscreenFrame() without an active frame; ignored");
13574
13575 QRhi::FrameOpResult r = wasInFrame ? d->endOffscreenFrame(flags) : FrameOpSuccess;
13576 d->inFrame = false;
13577 qDeleteAll(d->pendingDeleteResources);
13578 d->pendingDeleteResources.clear();
13579
13580 if (wasInFrame && qrhiDebugHooks.frameEnd) {
13581 QRhiCommandBuffer *cb = r == FrameOpSuccess ? d->currentOffscreenCb : nullptr;
13582 qrhiDebugHooks.frameEnd(d, nullptr, cb);
13583 }
13584 d->currentOffscreenCb = nullptr;
13585
13586 return r;
13587}
13588
13589/*!
13590 Waits for any work on the graphics queue (where applicable) to complete,
13591 then executes all deferred operations, like completing readbacks and
13592 resource releases. Can be called inside and outside of a frame, but not
13593 inside a pass. Inside a frame it implies submitting any work on the
13594 command buffer.
13595
13596 \note Avoid this function. One case where it may be needed is when the
13597 results of an enqueued readback in a swapchain-based frame are needed at a
13598 fixed given point and so waiting for the results is desired.
13599 */
13600QRhi::FrameOpResult QRhi::finish()
13601{
13602 return d->finish();
13603}
13604
13605/*!
13606 \return the list of supported sample counts.
13607
13608 A typical example would be (1, 2, 4, 8).
13609
13610 With some backend this list of supported values is fixed in advance, while
13611 with some others the (physical) device properties indicate what is
13612 supported at run time.
13613
13614 \sa QRhiRenderBuffer::setSampleCount(), QRhiTexture::setSampleCount(),
13615 QRhiGraphicsPipeline::setSampleCount(), QRhiSwapChain::setSampleCount()
13616 */
13617QList<int> QRhi::supportedSampleCounts() const
13618{
13619 return d->supportedSampleCounts();
13620}
13621
13622/*!
13623 \return the minimum uniform buffer offset alignment in bytes. This is
13624 typically 256.
13625
13626 Attempting to bind a uniform buffer region with an offset not aligned to
13627 this value will lead to failures depending on the backend and the
13628 underlying graphics API.
13629
13630 \sa ubufAligned()
13631 */
13632int QRhi::ubufAlignment() const
13633{
13634 return d->ubufAlignment();
13635}
13636
13637/*!
13638 \return The list of supported variable shading rates for the specified \a sampleCount.
13639
13640 1x1 is always supported.
13641
13642 \since 6.9
13643 */
13644QList<QSize> QRhi::supportedShadingRates(int sampleCount) const
13645{
13646 return d->supportedShadingRates(sampleCount);
13647}
13648
13649Q_CONSTINIT static QBasicAtomicInteger<QRhiGlobalObjectIdGenerator::Type> counter = Q_BASIC_ATOMIC_INITIALIZER(0);
13650
13651QRhiGlobalObjectIdGenerator::Type QRhiGlobalObjectIdGenerator::newId()
13652{
13653 return counter.fetchAndAddRelaxed(1) + 1;
13654}
13655
13657{
13658 return m_buffers.isEmpty() && m_textures.isEmpty();
13659}
13660
13662{
13663 m_buffers.clear();
13664 m_textures.clear();
13665}
13666
13672
13673void QRhiPassResourceTracker::registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
13674 const UsageState &state)
13675{
13676 auto it = m_buffers.find(buf);
13677 if (it != m_buffers.end()) {
13678 Buffer &b = it->second;
13679 if (Q_UNLIKELY(b.access != *access)) {
13680 const QByteArray name = buf->name();
13681 qWarning("Buffer %p (%s) used with different accesses within the same pass, this is not allowed.",
13682 buf, name.constData());
13683 return;
13684 }
13685 if (b.stage != *stage) {
13686 b.stage = earlierStage(b.stage, *stage);
13687 *stage = b.stage;
13688 }
13689 return;
13690 }
13691
13692 Buffer b;
13693 b.slot = slot;
13694 b.access = *access;
13695 b.stage = *stage;
13696 b.stateAtPassBegin = state; // first use -> initial state
13697 m_buffers.append(buf, b);
13698}
13699
13705
13712
13714 const UsageState &state)
13715{
13716 auto it = m_textures.find(tex);
13717 if (it != m_textures.end()) {
13718 Texture &t = it->second;
13719 if (t.access != *access) {
13720 // Different subresources of a texture may be used for both load
13721 // and store in the same pass. (think reading from one mip level
13722 // and writing to another one in a compute shader) This we can
13723 // handle by treating the entire resource as read-write.
13724 if (Q_LIKELY(isImageLoadStore(t.access) && isImageLoadStore(*access))) {
13726 *access = t.access;
13727 } else {
13728 const QByteArray name = tex->name();
13729 qWarning("Texture %p (%s) used with different accesses within the same pass, this is not allowed.",
13730 tex, name.constData());
13731 }
13732 }
13733 if (t.stage != *stage) {
13734 t.stage = earlierStage(t.stage, *stage);
13735 *stage = t.stage;
13736 }
13737 return;
13738 }
13739
13740 Texture t;
13741 t.access = *access;
13742 t.stage = *stage;
13743 t.stateAtPassBegin = state; // first use -> initial state
13744 m_textures.append(tex, t);
13745}
13746
13747QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
13748{
13749 // pick the earlier stage (as this is going to be dstAccessMask)
13750 if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
13752 if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
13754 if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
13756 if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
13758 if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
13760 if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
13762
13763 Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::BufVertexStage);
13764}
13765
13766QRhiPassResourceTracker::TextureStage QRhiPassResourceTracker::toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
13767{
13768 // pick the earlier stage (as this is going to be dstAccessMask)
13769 if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
13771 if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
13773 if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
13775 if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
13777 if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
13779 if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
13781
13782 Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::TexVertexStage);
13783}
13784
13785QSize QRhiImplementation::clampedSubResourceUploadSize(QSize size, QPoint dstPos, int level, QSize textureSizeAtLevelZero, bool warn)
13786{
13787 const QSize subResSize = q->sizeForMipLevel(level, textureSizeAtLevelZero);
13788 const bool outOfBoundsHoriz = dstPos.x() + size.width() > subResSize.width();
13789 const bool outOfBoundsVert = dstPos.y() + size.height() > subResSize.height();
13790 if (Q_UNLIKELY(outOfBoundsHoriz || outOfBoundsVert)) {
13791 if (warn) {
13792 qWarning("Invalid texture upload issued; size %dx%d dst.position %d,%d dst.subresource size %dx%d; size will be clamped",
13793 size.width(), size.height(), dstPos.x(), dstPos.y(), subResSize.width(), subResSize.height());
13794 }
13795 if (outOfBoundsHoriz)
13796 size.setWidth(subResSize.width() - dstPos.x());
13797 if (outOfBoundsVert)
13798 size.setHeight(subResSize.height() - dstPos.y());
13799 }
13800 return size;
13801}
13802
13803// Clamps size so that reading the image with a source row stride of bpl does
13804// not go past dataSize bytes. bpl may be 0, meaning the data is tightly packed.
13805// Returns a size with a height of 0 when not even a single row can be
13806// satisfied, in which case the caller is expected to skip the copy.
13807QSize QRhiImplementation::clampedSubResourceUploadSizeForSourceData(QSize size, quint32 bpl,
13808 quint32 bytesPerPixel,
13809 qsizetype dataSize, bool warn)
13810{
13811 if (size.isEmpty() || !bytesPerPixel)
13812 return size;
13813
13814 const quint64 rowBytes = quint64(bytesPerPixel) * quint64(size.width());
13815 if (!bpl)
13816 bpl = quint32(qMin(rowBytes, quint64(std::numeric_limits<quint32>::max())));
13817
13818 if (quint64(bpl) < rowBytes) {
13819 if (warn) {
13820 qWarning("Invalid texture upload issued; source row stride %u is smaller than the %llu "
13821 "bytes a row of %d pixels needs; upload will be skipped",
13822 bpl, rowBytes, size.width());
13823 }
13824 return QSize(size.width(), 0);
13825 }
13826
13827 // Row y is read from y * bpl and needs rowBytes bytes, so the last row ends
13828 // at (height - 1) * bpl + rowBytes.
13829 const quint64 needed = quint64(bpl) * quint64(size.height() - 1) + rowBytes;
13830 if (quint64(dataSize) >= needed)
13831 return size;
13832
13833 int rows = 0;
13834 if (quint64(dataSize) >= rowBytes)
13835 rows = int((quint64(dataSize) - rowBytes) / quint64(bpl)) + 1;
13836
13837 if (warn) {
13838 qWarning("Invalid texture upload issued; %lld bytes of data cannot back a %dx%d upload with "
13839 "source row stride %u (needs %llu bytes); height will be clamped to %d",
13840 qint64(dataSize), size.width(), size.height(), bpl, needed, rows);
13841 }
13842
13843 return QSize(size.width(), rows);
13844}
13845
13846QT_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:9339
QRhiBufferBackedIndirectCommandBuffer(QRhiImplementation *rhi, Type type, quint32 maxCommandCount)
\variable QRhiIndirectCommandBufferBuildInfo::topology
Definition qrhi.cpp:9249
void enqueueUpload(QRhiResourceUpdateBatch *u)
Definition qrhi.cpp:9303
void build(const QRhiIndirectCommandBufferBuildInfo &info)
Definition qrhi.cpp:9326
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
Definition qrhi.cpp:9261
bool create() override
Creates the corresponding native objects.
Definition qrhi.cpp:9284
bool isEmpty() const
Definition qrhi.cpp:13656
void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage, const UsageState &state)
Definition qrhi.cpp:13673
void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage, const UsageState &state)
Definition qrhi.cpp:13713
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:11430
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:9500
static QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a, QRhiPassResourceTracker::BufferStage b)
Definition qrhi.cpp:13667
QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
Definition qrhi.cpp:8552
static bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess access)
Definition qrhi.cpp:13706
static const char * deviceTypeStr(QRhiDriverInfo::DeviceType type)
\variable QRhiDriverInfo::deviceName
Definition qrhi.cpp:10483
static QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a, QRhiPassResourceTracker::TextureStage b)
Definition qrhi.cpp:13700
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