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
4#include "qrhi_p.h"
5#include <qmath.h>
6#include <QLoggingCategory>
7#include "private/qloggingregistry_p.h"
8
9#include "qrhinull_p.h"
10#ifndef QT_NO_OPENGL
11#include "qrhigles2_p.h"
12#endif
13#if QT_CONFIG(vulkan)
14#include "qrhivulkan_p.h"
15#endif
16#ifdef Q_OS_WIN
17#include "qrhid3d11_p.h"
18#include "qrhid3d12_p.h"
19#endif
20#if QT_CONFIG(metal)
21#include "qrhimetal_p.h"
22#endif
23
24#include <memory>
25
26QT_BEGIN_NAMESPACE
27
28// Play nice with QSG_INFO since that is still the most commonly used
29// way to get graphics info printed from Qt Quick apps, and the Quick
30// scenegraph is our primary user.
31Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(QRHI_LOG_INFO, "QSG_INFO", "qt.rhi.general")
32
33Q_LOGGING_CATEGORY(QRHI_LOG_RUB, "qt.rhi.rub")
34
35/*!
36 \class QRhi
37 \ingroup painting-3D
38 \inmodule QtGuiPrivate
39 \inheaderfile rhi/qrhi.h
40 \since 6.6
41
42 \brief Accelerated 2D/3D graphics API abstraction.
43
44 The Qt Rendering Hardware Interface is an abstraction for hardware accelerated
45 graphics APIs, such as, \l{https://www.khronos.org/opengl/}{OpenGL},
46 \l{https://www.khronos.org/opengles/}{OpenGL ES},
47 \l{https://docs.microsoft.com/en-us/windows/desktop/direct3d}{Direct3D},
48 \l{https://developer.apple.com/metal/}{Metal}, and
49 \l{https://www.khronos.org/vulkan/}{Vulkan}.
50
51 \warning The QRhi family of classes in the Qt Gui module, including QShader
52 and QShaderDescription, offer limited compatibility guarantees. There are
53 no source or binary compatibility guarantees for these classes, meaning the
54 API is only guaranteed to work with the Qt version the application was
55 developed against. Source incompatible changes are however aimed to be kept
56 at a minimum and will only be made in minor releases (6.7, 6.8, and so on).
57 To use these classes in an application, link to
58 \c{Qt::GuiPrivate} (if using CMake), and include the headers with the \c
59 rhi prefix, for example \c{#include <rhi/qrhi.h>}.
60
61 Each QRhi instance is backed by a backend for a specific graphics API. The
62 selection of the backend is a run time choice and is up to the application
63 or library that creates the QRhi instance. Some backends are available on
64 multiple platforms (OpenGL, Vulkan, Null), while APIs specific to a given
65 platform are only available when running on the platform in question (Metal
66 on macOS/iOS, Direct3D on Windows).
67
68 The available backends currently are:
69
70 \list
71
72 \li OpenGL 2.1 / OpenGL ES 2.0 or newer. Some extensions and newer core
73 specification features are utilized when present, for example to enable
74 multisample framebuffers or compute shaders. Operating in core profile
75 contexts is supported as well. If necessary, applications can query the
76 \l{QRhi::Feature}{feature flags} at runtime to check for features that are
77 not supported in the OpenGL context backing the QRhi. The OpenGL backend
78 builds on QOpenGLContext, QOpenGLFunctions, and the related cross-platform
79 infrastructure of the Qt GUI module.
80
81 \li Direct3D 11.2 and newer (with DXGI 1.3 and newer), using Shader Model
82 5.0 or newer. When the D3D runtime has no support for 11.2 features or
83 Shader Model 5.0, initialization using an accelerated graphics device will
84 fail, but using the
85 \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/directx-warp}{software
86 adapter} is still an option.
87
88 \li Direct3D 12 on Windows 10 version 1703 and newer, with Shader Model 5.0
89 or newer. Qt requires ID3D12Device2 to be present, hence the requirement
90 for at least version 1703 of Windows 10. The D3D12 device is by default
91 created with specifying a minimum feature level of
92 \c{D3D_FEATURE_LEVEL_11_0}.
93
94 \li Metal 1.2 or newer.
95
96 \li Vulkan 1.0 or newer, optionally utilizing some Vulkan 1.1 level
97 features.
98
99 \li Null, a "dummy" backend that issues no graphics calls at all.
100
101 \endlist
102
103 In order to allow shader code to be written once in Qt applications and
104 libraries, all shaders are expected to be written in a single language
105 which is then compiled into SPIR-V. Versions for various shading language
106 are then generated from that, together with reflection information (inputs,
107 outputs, shader resources). This is then packed into easily and efficiently
108 serializable QShader instances. The compilers and tools to generate such
109 shaders are not part of QRhi and the Qt GUI module, but the core classes
110 for using such shaders, QShader and QShaderDescription, are. The APIs and
111 tools for performing compilation and translation are part of the Qt Shader
112 Tools module.
113
114 See the \l{RHI Window Example} for an introductory example of creating a
115 portable, cross-platform application that performs accelerated 3D rendering
116 onto a QWindow using QRhi.
117
118 \section1 An Impression of the API
119
120 To provide a quick look at the API with a short yet complete example that
121 does not involve window-related setup, the following is a complete,
122 runnable cross-platform application that renders 20 frames off-screen, and
123 then saves the generated images to files after reading back the texture
124 contents from the GPU. For an example that renders on-screen, which then
125 involves setting up a QWindow and a swapchain, refer to the
126 \l{RHI Window Example}.
127
128 For brevity, the initialization of the QRhi is done based on the platform:
129 the sample code here chooses Direct 3D 12 on Windows, Metal on macOS and
130 iOS, and Vulkan otherwise. OpenGL and Direct 3D 11 are never used by this
131 application, but support for those could be introduced with a few
132 additional lines.
133
134 \snippet rhioffscreen/main.cpp 0
135
136 The result of the application is 20 \c PNG images (frame0.png -
137 frame19.png). These contain a rotating triangle with varying opacity over a
138 green background.
139
140 The vertex and fragment shaders are expected to be processed and packaged
141 into \c{.qsb} files. The Vulkan-compatible GLSL source code is the
142 following:
143
144 \e color.vert
145 \snippet rhioffscreen/color.vert 0
146
147 \e color.frag
148 \snippet rhioffscreen/color.frag 0
149
150 To manually compile and transpile these shaders to a number of targets
151 (SPIR-V, HLSL, MSL, GLSL) and generate the \c{.qsb} files the application
152 loads at run time, run \c{qsb --qt6 color.vert -o color.vert.qsb} and
153 \c{qsb --qt6 color.frag -o color.frag.qsb}. Alternatively, the Qt Shader
154 Tools module offers build system integration for CMake, the
155 \c qt_add_shaders() CMake function, that can achieve the same at build time.
156
157 \section1 Security Considerations
158
159 All data consumed by QRhi and related classes such as QShader are considered
160 trusted content.
161
162 \warning Application developers are advised to carefully consider the
163 potential implications before allowing the feeding of user-provided content
164 that is not part of the application and is not under the developers'
165 control. (this includes all vertex/index data, shaders, pipeline and draw
166 call parameters, etc.)
167
168 \section1 Design Fundamentals
169
170 A QRhi cannot be instantiated directly. Instead, use the create()
171 function. Delete the QRhi instance normally to release the graphics device.
172
173 \section2 Resources
174
175 Instances of classes deriving from QRhiResource, such as, QRhiBuffer,
176 QRhiTexture, etc., encapsulate zero, one, or more native graphics
177 resources. Instances of such classes are always created via the \c new
178 functions of the QRhi, such as, newBuffer(), newTexture(),
179 newTextureRenderTarget(), newSwapChain().
180
181 \code
182 QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
183 if (!vbuf->create()) { error(); }
184 // ...
185 delete vbuf;
186 \endcode
187
188 \list
189
190 \li The returned value from functions like newBuffer() is always owned by
191 the caller.
192
193 \li Just creating an instance of a QRhiResource subclass never allocates or
194 initializes any native resources. That is only done when calling the
195 \c create() function of a subclass, for example, QRhiBuffer::create() or
196 QRhiTexture::create().
197
198 \li The exceptions are
199 QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor(),
200 QRhiSwapChain::newCompatibleRenderPassDescriptor(), and
201 QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor(). There is no
202 \c create() operation for these and the returned object is immediately
203 active.
204
205 \li The resource objects themselves are treated as immutable: once a
206 resource has create() called, changing any parameters via the setters, such as,
207 QRhiTexture::setPixelSize(), has no effect, unless the underlying native
208 resource is released and \c create() is called again. See more about resource
209 reuse in the sections below.
210
211 \li The underlying native resources are scheduled for releasing by the
212 QRhiResource destructor, or by calling QRhiResource::destroy(). Backends
213 often queue release requests and defer executing them to an unspecified
214 time, this is hidden from the applications. This way applications do not
215 have to worry about releasing native resources that may still be in use by
216 an in-flight frame.
217
218 \li Note that this does not mean that a QRhiResource can freely be
219 destroy()'ed or deleted within a frame (that is, in a
220 \l{QRhi::beginFrame()}{beginFrame()} - \l{QRhi::endFrame()}{endFrame()}
221 section). As a general rule, all referenced QRhiResource objects must stay
222 unchanged until the frame is submitted by calling
223 \l{QRhi::endFrame()}{endFrame()}. To ease this,
224 QRhiResource::deleteLater() is provided as a convenience.
225
226 \endlist
227
228 \section2 Command buffers and deferred command execution
229
230 Regardless of the design and capabilities of the underlying graphics API,
231 all QRhi backends implement some level of command buffers. No
232 QRhiCommandBuffer function issues any native bind or draw command (such as,
233 \c glDrawElements) directly. Commands are always recorded in a queue,
234 either native or provided by the QRhi backend. The command buffer is
235 submitted, and so execution starts only upon QRhi::endFrame() or
236 QRhi::finish().
237
238 The deferred nature has consequences for some types of objects. For example,
239 writing to a dynamic buffer multiple times within a frame, in case such
240 buffers are backed by host-visible memory, will result in making the
241 results of all writes are visible to all draw calls in the command buffer
242 of the frame, regardless of when the dynamic buffer update was recorded
243 relative to a draw call.
244
245 Furthermore, instances of QRhiResource subclasses must be treated immutable
246 within a frame in which they are referenced in any way. Create
247 all resources upfront, before starting to record commands for the next
248 frame. Reusing a QRhiResource instance within a frame (by calling \c create()
249 then referencing it again in the same \c{beginFrame - endFrame} section)
250 should be avoided as it may lead to unexpected results, depending on the
251 backend.
252
253 As a general rule, all referenced QRhiResource objects must stay valid and
254 unmodified until the frame is submitted by calling
255 \l{QRhi::endFrame()}{endFrame()}. On the other hand, calling
256 \l{QRhiResource::destroy()}{destroy()} or deleting the QRhiResource are
257 always safe once the frame is submitted, regardless of the status of the
258 underlying native resources (which may still be in use by the GPU - but
259 that is taken care of internally).
260
261 Unlike APIs like OpenGL, upload and copy type of commands cannot be mixed
262 with draw commands. The typical renderer will involve a sequence similar to
263 the following:
264
265 \list
266 \li (re)create resources
267 \li begin frame
268 \li record/issue uploads and copies
269 \li start recording a render pass
270 \li record draw calls
271 \li end render pass
272 \li end frame
273 \endlist
274
275 Recording copy type of operations happens via QRhiResourceUpdateBatch. Such
276 operations are committed typically on
277 \l{QRhiCommandBuffer::beginPass()}{beginPass()}.
278
279 When working with legacy rendering engines designed for OpenGL, the
280 migration to QRhi often involves redesigning from having a single \c render
281 step (that performs copies and uploads, clears buffers, and issues draw
282 calls, all mixed together) to a clearly separated, two phase \c prepare -
283 \c render setup where the \c render step only starts a renderpass and
284 records draw calls, while all resource creation and queuing of updates,
285 uploads and copies happens beforehand, in the \c prepare step.
286
287 QRhi does not at the moment allow freely creating and submitting command
288 buffers. This may be lifted in the future to some extent, in particular if
289 compute support is introduced, but the model of well defined
290 \c{frame-start} and \c{frame-end} points, combined with a dedicated,
291 "frame" command buffer, where \c{frame-end} implies presenting, is going to
292 remain the primary way of operating since this is what fits Qt's various UI
293 technologies best.
294
295 \section2 Threading
296
297 A QRhi instance and the associated resources can be created and used on any
298 thread but all usage must be limited to that one single thread. When
299 rendering to multiple QWindows in an application, having a dedicated thread
300 and QRhi instance for each window is often advisable, as this can eliminate
301 issues with unexpected throttling caused by presenting to multiple windows.
302 Conceptually that is then the same as how Qt Quick scene graph's threaded
303 render loop operates when working directly with OpenGL: one thread for each
304 window, one QOpenGLContext for each thread. When moving onto QRhi,
305 QOpenGLContext is replaced by QRhi, making the migration straightforward.
306
307 When it comes to externally created native objects, such as OpenGL contexts
308 passed in via QRhiGles2NativeHandles, it is up to the application to ensure
309 they are not misused by other threads.
310
311 Resources are not shareable between QRhi instances. This is an intentional
312 choice since QRhi hides most queue, command buffer, and resource
313 synchronization related tasks, and provides no API for them. Safe and
314 efficient concurrent use of graphics resources from multiple threads is
315 tied to those concepts, however, and is thus a topic that is currently out
316 of scope, but may be introduced in the future.
317
318 \note The Metal backend requires that an autorelease pool is available on
319 the rendering thread, ideally wrapping each iteration of the render loop.
320 This needs no action from the users of QRhi when rendering on the main
321 (gui) thread, but becomes important when a separate, dedicated render
322 thread is used.
323
324 \section2 Resource synchronization
325
326 QRhi does not expose APIs for resource barriers or image layout
327 transitions. Such synchronization is done implicitly by the backends, where
328 applicable (for example, Vulkan), by tracking resource usage as necessary.
329 Buffer and image barriers are inserted before render or compute passes
330 transparently to the application.
331
332 \note Resources within a render or compute pass are expected to be bound to
333 a single usage during that pass. For example, a buffer can be used as
334 vertex, index, uniform, or storage buffer, but not a combination of them
335 within a single pass. However, it is perfectly fine to use a buffer as a
336 storage buffer in a compute pass, and then as a vertex buffer in a render
337 pass, for example, assuming the buffer declared both usages upon creation.
338
339 \note Textures have this rule relaxed in certain cases, because using two
340 subresources (typically two different mip levels) of the same texture for
341 different access (one for load, one for store) is supported even within the
342 same pass.
343
344 \section2 Resource reuse
345
346 From the user's point of view a QRhiResource is reusable immediately after
347 calling QRhiResource::destroy(). With the exception of swapchains, calling
348 \c create() on an already created object does an implicit \c destroy(). This
349 provides a handy shortcut to reuse a QRhiResource instance with different
350 parameters, with a new native graphics object underneath.
351
352 The importance of reusing the same object lies in the fact that some
353 objects reference other objects: for example, a QRhiShaderResourceBindings
354 can reference QRhiBuffer, QRhiTexture, and QRhiSampler instances. If in a
355 later frame one of these buffers need to be resized or a sampler parameter
356 needs changing, destroying and creating a whole new QRhiBuffer or
357 QRhiSampler would invalidate all references to the old instance. By just
358 changing the appropriate parameters via QRhiBuffer::setSize() or similar
359 and then calling QRhiBuffer::create(), everything works as expected and
360 there is no need to touch the QRhiShaderResourceBindings at all, even
361 though there is a good chance that under the hood the QRhiBuffer is now
362 backed by a whole new native buffer.
363
364 \code
365 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 256);
366 ubuf->create();
367
368 QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings()
369 srb->setBindings({
370 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf)
371 });
372 srb->create();
373
374 // ...
375
376 // now in a later frame we need to grow the buffer to a larger size
377 ubuf->setSize(512);
378 ubuf->create(); // same as ubuf->destroy(); ubuf->create();
379
380 // srb needs no changes whatsoever, any references in it to ubuf
381 // stay valid. When it comes to internal details, such as that
382 // ubuf may now be backed by a completely different native buffer
383 // resource, that is is recognized and handled automatically by the
384 // next setShaderResources().
385 \endcode
386
387 QRhiTextureRenderTarget offers the same contract: calling
388 QRhiCommandBuffer::beginPass() is safe even when one of the render target's
389 associated textures or renderbuffers has been rebuilt (by calling \c
390 create() on it) since the creation of the render target object. This allows
391 the application to resize a texture by setting a new pixel size on the
392 QRhiTexture and calling create(), thus creating a whole new native texture
393 resource underneath, without having to update the QRhiTextureRenderTarget
394 as that will be done implicitly in beginPass().
395
396 \section2 Pooled objects
397
398 In addition to resources, there are pooled objects as well, such as,
399 QRhiResourceUpdateBatch. An instance is retrieved via a \c next function,
400 such as, nextResourceUpdateBatch(). The caller does not own the returned
401 instance in this case. The only valid way of operating here is calling
402 functions on the QRhiResourceUpdateBatch and then passing it to
403 QRhiCommandBuffer::beginPass() or QRhiCommandBuffer::endPass(). These
404 functions take care of returning the batch to the pool. Alternatively, a
405 batch can be "canceled" and returned to the pool without processing by
406 calling QRhiResourceUpdateBatch::release().
407
408 A typical pattern is thus:
409
410 \code
411 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
412 // ...
413 resUpdates->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
414 if (!image.isNull()) {
415 resUpdates->uploadTexture(texture, image);
416 image = QImage();
417 }
418 // ...
419 QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
420 // note the last argument
421 cb->beginPass(swapchain->currentFrameRenderTarget(), clearCol, clearDs, resUpdates);
422 \endcode
423
424 \section2 Swapchain specifics
425
426 QRhiSwapChain features some special semantics due to the peculiar nature of
427 swapchains.
428
429 \list
430
431 \li It has no \c create() but rather a QRhiSwapChain::createOrResize().
432 Repeatedly calling this function is \b not the same as calling
433 QRhiSwapChain::destroy() followed by QRhiSwapChain::createOrResize(). This
434 is because swapchains often have ways to handle the case where buffers need
435 to be resized in a manner that is more efficient than a brute force
436 destroying and recreating from scratch.
437
438 \li An active QRhiSwapChain must be released by calling
439 \l{QRhiSwapChain::destroy()}{destroy()}, or by destroying the object, before
440 the QWindow's underlying QPlatformWindow, and so the associated native
441 window object, is destroyed. It should not be postponed because releasing
442 the swapchain may become problematic (and with some APIs, like Vulkan, is
443 explicitly disallowed) when the native window is not around anymore, for
444 example because the QPlatformWindow got destroyed upon getting a
445 QWindow::close(). Therefore, releasing the swapchain must happen whenever
446 the targeted QWindow sends the
447 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed event. If the event does
448 not arrive before the destruction of the QWindow - this can happen when
449 using QCoreApplication::quit() -, then check QWindow::handle() after the
450 event loop exits and invoke the swapchain release when non-null (meaning
451 the underlying native window is still around).
452
453 \endlist
454
455 \section2 Ownership
456
457 The general rule is no ownership transfer. Creating a QRhi with an already
458 existing graphics device does not mean the QRhi takes ownership of the
459 device object. Similarly, ownership is not given away when a device or
460 texture object is "exported" via QRhi::nativeHandles() or
461 QRhiTexture::nativeTexture(). Most importantly, passing pointers in structs
462 and via setters does not transfer ownership.
463
464 \section1 Troubleshooting and Profiling
465
466 \section2 Error reporting
467
468 Functions such as \l QRhi::create() and the resource classes' \c create()
469 member functions (e.g., \l QRhiBuffer::create()) indicate failure with the
470 return value (\nullptr or
471 \c false, respectively). When working with QShader, \l QShader::fromSerialized()
472 returns an invalid QShader (for which \l{QShader::isValid()}{isValid()} returns
473 \c false) when the data passed to the function cannot be successfully deserialized.
474 Some functions, beginFrame() in particular, may also sometimes report "soft failures",
475 such as \l FrameOpSwapChainOutOfDate, which do not indicate an unrecoverable error,
476 but rather should be seen as a "try again later" response.
477
478 Warnings and errors may get printed at any time to the debug output via
479 qWarning(). It is therefore always advisable to inspect the output of the
480 application.
481
482 Additional debug messages can be enabled via the following logging
483 categories. Messages from these categories are not printed by default
484 unless explicitly enabled via QLoggingCategory or the \c QT_LOGGING_RULES
485 environment variable. For better interoperation with Qt Quick, the
486 environment variable \c{QSG_INFO} also enables these debug prints.
487
488 \list
489 \li \c{qt.rhi.general}
490 \endlist
491
492 Additionally, applications can query the \l{QRhi::backendName()}{QRhi
493 backend name} and
494 \l{QRhi::driverInfo()}{graphics device information} from a successfully
495 initialized QRhi. This can then be printed to the user or stored in the
496 application logs even in production builds, if desired.
497
498 \section2 Investigating rendering problems
499
500 When the rendering results are not as expected, or the application is
501 experiencing problems, always consider checking with the the native 3D
502 APIs' debug and validation facilities. QRhi itself features limited error
503 checking since replicating the already existing, vast amount of
504 functionality in the underlying layers is not reasonable.
505
506 \list
507
508 \li For Vulkan, controlling the
509 \l{https://github.com/KhronosGroup/Vulkan-ValidationLayers}{Vulkan
510 Validation Layers} is not in the scope of the QRhi, but rather can be
511 achieved by configuring the \l QVulkanInstance with the appropriate layers.
512 For example, call \c{instance.setLayers({ "VK_LAYER_KHRONOS_validation" });}
513 before invoking \l{QVulkanInstance::create()}{create()} on the QVulkanInstance.
514 (note that this assumes that the validation layers are actually installed
515 and available, e.g. from the Vulkan SDK) By default, QVulkanInstance conveniently
516 redirects the Vulkan debug messages to qDebug, meaning the validation messages get
517 printed just like other Qt warnings.
518
519 \li With Direct 3D 11 and 12, a graphics device with the debug layer
520 enabled can be requested by toggling the \c enableDebugLayer flag in the
521 appropriate \l{QRhiD3D11InitParams}{init params struct}. The messages appear on the
522 debug output, which is visible in Qt Creator's messages panel or via a tool
523 such as \l{https://learn.microsoft.com/en-us/sysinternals/downloads/debugview}{DebugView}.
524
525 \li For Metal, controlling Metal Validation is outside of QRhi's scope.
526 Rather, to enable validation, run the application with the environment
527 variable \c{METAL_DEVICE_WRAPPER_TYPE=1} set, or run the application within
528 XCode. There may also be further settings and environment variable in modern
529 XCode and macOS versions. See for instance
530 \l{https://developer.apple.com/documentation/metal/diagnosing_metal_programming_issues_early}{this
531 page}.
532
533 \endlist
534
535 \section2 Frame captures and performance profiling
536
537 A Qt application rendering with QRhi to a window while relying on a 3D API
538 under the hood, is, from the windowing and graphics pipeline perspective at
539 least, no different from any other (non-Qt) applications using the same 3D
540 API. This means that tools and practices for debugging and profiling
541 applications involving 3D graphics, such as games, all apply to such a Qt
542 application as well.
543
544 A few examples of tools that can provide insights into the rendering
545 internals of Qt applications that use QRhi, which includes Qt Quick and Qt
546 Quick 3D based projects as well:
547
548 \list
549
550 \li \l{https://renderdoc.org/}{RenderDoc} allows taking frame captures and
551 introspecting the recorded commands and pipeline state on Windows and Linux
552 for applications using OpenGL, Vulkan, D3D11, or D3D12. When trying to
553 figure out why some parts of the 3D scene do not show up as expected,
554 RenderDoc is often a fast and efficient way to check the pipeline stages
555 and the related state and discover the missing or incorrect value. It is
556 also a tool that is actively used when developing Qt itself.
557
558 \li For NVIDIA-based systems,
559 \l{https://developer.nvidia.com/nsight-graphics}{Nsight Graphics} provides
560 a graphics debugger tool on Windows and Linux. In addition to investigating the commands
561 in the frame and the pipeline, the vendor-specific tools allow looking at timings and
562 hardware performance information, which is not something simple frame captures can provide.
563
564 \li For AMD-based systems, the \l{https://gpuopen.com/rgp/}{Radeon GPU
565 Profiler} can be used to gain deeper insights into the application's
566 rendering and its performance.
567
568 \li Overlays showing live performance information can be highly useful as well, and
569 are often preferable to implementing simple frames-per-second counters within the
570 application itself, since they are more reliable and show more information. An example
571 is \l{https://game.intel.com/us/intel-presentmon/}{PresentMon}, which supports
572 graphics hardware from multiple vendors.
573
574 \li As QRhi supports Direct 3D 12, using
575 \l{https://devblogs.microsoft.com/pix/download/}{PIX}, a performance tuning
576 and debugging tool for DirectX 12 games on Windows is an option as well.
577
578 \li On macOS,
579 \l{https://developer.apple.com/documentation/metal/debugging_tools/viewing_your_gpu_workload_with_the_metal_debugger}{the
580 XCode Metal debugger} can be used to take and introspect frame
581 captures, to investigate performance details, and debug shaders. In macOS 13 it is also possible
582 to enable an overlay that displays frame rate and other information for any Metal-based window by
583 setting the environment variable \c{MTL_HUD_ENABLED=1}.
584
585 \endlist
586
587 On mobile and embedded platforms, there may be vendor and platform-specific
588 tools, provided by the GPU or SoC vendor, available to perform performance
589 profiling of application using OpenGL ES or Vulkan.
590
591 When capturing frames, remember that objects and groups of commands can be
592 named via debug markers, as long as \l{QRhi::EnableDebugMarkers}{debug
593 markers were enabled} for the QRhi, and the graphics API in use supports
594 this. To annotate the command stream, call
595 \l{QRhiCommandBuffer::debugMarkBegin()}{debugMarkBegin()},
596 \l{QRhiCommandBuffer::debugMarkEnd()}{debugMarkEnd()} and/or
597 \l{QRhiCommandBuffer::debugMarkMsg()}{debugMarkMsg()}.
598 This can be particularly useful in larger frames with multiple render passes.
599 Resources are named by calling \l{QRhiResource::setName()}{setName()} before create().
600
601 To perform basic timing measurements on the CPU and GPU side within the
602 application, \l QElapsedTimer and
603 \l QRhiCommandBuffer::lastCompletedGpuTime() can be used. The latter is
604 only available with select graphics APIs at the moment and requires opting
605 in via the \l QRhi::EnableTimestamps flag.
606
607 \section2 Resource leak checking
608
609 When destroying a QRhi object without properly destroying all buffers,
610 textures, and other resources created from it, warnings about this are
611 printed to the debug output whenever the application is a debug build, or
612 when the \c QT_RHI_LEAK_CHECK environment variable is set to a non-zero
613 value. This is a simple way to discover design issues around resource
614 handling within the application rendering logic. Note however that some
615 platforms and underlying graphics APIs may perform their own allocation and
616 resource leak detection as well, over which Qt will have no direct control.
617 For example, when using Vulkan, the memory allocator may raise failing
618 assertions in debug builds when resources that own graphics memory
619 allocations are not destroyed before the QRhi. In addition, the Vulkan
620 validation layer, when enabled, will issue warnings about native graphics
621 resources that were not released. Similarly, with Direct 3D warnings may
622 get printed about unreleased COM objects when the application does not
623 destroy the QRhi and its resources in the correct order.
624
625 \sa {RHI Window Example}, QRhiCommandBuffer, QRhiResourceUpdateBatch,
626 QRhiShaderResourceBindings, QShader, QRhiBuffer, QRhiTexture,
627 QRhiRenderBuffer, QRhiSampler, QRhiTextureRenderTarget,
628 QRhiGraphicsPipeline, QRhiComputePipeline, QRhiSwapChain
629 */
630
631/*!
632 \enum QRhi::Implementation
633 Describes which graphics API-specific backend gets used by a QRhi instance.
634
635 \value Null
636 \value Vulkan
637 \value OpenGLES2
638 \value D3D11
639 \value D3D12
640 \value Metal
641 */
642
643/*!
644 \enum QRhi::Flag
645 Describes what special features to enable.
646
647 \value EnableDebugMarkers Enables debug marker groups. Without this frame
648 debugging features like making debug groups and custom resource name
649 visible in external GPU debugging tools will not be available and functions
650 like QRhiCommandBuffer::debugMarkBegin() will become no-ops. Avoid enabling
651 in production builds as it may involve a small performance impact. Has no
652 effect when the QRhi::DebugMarkers feature is not reported as supported.
653
654 \value EnableTimestamps Enables GPU timestamp collection. When not set,
655 QRhiCommandBuffer::lastCompletedGpuTime() always returns 0. Enable this
656 only when needed since there may be a small amount of extra work involved
657 (e.g. timestamp queries), depending on the underlying graphics API. Has no
658 effect when the QRhi::Timestamps feature is not reported as supported.
659
660 \value PreferSoftwareRenderer Indicates that backends should prefer
661 choosing an adapter or physical device that renders in software on the CPU.
662 For example, with Direct3D there is typically a "Basic Render Driver"
663 adapter available with \c{DXGI_ADAPTER_FLAG_SOFTWARE}. Setting this flag
664 requests the backend to choose that adapter over any other, as long as no
665 specific adapter was forced by other backend-specific means. With Vulkan
666 this maps to preferring physical devices with
667 \c{VK_PHYSICAL_DEVICE_TYPE_CPU}. When not available, or when it is not
668 possible to decide if an adapter/device is software-based, this flag is
669 ignored. It may also be ignored with graphics APIs that have no concept and
670 means of enumerating adapters/devices.
671
672 \value EnablePipelineCacheDataSave Enables retrieving the pipeline cache
673 contents, where applicable. When not set, pipelineCacheData() will return
674 an empty blob always. With backends where retrieving and restoring the
675 pipeline cache contents is not supported, the flag has no effect and the
676 serialized cache data is always empty. The flag provides an opt-in
677 mechanism because the cost of maintaining the related data structures is
678 not insignificant with some backends. With Vulkan this feature maps
679 directly to VkPipelineCache, vkGetPipelineCacheData and
680 VkPipelineCacheCreateInfo::pInitialData. With Direct3D 11 there is no real
681 pipline cache, but the results of HLSL->DXBC compilations are stored and
682 can be serialized/deserialized via this mechanism. This allows skipping the
683 time consuming D3DCompile() in future runs of the applications for shaders
684 that come with HLSL source instead of offline pre-compiled bytecode. This
685 can provide a huge boost in startup and load times, if there is a lot of
686 HLSL source compilation happening. With OpenGL the "pipeline cache" is
687 simulated by retrieving and loading shader program binaries (if supported
688 by the driver). With OpenGL there are additional, disk-based caching
689 mechanisms for shader/program binaries provided by Qt. Writing to those may
690 get disabled whenever this flag is set since storing program binaries to
691 multiple caches is not sensible.
692
693 \value SuppressSmokeTestWarnings Indicates that, with backends where this
694 is relevant, certain, non-fatal QRhi::create() failures should not
695 produce qWarning() calls. For example, with D3D11, passing this flag
696 makes a number of warning messages (that appear due to QRhi::create()
697 failing) to become categorized debug prints instead under the commonly used
698 \c{qt.rhi.general} logging category. This can be used by engines, such as
699 Qt Quick, that feature fallback logic, i.e. they retry calling create()
700 with a different set of flags (such as, \l PreferSoftwareRenderer), in order
701 to hide the unconditional warnings from the output that would be printed
702 when the first create() attempt had failed.
703 */
704
705/*!
706 \enum QRhi::FrameOpResult
707 Describes the result of operations that can have a soft failure.
708
709 \value FrameOpSuccess Success
710
711 \value FrameOpError Unspecified error
712
713 \value FrameOpSwapChainOutOfDate The swapchain is in an inconsistent state
714 internally. This can be recoverable by attempting to repeat the operation
715 (such as, beginFrame()) later.
716
717 \value FrameOpDeviceLost The graphics device was lost. This can be
718 recoverable by attempting to repeat the operation (such as, beginFrame())
719 after releasing and reinitializing all objects backed by native graphics
720 resources. See isDeviceLost().
721 */
722
723/*!
724 \enum QRhi::Feature
725 Flag values to indicate what features are supported by the backend currently in use.
726
727 \value MultisampleTexture Indicates that textures with a sample count larger
728 than 1 are supported. In practice this feature will be unsupported with
729 OpenGL ES versions older than 3.1, and OpenGL older than 3.0.
730
731 \value MultisampleRenderBuffer Indicates that renderbuffers with a sample
732 count larger than 1 are supported. In practice this feature will be
733 unsupported with OpenGL ES 2.0, and may also be unsupported with OpenGL 2.x
734 unless the relevant extensions are present.
735
736 \value DebugMarkers Indicates that debug marker groups (and so
737 QRhiCommandBuffer::debugMarkBegin()) are supported.
738
739 \value Timestamps Indicates that command buffer timestamps are supported.
740 Relevant for QRhiCommandBuffer::lastCompletedGpuTime(). This can be
741 expected to be supported on Metal, Vulkan, Direct 3D 11 and 12, and OpenGL
742 contexts of version 3.3 or newer. However, with some of these APIs support
743 for timestamp queries is technically optional, and therefore it cannot be
744 guaranteed that this feature is always supported with every implementation
745 of them.
746
747 \value Instancing Indicates that instanced drawing is supported. In
748 practice this feature will be unsupported with OpenGL ES 2.0 and OpenGL
749 3.2 or older.
750
751 \value CustomInstanceStepRate Indicates that instance step rates other
752 than 1 are supported. In practice this feature will always be unsupported
753 with OpenGL. In addition, running with Vulkan 1.0 without
754 VK_EXT_vertex_attribute_divisor will also lead to reporting false for this
755 feature.
756
757 \value PrimitiveRestart Indicates that restarting the assembly of
758 primitives when encountering an index value of 0xFFFF
759 (\l{QRhiCommandBuffer::IndexUInt16}{IndexUInt16}) or 0xFFFFFFFF
760 (\l{QRhiCommandBuffer::IndexUInt32}{IndexUInt32}) is enabled, for certain
761 primitive topologies at least. QRhi will try to enable this with all
762 backends, but in some cases it will not be supported. Dynamically
763 controlling primitive restart is not possible since with some APIs
764 primitive restart with a fixed index is always on. Applications must assume
765 that whenever this feature is reported as supported, the above mentioned
766 index values \c may be treated specially, depending on the topology. The
767 only two topologies where primitive restart is guaranteed to behave
768 identically across backends, as long as this feature is reported as
769 supported, are \l{QRhiGraphicsPipeline::LineStrip}{LineStrip} and
770 \l{QRhiGraphicsPipeline::TriangleStrip}{TriangleStrip}.
771
772 \value NonDynamicUniformBuffers Indicates that creating buffers with the
773 usage \l{QRhiBuffer::UniformBuffer}{UniformBuffer} and the types
774 \l{QRhiBuffer::Immutable}{Immutable} or \l{QRhiBuffer::Static}{Static} is
775 supported. When reported as unsupported, uniform (constant) buffers must be
776 created as \l{QRhiBuffer::Dynamic}{Dynamic}. (which is recommended
777 regardless)
778
779 \value NonFourAlignedEffectiveIndexBufferOffset Indicates that effective
780 index buffer offsets (\c{indexOffset + firstIndex * indexComponentSize})
781 that are not 4 byte aligned are supported. When not supported, attempting
782 to issue a \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} with a
783 non-aligned effective offset may lead to unspecified behavior. Relevant in
784 particular for Metal, where this will be reported as unsupported.
785
786 \value NPOTTextureRepeat Indicates that the
787 \l{QRhiSampler::Repeat}{Repeat} wrap mode and mipmap filtering modes are
788 supported for textures with a non-power-of-two size. In practice this can
789 only be false with OpenGL ES 2.0 implementations without
790 \c{GL_OES_texture_npot}.
791
792 \value RedOrAlpha8IsRed Indicates that the
793 \l{QRhiTexture::RED_OR_ALPHA8}{RED_OR_ALPHA8} format maps to a one
794 component 8-bit \c red format. This is the case for all backends except
795 OpenGL when using either OpenGL ES or a non-core profile context. There
796 \c{GL_ALPHA}, a one component 8-bit \c alpha format, is used
797 instead. Using the special texture format allows having a single code
798 path for creating textures, leaving it up to the backend to decide the
799 actual format, while the feature flag can be used to pick the
800 appropriate shader variant for sampling the texture.
801
802 \value ElementIndexUint Indicates that 32-bit unsigned integer elements are
803 supported in the index buffer. In practice this is true everywhere except
804 when running on plain OpenGL ES 2.0 implementations without the necessary
805 extension. When false, only 16-bit unsigned elements are supported in the
806 index buffer.
807
808 \value Compute Indicates that compute shaders, image load/store, and
809 storage buffers are supported. OpenGL older than 4.3 and OpenGL ES older
810 than 3.1 have no compute support.
811
812 \value WideLines Indicates that lines with a width other than 1 are
813 supported. When reported as not supported, the line width set on the
814 graphics pipeline state is ignored. This can always be false with some
815 backends (D3D11, D3D12, Metal). With Vulkan, the value depends on the
816 implementation. With OpenGL, wide lines are not supported in core profile
817 contexts.
818
819 \value VertexShaderPointSize Indicates that the size of rasterized points
820 set via \c{gl_PointSize} in the vertex shader is taken into account. When
821 reported as not supported, drawing points with a size other than 1 is not
822 supported. Setting \c{gl_PointSize} in the shader is still valid then, but
823 is ignored. (for example, when generating HLSL, the assignment is silently
824 dropped from the generated code) Note that some APIs (Metal, Vulkan)
825 require the point size to be set in the shader explicitly whenever drawing
826 points, even when the size is 1, as they do not automatically default to 1.
827
828 \value BaseVertex Indicates that
829 \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} supports the \c
830 vertexOffset argument. When reported as not supported, the vertexOffset
831 value in an indexed draw is ignored. In practice this feature will be
832 unsupported with OpenGL and OpenGL ES versions lower than 3.2, and with
833 Metal on older iOS devices, including the iOS Simulator.
834
835 \value BaseInstance Indicates that instanced draw commands support the \c
836 firstInstance argument. When reported as not supported, the firstInstance
837 value is ignored and the instance ID starts from 0. In practice this feature
838 will be unsupported with with Metal on older iOS devices, including the iOS
839 Simulator, and all versions of OpenGL. The latter is due to OpenGL ES not
840 supporting draw calls with a base instance at all. Currently QRhi's OpenGL
841 backend does not implement the functionality for OpenGL (non-ES) either,
842 because portable applications cannot rely on a non-zero base instance in
843 practice due to GLES. If the application still chooses to do so, it should
844 be aware of the InstanceIndexIncludesBaseInstance feature as well.
845
846 \value TriangleFanTopology Indicates that QRhiGraphicsPipeline::setTopology()
847 supports QRhiGraphicsPipeline::TriangleFan. In practice this feature will be
848 unsupported with Metal and Direct 3D 11/12.
849
850 \value ReadBackNonUniformBuffer Indicates that
851 \l{QRhiResourceUpdateBatch::readBackBuffer()}{reading buffer contents} is
852 supported for QRhiBuffer instances with a usage different than
853 UniformBuffer. In practice this feature will be unsupported with OpenGL ES
854 2.0.
855
856 \value ReadBackNonBaseMipLevel Indicates that specifying a mip level other
857 than 0 is supported when reading back texture contents. When not supported,
858 specifying a non-zero level in QRhiReadbackDescription leads to returning
859 an all-zero image. In practice this feature will be unsupported with OpenGL
860 ES 2.0.
861
862 \value TexelFetch Indicates that texelFetch() and textureLod() are available
863 in shaders. In practice this will be reported as unsupported with OpenGL ES
864 2.0 and OpenGL 2.x contexts, because GLSL 100 es and versions before 130 do
865 not support these functions.
866
867 \value RenderToNonBaseMipLevel Indicates that specifying a mip level other
868 than 0 is supported when creating a QRhiTextureRenderTarget with a
869 QRhiTexture as its color attachment. When not supported, create() will fail
870 whenever the target mip level is not zero. In practice this feature will be
871 unsupported with OpenGL ES 2.0.
872
873 \value IntAttributes Indicates that specifying input attributes with
874 signed and unsigned integer types for a shader pipeline is supported. When
875 not supported, build() will succeed but just show a warning message and the
876 values of the target attributes will be broken. In practice this feature
877 will be unsupported with OpenGL ES 2.0 and OpenGL 2.x.
878
879 \value ScreenSpaceDerivatives Indicates that functions such as dFdx(),
880 dFdy(), and fwidth() are supported in shaders. In practice this feature will
881 be unsupported with OpenGL ES 2.0 without the GL_OES_standard_derivatives
882 extension.
883
884 \value ReadBackAnyTextureFormat Indicates that reading back texture
885 contents can be expected to work for any QRhiTexture::Format. Backends
886 other than OpenGL can be expected to return true for this feature. When
887 reported as false, which will typically happen with OpenGL, only the
888 formats QRhiTexture::RGBA8 and QRhiTexture::BGRA8 are guaranteed to be
889 supported for readbacks. In addition, with OpenGL, but not OpenGL ES,
890 reading back the 1 byte per component formats QRhiTexture::R8 and
891 QRhiTexture::RED_OR_ALPHA8 are supported as well. Reading back floating
892 point formats QRhiTexture::RGBA16F and RGBA32F may work too with OpenGL, as
893 long as the implementation provides support for these, but QRhi can give no
894 guarantees, as indicated by this flag.
895
896 \value PipelineCacheDataLoadSave Indicates that the pipelineCacheData() and
897 setPipelineCacheData() functions are functional. When not supported, the
898 functions will not perform any action, the retrieved blob is always empty,
899 and thus no benefits can be expected from retrieving and, during a
900 subsequent run of the application, reloading the pipeline cache content.
901
902 \value ImageDataStride Indicates that specifying a custom stride (row
903 length) for raw image data in texture uploads is supported. When not
904 supported (which can happen when the underlying API is OpenGL ES 2.0 without
905 support for GL_UNPACK_ROW_LENGTH),
906 QRhiTextureSubresourceUploadDescription::setDataStride() must not be used.
907
908 \value RenderBufferImport Indicates that QRhiRenderBuffer::createFrom() is
909 supported. For most graphics APIs this is not sensible because
910 QRhiRenderBuffer encapsulates texture objects internally, just like
911 QRhiTexture. With OpenGL however, renderbuffer object exist as a separate
912 object type in the API, and in certain environments (for example, where one
913 may want to associated a renderbuffer object with an EGLImage object) it is
914 important to allow wrapping an existing OpenGL renderbuffer object with a
915 QRhiRenderBuffer.
916
917 \value ThreeDimensionalTextures Indicates that 3D textures are supported.
918 In practice this feature will be unsupported with OpenGL and OpenGL ES
919 versions lower than 3.0.
920
921 \value RenderTo3DTextureSlice Indicates that rendering to a slice in a 3D
922 texture is supported. This can be unsupported with Vulkan 1.0 due to
923 relying on VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT which is a Vulkan 1.1
924 feature.
925
926 \value TextureArrays Indicates that texture arrays are supported and
927 QRhi::newTextureArray() is functional. Note that even when texture arrays
928 are not supported, arrays of textures are still available as those are two
929 independent features.
930
931 \value Tessellation Indicates that the tessellation control and evaluation
932 stages are supported. When reported as supported, the topology of a
933 QRhiGraphicsPipeline can be set to
934 \l{QRhiGraphicsPipeline::Patches}{Patches}, the number of control points
935 can be set via
936 \l{QRhiGraphicsPipeline::setPatchControlPointCount()}{setPatchControlPointCount()},
937 and shaders for tessellation control and evaluation can be specified in the
938 QRhiShaderStage list. Tessellation shaders have portability issues between
939 APIs (for example, translating GLSL/SPIR-V to HLSL is problematic due to
940 the way hull shaders are structured, whereas Metal uses a somewhat
941 different tessellation pipeline than others), and therefore unexpected
942 issues may still arise, even though basic functionality is implemented
943 across all the underlying APIs. For Direct 3D in particular, handwritten
944 HLSL hull and domain shaders must be injected into each QShader for the
945 tessellation control and evaluation stages, respectively, since qsb cannot
946 generate these from SPIR-V. Note that isoline tessellation should be
947 avoided as it will not be supported by all backends. The maximum patch
948 control point count portable between backends is 32.
949
950 \value GeometryShader Indicates that the geometry shader stage is supported.
951 When supported, a geometry shader can be specified in the QRhiShaderStage
952 list. Geometry Shaders are considered an experimental feature in QRhi and
953 can only be expected to be supported with Vulkan, Direct 3D 11 and 12,
954 OpenGL (3.2+) and OpenGL ES (3.2+), assuming the implementation reports it
955 as supported at run time. Starting with Qt 6.11 geometry shaders are
956 automatically translated to HLSL, and therefore no injection of handwritten
957 HLSL geometry shaders is necessary anymore (but note that gl_in and
958 expressions such as gl_in[0].gl_Position are not supported; rather, pass the
959 position as an output variable from the vertex shader). Geometry shaders are
960 not supported with Metal.
961
962 \value TextureArrayRange Indicates that for
963 \l{QRhi::newTextureArray()}{texture arrays} it is possible to specify a
964 range that is exposed to the shaders. Normally all array layers are exposed
965 and it is up to the shader to select the layer (via the third coordinate
966 passed to texture() when sampling the \c sampler2DArray). When supported,
967 calling QRhiTexture::setArrayRangeStart() and
968 QRhiTexture::setArrayRangeLength() before
969 \l{QRhiTexture::create()}{building} or
970 \l{QRhiTexture::createFrom()}{importing} the native texture has an effect,
971 and leads to selecting only the specified range from the array. This will
972 be necessary in special cases, such as when working with accelerated video
973 decoding and Direct 3D 11, because a texture array with both
974 \c{D3D11_BIND_DECODER} and \c{D3D11_BIND_SHADER_RESOURCE} on it is only
975 usable as a shader resource if a single array layer is selected. Note that
976 all this is applicable only when the texture is used as a
977 QRhiShaderResourceBinding::SampledTexture or
978 QRhiShaderResourceBinding::Texture shader resource, and is not compatible
979 with image load/store. This feature is only available with some backends as
980 it does not map well to all graphics APIs, and it is only meant to provide
981 support for special cases anyhow. In practice the feature can be expected to
982 be supported with Direct3D 11/12 and Vulkan.
983
984 \value NonFillPolygonMode Indicates that setting a PolygonMode other than
985 the default Fill is supported for QRhiGraphicsPipeline. A common use case
986 for changing the mode to Line is to get wireframe rendering. This however
987 is not available as a core OpenGL ES feature, and is optional with Vulkan
988 as well as some mobile GPUs may not offer the feature.
989
990 \value OneDimensionalTextures Indicates that 1D textures are supported.
991 In practice this feature will be unsupported on OpenGL ES.
992
993 \value OneDimensionalTextureMipmaps Indicates that generating 1D texture
994 mipmaps are supported. In practice this feature will be unsupported on
995 backends that do not report support for
996 \l{OneDimensionalTextures}, Metal, and Direct 3D 12.
997
998 \value HalfAttributes Indicates that specifying input attributes with half
999 precision (16bit) floating point types for a shader pipeline is supported.
1000 When not supported, build() will succeed but just show a warning message
1001 and the values of the target attributes will be broken. In practice this
1002 feature will be unsupported in some OpenGL ES 2.0 and OpenGL 2.x
1003 implementations. Note that while Direct3D 11/12 does support half precision
1004 input attributes, it does not support the half3 type. The D3D backends pass
1005 half3 attributes as half4. To ensure cross platform compatibility, half3
1006 inputs should be padded to 8 bytes.
1007
1008 \value RenderToOneDimensionalTexture Indicates that 1D texture render
1009 targets are supported. In practice this feature will be unsupported on
1010 backends that do not report support for
1011 \l{OneDimensionalTextures}, and Metal.
1012
1013 \value ThreeDimensionalTextureMipmaps Indicates that generating 3D texture
1014 mipmaps are supported. This is typically supported with all backends starting
1015 with Qt 6.10.
1016
1017 \value MultiView Indicates that multiview, see e.g.
1018 \l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_multiview.html}{VK_KHR_multiview}
1019 is supported. With OpenGL ES 2.0, Direct 3D 11, and OpenGL (ES)
1020 implementations without \c{GL_OVR_multiview2} this feature will not be
1021 supported. With Vulkan 1.1 and newer, and Direct 3D 12 multiview is
1022 typically supported. When reported as supported, creating a
1023 QRhiTextureRenderTarget with a QRhiColorAttachment that references a texture
1024 array and has \l{QRhiColorAttachment::setMultiViewCount()}{multiViewCount}
1025 set enables recording a render pass that uses multiview rendering. In addition,
1026 any QRhiGraphicsPipeline used in that render pass must have
1027 \l{QRhiGraphicsPipeline::setMultiViewCount()}{the same view count set}. Note that
1028 multiview is only available in combination with 2D texture arrays. It cannot
1029 be used to optimize the rendering into individual textures (e.g. two, for
1030 the left and right eyes). Rather, the target of a multiview render pass is
1031 always a texture array, automatically rendering to the layer (array element)
1032 corresponding to each view. Therefore this feature implies \l TextureArrays
1033 as well. Multiview rendering is not supported in combination with
1034 tessellation or geometry shaders. See QRhiColorAttachment::setMultiViewCount()
1035 for further details on multiview rendering. This enum value has been introduced in Qt 6.7.
1036
1037 \value TextureViewFormat Indicates that setting a
1038 \l{QRhiTexture::setWriteViewFormat()}{view format} on a QRhiTexture is
1039 effective. When reported as supported, setting the read (sampling) or write
1040 (render target / image load-store) view mode changes the texture's viewing
1041 format. When unsupported, setting a view format has no effect. Note that Qt
1042 has no knowledge or control over format compatibility or resource view rules
1043 in the underlying 3D API and its implementation. Passing in unsuitable,
1044 incompatible formats may lead to errors and unspecified behavior. This is
1045 provided mainly to allow "casting" rendering into a texture created with an
1046 sRGB format to non-sRGB to avoid the unwanted linear->sRGB conversion on
1047 shader writes. Other types of casting may or may not be functional,
1048 depending on the underlying API. Currently implemented for Vulkan and Direct
1049 3D 12. With D3D12 the feature is available only if
1050 \c CastingFullyTypedFormatSupported is supported, see
1051 \l{https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html} (and
1052 note that QRhi always uses fully typed formats for textures.) This enum
1053 value has been introduced in Qt 6.8.
1054
1055 \value ResolveDepthStencil Indicates that resolving a multisample depth or
1056 depth-stencil texture is supported. Otherwise,
1057 \l{QRhiTextureRenderTargetDescription::setDepthResolveTexture()}{setting a
1058 depth resolve texture} is not functional and must be avoided. Direct 3D 11
1059 and 12 have no support for resolving depth/depth-stencil formats, and
1060 therefore this feature will never be supported with those. Vulkan 1.0 has no
1061 API to request resolving a depth-stencil attachment. Therefore, with Vulkan
1062 this feature will only be supported with Vulkan 1.2 and up, and on 1.1
1063 implementations with the appropriate extensions present. This feature is
1064 provided for the rare case when resolving into a non-multisample depth
1065 texture becomes necessary, for example when rendering into an
1066 OpenXR-provided depth texture (XR_KHR_composition_layer_depth). This enum
1067 value has been introduced in Qt 6.8.
1068
1069 \value VariableRateShading Indicates that per-draw (per-pipeline) variable
1070 rate shading is supported. When reported as supported, \l
1071 QRhiCommandBuffer::setShadingRate() is functional and has an effect for
1072 QRhiGraphicsPipeline objects that declared \l
1073 QRhiGraphicsPipeline::UsesShadingRate in their flags. Call \l
1074 QRhi::supportedShadingRates() to check which rates are supported. (1x1 is
1075 always supported, other typical values are 2x2, 1x2, 2x1, 2x4, 4x2, 4x4).
1076 This feature can be expected to be supported with Direct 3D 12 and Vulkan,
1077 assuming the implementation and GPU used at run time supports VRS. This enum
1078 value has been introduced in Qt 6.9.
1079
1080 \value VariableRateShadingMap Indicates that image-based specification of
1081 the shading rate is possible. The "image" is not necessarily a texture, it
1082 may be a native 3D API object, depending on the underlying backend and
1083 graphics API at run time. In practice this feature can be expected to be
1084 supported with Direct 3D 12, Vulkan, and Metal, assuming the GPU is modern
1085 enough to support VRS. To check if D3D12/Vulkan-style image-based VRS is
1086 suspported, use VariableRateShadingMapWithTexture instead. When this feature
1087 is reported as supported, there are two possibilities: when
1088 VariableRateShadingMapWithTexture is also true, then QRhiShadingRateMap
1089 consumes QRhiTexture objects via the createFrom() overload taking a
1090 QRhiTexture argument. When VariableRateShadingMapWithTexture is false, then
1091 QRhiShadingRateMap consumes some other type of native objects, for example
1092 an MTLRasterizationRateMap in case of Metal. Use the createFrom() overload
1093 taking a NativeShadingRateMap in this case. This enum value has been
1094 introduced in Qt 6.9.
1095
1096 \value VariableRateShadingMapWithTexture Indicates that image-based
1097 specification of the shading rate is supported via regular textures. In
1098 practice this may be supported with Direct 3D 12 and Vulkan. This enum value
1099 has been introduced in Qt 6.9.
1100
1101 \value PerRenderTargetBlending Indicates that per rendertarget blending is
1102 supported i.e. different render targets in MRT framebuffer can have different
1103 blending modes. In practice this can be expected to be supported everywhere
1104 except OpenGL ES, where it is only available with GLES 3.2 implementations.
1105 This enum value has been introduced in Qt 6.9.
1106
1107 \value SampleVariables Indicates that gl_SampleID, gl_SamplePosition,
1108 gl_SampleMaskIn and gl_SampleMask variables are available in fragment shaders.
1109 In practice this can be expected to be supported everywhere except OpenGL ES,
1110 where it is only available with GLES 3.2 implementations.
1111 This enum value has been introduced in Qt 6.9.
1112
1113 \value InstanceIndexIncludesBaseInstance Indicates that \c gl_InstanceIndex
1114 includes the base instance (the \c firstInstance argument in draw calls) in
1115 its value. When this feature is unsupported, but BaseInstance is, it
1116 indicates that \c gl_InstanceIndex always starts at 0, not the base value.
1117 In practice this will be the case for Direct 3D 11 and 12 at the moment.
1118 With Vulkan and Metal this feature is expected to be reported as supported
1119 always. This enum value has been introduced in Qt 6.11.
1120 */
1121
1122/*!
1123 \enum QRhi::BeginFrameFlag
1124 Flag values for QRhi::beginFrame()
1125 */
1126
1127/*!
1128 \enum QRhi::EndFrameFlag
1129 Flag values for QRhi::endFrame()
1130
1131 \value SkipPresent Specifies that no present command is to be queued or no
1132 swapBuffers call is to be made. This way no image is presented. Generating
1133 multiple frames with all having this flag set is not recommended (except,
1134 for example, for benchmarking purposes - but keep in mind that backends may
1135 behave differently when it comes to waiting for command completion without
1136 presenting so the results are not comparable between them)
1137 */
1138
1139/*!
1140 \enum QRhi::ResourceLimit
1141 Describes the resource limit to query.
1142
1143 \value TextureSizeMin Minimum texture width and height. This is typically
1144 1. The minimum texture size is handled gracefully, meaning attempting to
1145 create a texture with an empty size will instead create a texture with the
1146 minimum size.
1147
1148 \value TextureSizeMax Maximum texture width and height. This depends on the
1149 graphics API and sometimes the platform or implementation as well.
1150 Typically the value is in the range 4096 - 16384. Attempting to create
1151 textures larger than this is expected to fail.
1152
1153 \value MaxColorAttachments The maximum number of color attachments for a
1154 QRhiTextureRenderTarget, in case multiple render targets are supported. When
1155 MRT is not supported, the value is 1. Otherwise this is typically 8, but
1156 watch out for the fact that OpenGL only mandates 4 as the minimum, and that
1157 is what some OpenGL ES implementations provide.
1158
1159 \value FramesInFlight The number of frames the backend may keep "in
1160 flight": with backends like Vulkan or Metal, it is the responsibility of
1161 QRhi to block whenever starting a new frame and finding the CPU is already
1162 \c{N - 1} frames ahead of the GPU (because the command buffer submitted in
1163 frame no. \c{current} - \c{N} has not yet completed). The value N is what
1164 is returned from here, and is typically 2. This can be relevant to
1165 applications that integrate rendering done directly with the graphics API,
1166 as such rendering code may want to perform double (if the value is 2)
1167 buffering for resources, such as, buffers, similarly to the QRhi backends
1168 themselves. The current frame slot index (a value running 0, 1, .., N-1,
1169 then wrapping around) is retrievable from QRhi::currentFrameSlot(). The
1170 value is 1 for backends where the graphics API offers no such low level
1171 control over the command submission process. Note that pipelining may still
1172 happen even when this value is 1 (some backends, such as D3D11, are
1173 designed to attempt to enable this, for instance, by using an update
1174 strategy for uniform buffers that does not stall the pipeline), but that is
1175 then not controlled by QRhi and so not reflected here in the API.
1176
1177 \value MaxAsyncReadbackFrames The number of \l{QRhi::endFrame()}{submitted}
1178 frames (including the one that contains the readback) after which an
1179 asynchronous texture or buffer readback is guaranteed to complete upon
1180 \l{QRhi::beginFrame()}{starting a new frame}.
1181
1182 \value MaxThreadGroupsPerDimension The maximum number of compute
1183 work/thread groups that can be dispatched. Effectively the maximum value
1184 for the arguments of QRhiCommandBuffer::dispatch(). Typically 65535.
1185
1186 \value MaxThreadsPerThreadGroup The maximum number of invocations in a
1187 single local work group, or in other terminology, the maximum number of
1188 threads in a thread group. Effectively the maximum value for the product of
1189 \c local_size_x, \c local_size_y, and \c local_size_z in the compute
1190 shader. Typical values are 128, 256, 512, 1024, or 1536. Watch out that
1191 both OpenGL ES and Vulkan specify only 128 as the minimum required limit
1192 for implementations. While uncommon for Vulkan, some OpenGL ES 3.1
1193 implementations for mobile/embedded devices only support the spec-mandated
1194 minimum value.
1195
1196 \value MaxThreadGroupX The maximum size of a work/thread group in the X
1197 dimension. Effectively the maximum value of \c local_size_x in the compute
1198 shader. Typically 256 or 1024.
1199
1200 \value MaxThreadGroupY The maximum size of a work/thread group in the Y
1201 dimension. Effectively the maximum value of \c local_size_y in the compute
1202 shader. Typically 256 or 1024.
1203
1204 \value MaxThreadGroupZ The maximum size of a work/thread group in the Z
1205 dimension. Effectively the maximum value of \c local_size_z in the compute
1206 shader. Typically 64 or 256.
1207
1208 \value TextureArraySizeMax Maximum texture array size. Typically in range
1209 256 - 2048. Attempting to \l{QRhi::newTextureArray()}{create a texture
1210 array} with more elements will likely fail.
1211
1212 \value MaxUniformBufferRange The number of bytes that can be exposed from a
1213 uniform buffer to the shaders at once. On OpenGL ES 2.0 and 3.0
1214 implementations this may be as low as 3584 bytes (224 four component, 32
1215 bits per component vectors). Elsewhere the value is typically 16384 (1024
1216 vec4s) or 65536 (4096 vec4s).
1217
1218 \value MaxVertexInputs The number of input attributes to the vertex shader.
1219 The location in a QRhiVertexInputAttribute must be in range \c{[0,
1220 MaxVertexInputs-1]}. The value may be as low as 8 with OpenGL ES 2.0.
1221 Elsewhere, typical values are 16, 31, or 32.
1222
1223 \value MaxVertexOutputs The maximum number of outputs (4 component vector
1224 \c out variables) from the vertex shader. The value may be as low as 8 with
1225 OpenGL ES 2.0, and 15 with OpenGL ES 3.0 and some Metal devices. Elsewhere,
1226 a typical value is 32.
1227
1228 \value ShadingRateImageTileSize The tile size for shading rate textures. 0
1229 if the QRhi::VariableRateShadingMapWithTexture feature is not supported.
1230 Otherwise a value such as 16, indicating, for example, a tile size of 16x16.
1231 Each byte in the (R8UI) shading rate texture defines then the shading rate
1232 for a tile of 16x16 pixels. See \l QRhiShadingRateMap for details.
1233 */
1234
1235/*!
1236 \class QRhiInitParams
1237 \inmodule QtGuiPrivate
1238 \inheaderfile rhi/qrhi.h
1239 \since 6.6
1240 \brief Base class for backend-specific initialization parameters.
1241
1242 Contains fields that are relevant to all backends.
1243
1244 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1245 for details.
1246 */
1247
1248/*!
1249 \class QRhiDepthStencilClearValue
1250 \inmodule QtGuiPrivate
1251 \inheaderfile rhi/qrhi.h
1252 \since 6.6
1253 \brief Specifies clear values for a depth or stencil buffer.
1254
1255 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1256 for details.
1257 */
1258
1259/*!
1260 \fn QRhiDepthStencilClearValue::QRhiDepthStencilClearValue() = default
1261
1262 Constructs a depth/stencil clear value with depth clear value 1.0f and
1263 stencil clear value 0.
1264 */
1265
1266/*!
1267 Constructs a depth/stencil clear value with depth clear value \a d and
1268 stencil clear value \a s.
1269 */
1270QRhiDepthStencilClearValue::QRhiDepthStencilClearValue(float d, quint32 s)
1271 : m_d(d),
1272 m_s(s)
1273{
1274}
1275
1276/*!
1277 \fn float QRhiDepthStencilClearValue::depthClearValue() const
1278 \return the depth clear value. In most cases this is 1.0f.
1279 */
1280
1281/*!
1282 \fn void QRhiDepthStencilClearValue::setDepthClearValue(float d)
1283 Sets the depth clear value to \a d.
1284 */
1285
1286/*!
1287 \fn quint32 QRhiDepthStencilClearValue::stencilClearValue() const
1288 \return the stencil clear value. In most cases this is 0.
1289 */
1290
1291/*!
1292 \fn void QRhiDepthStencilClearValue::setStencilClearValue(quint32 s)
1293 Sets the stencil clear value to \a s.
1294 */
1295
1296/*!
1297 \fn bool QRhiDepthStencilClearValue::operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1298
1299 \return \c true if the values in the two QRhiDepthStencilClearValue objects
1300 \a a and \a b are equal.
1301 */
1302
1303/*!
1304 \fn bool QRhiDepthStencilClearValue::operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1305
1306 \return \c false if the values in the two QRhiDepthStencilClearValue
1307 objects \a a and \a b are equal; otherwise returns \c true.
1308
1309*/
1310
1311/*!
1312 \fn size_t QRhiDepthStencilClearValue::qHash(const QRhiDepthStencilClearValue &key, size_t seed)
1313 \qhash{QRhiDepthStencilClearValue}
1314 */
1315
1316#ifndef QT_NO_DEBUG_STREAM
1317QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
1318{
1319 QDebugStateSaver saver(dbg);
1320 dbg.nospace() << "QRhiDepthStencilClearValue(depth-clear=" << v.depthClearValue()
1321 << " stencil-clear=" << v.stencilClearValue()
1322 << ')';
1323 return dbg;
1324}
1325#endif
1326
1327/*!
1328 \class QRhiViewport
1329 \inmodule QtGuiPrivate
1330 \inheaderfile rhi/qrhi.h
1331 \since 6.6
1332 \brief Specifies a viewport rectangle.
1333
1334 Used with QRhiCommandBuffer::setViewport().
1335
1336 QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
1337 bottom-left. Negative width or height are not allowed.
1338
1339 Typical usage is like the following:
1340
1341 \code
1342 const QSize outputSizeInPixels = swapchain->currentPixelSize();
1343 const QRhiViewport viewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height());
1344 cb->beginPass(swapchain->currentFrameRenderTarget(), Qt::black, { 1.0f, 0 });
1345 cb->setGraphicsPipeline(ps);
1346 cb->setViewport(viewport);
1347 // ...
1348 \endcode
1349
1350 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1351 for details.
1352
1353 \sa QRhiCommandBuffer::setViewport(), QRhi::clipSpaceCorrMatrix(), QRhiScissor
1354 */
1355
1356/*!
1357 \fn QRhiViewport::QRhiViewport() = default
1358
1359 Constructs a viewport description with an empty rectangle and a depth range
1360 of 0.0f - 1.0f.
1361
1362 \sa QRhi::clipSpaceCorrMatrix()
1363 */
1364
1365/*!
1366 Constructs a viewport description with the rectangle specified by \a x, \a
1367 y, \a w, \a h and the depth range \a minDepth and \a maxDepth.
1368
1369 \note \a x and \a y are assumed to be the bottom-left position. \a w and \a
1370 h should not be negative, the viewport will be ignored by
1371 QRhiCommandBuffer::setViewport() otherwise.
1372
1373 \sa QRhi::clipSpaceCorrMatrix()
1374 */
1375QRhiViewport::QRhiViewport(float x, float y, float w, float h, float minDepth, float maxDepth)
1376 : m_rect { { x, y, w, h } },
1377 m_minDepth(minDepth),
1378 m_maxDepth(maxDepth)
1379{
1380}
1381
1382/*!
1383 \fn std::array<float, 4> QRhiViewport::viewport() const
1384 \return the viewport x, y, width, and height.
1385 */
1386
1387/*!
1388 \fn void QRhiViewport::setViewport(float x, float y, float w, float h)
1389 Sets the viewport's position and size to \a x, \a y, \a w, and \a h.
1390
1391 \note Viewports are specified in a coordinate system that has its origin in
1392 the bottom-left.
1393 */
1394
1395/*!
1396 \fn float QRhiViewport::minDepth() const
1397 \return the minDepth value of the depth range of the viewport.
1398 */
1399
1400/*!
1401 \fn void QRhiViewport::setMinDepth(float minDepth)
1402 Sets the \a minDepth of the depth range of the viewport.
1403 By default this is set to 0.0f.
1404 */
1405
1406/*!
1407 \fn float QRhiViewport::maxDepth() const
1408 \return the maxDepth value of the depth range of the viewport.
1409 */
1410
1411/*!
1412 \fn void QRhiViewport::setMaxDepth(float maxDepth)
1413 Sets the \a maxDepth of the depth range of the viewport.
1414 By default this is set to 1.0f.
1415 */
1416
1417/*!
1418 \fn bool QRhiViewport::operator==(const QRhiViewport &a, const QRhiViewport &b) noexcept
1419
1420 \return \c true if the values in the two QRhiViewport objects
1421 \a a and \a b are equal.
1422 */
1423
1424/*!
1425 \fn bool QRhiViewport::operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept
1426
1427 \return \c false if the values in the two QRhiViewport
1428 objects \a a and \a b are equal; otherwise returns \c true.
1429*/
1430
1431/*!
1432 \fn size_t QRhiViewport::qHash(const QRhiViewport &key, size_t seed)
1433 \qhash{QRhiViewport}
1434 */
1435
1436#ifndef QT_NO_DEBUG_STREAM
1437QDebug operator<<(QDebug dbg, const QRhiViewport &v)
1438{
1439 QDebugStateSaver saver(dbg);
1440 const std::array<float, 4> r = v.viewport();
1441 dbg.nospace() << "QRhiViewport(bottom-left-x=" << r[0]
1442 << " bottom-left-y=" << r[1]
1443 << " width=" << r[2]
1444 << " height=" << r[3]
1445 << " minDepth=" << v.minDepth()
1446 << " maxDepth=" << v.maxDepth()
1447 << ')';
1448 return dbg;
1449}
1450#endif
1451
1452/*!
1453 \class QRhiScissor
1454 \inmodule QtGuiPrivate
1455 \inheaderfile rhi/qrhi.h
1456 \since 6.6
1457 \brief Specifies a scissor rectangle.
1458
1459 Used with QRhiCommandBuffer::setScissor(). Setting a scissor rectangle is
1460 only possible with a QRhiGraphicsPipeline that has
1461 QRhiGraphicsPipeline::UsesScissor set.
1462
1463 QRhi assumes OpenGL-style scissor coordinates, meaning x and y are
1464 bottom-left. Negative width or height are not allowed. However, apart from
1465 that, the flexible OpenGL semantics apply: negative x and y, partially out
1466 of bounds rectangles, etc. will be handled gracefully, clamping as
1467 appropriate. Therefore, any rendering logic targeting OpenGL can feed
1468 scissor rectangles into QRhiScissor as-is, without any adaptation.
1469
1470 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1471 for details.
1472
1473 \sa QRhiCommandBuffer::setScissor(), QRhiViewport
1474 */
1475
1476/*!
1477 \fn QRhiScissor::QRhiScissor() = default
1478
1479 Constructs an empty scissor.
1480 */
1481
1482/*!
1483 Constructs a scissor with the rectangle specified by \a x, \a y, \a w, and
1484 \a h.
1485
1486 \note \a x and \a y are assumed to be the bottom-left position. Negative \a w
1487 or \a h are not allowed, such scissor rectangles will be ignored by
1488 QRhiCommandBuffer. Other than that, the flexible OpenGL semantics apply:
1489 negative x and y, partially out of bounds rectangles, etc. will be handled
1490 gracefully, clamping as appropriate.
1491 */
1492QRhiScissor::QRhiScissor(int x, int y, int w, int h)
1493 : m_rect { { x, y, w, h } }
1494{
1495}
1496
1497/*!
1498 \fn std::array<int, 4> QRhiScissor::scissor() const
1499 \return the scissor position and size.
1500 */
1501
1502/*!
1503 \fn void QRhiScissor::setScissor(int x, int y, int w, int h)
1504 Sets the scissor position and size to \a x, \a y, \a w, \a h.
1505
1506 \note The position is always expected to be specified in a coordinate
1507 system that has its origin in the bottom-left corner, like OpenGL.
1508 */
1509
1510/*!
1511 \fn bool QRhiScissor::operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept
1512
1513 \return \c true if the values in the two QRhiScissor objects
1514 \a a and \a b are equal.
1515 */
1516
1517/*!
1518 \fn bool QRhiScissor::operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept
1519
1520 \return \c false if the values in the two QRhiScissor
1521 objects \a a and \a b are equal; otherwise returns \c true.
1522*/
1523
1524/*!
1525 \fn size_t QRhiScissor::qHash(const QRhiScissor &key, size_t seed)
1526 \qhash{QRhiScissor}
1527 */
1528
1529#ifndef QT_NO_DEBUG_STREAM
1530QDebug operator<<(QDebug dbg, const QRhiScissor &s)
1531{
1532 QDebugStateSaver saver(dbg);
1533 const std::array<int, 4> r = s.scissor();
1534 dbg.nospace() << "QRhiScissor(bottom-left-x=" << r[0]
1535 << " bottom-left-y=" << r[1]
1536 << " width=" << r[2]
1537 << " height=" << r[3]
1538 << ')';
1539 return dbg;
1540}
1541#endif
1542
1543/*!
1544 \class QRhiVertexInputBinding
1545 \inmodule QtGuiPrivate
1546 \inheaderfile rhi/qrhi.h
1547 \since 6.6
1548 \brief Describes a vertex input binding.
1549
1550 Specifies the stride (in bytes, must be a multiple of 4), the
1551 classification and optionally the instance step rate.
1552
1553 As an example, assume a vertex shader with the following inputs:
1554
1555 \badcode
1556 layout(location = 0) in vec4 position;
1557 layout(location = 1) in vec2 texcoord;
1558 \endcode
1559
1560 Now let's assume also that 3 component vertex positions \c{(x, y, z)} and 2
1561 component texture coordinates \c{(u, v)} are provided in a non-interleaved
1562 format in a buffer (or separate buffers even). Defining two bindings
1563 could then be done like this:
1564
1565 \code
1566 QRhiVertexInputLayout inputLayout;
1567 inputLayout.setBindings({
1568 { 3 * sizeof(float) },
1569 { 2 * sizeof(float) }
1570 });
1571 \endcode
1572
1573 Only the stride is interesting here since instancing is not used. The
1574 binding number is given by the index of the QRhiVertexInputBinding
1575 element in the bindings vector of the QRhiVertexInputLayout.
1576
1577 Once a graphics pipeline with this vertex input layout is bound, the vertex
1578 inputs could be set up like the following for drawing a cube with 36
1579 vertices, assuming we have a single buffer with first the positions and
1580 then the texture coordinates:
1581
1582 \code
1583 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1584 { cubeBuf, 0 },
1585 { cubeBuf, 36 * 3 * sizeof(float) }
1586 };
1587 cb->setVertexInput(0, 2, vbufBindings);
1588 \endcode
1589
1590 Note how the index defined by \c {startBinding + i}, where \c i is the
1591 index in the second argument of
1592 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}, matches the
1593 index of the corresponding entry in the \c bindings vector of the
1594 QRhiVertexInputLayout.
1595
1596 \note the stride must always be a multiple of 4.
1597
1598 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1599 for details.
1600
1601 \sa QRhiCommandBuffer::setVertexInput()
1602 */
1603
1604/*!
1605 \enum QRhiVertexInputBinding::Classification
1606 Describes the input data classification.
1607
1608 \value PerVertex Data is per-vertex
1609 \value PerInstance Data is per-instance
1610 */
1611
1612/*!
1613 \fn QRhiVertexInputBinding::QRhiVertexInputBinding() = default
1614
1615 Constructs a default vertex input binding description.
1616 */
1617
1618/*!
1619 Constructs a vertex input binding description with the specified \a stride,
1620 classification \a cls, and instance step rate \a stepRate.
1621
1622 \note \a stepRate other than 1 is only supported when
1623 QRhi::CustomInstanceStepRate is reported to be supported.
1624 */
1625QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cls, quint32 stepRate)
1626 : m_stride(stride),
1627 m_classification(cls),
1628 m_instanceStepRate(stepRate)
1629{
1630}
1631
1632/*!
1633 \fn quint32 QRhiVertexInputBinding::stride() const
1634 \return the stride in bytes.
1635 */
1636
1637/*!
1638 \fn void QRhiVertexInputBinding::setStride(quint32 s)
1639 Sets the stride to \a s.
1640 */
1641
1642/*!
1643 \fn QRhiVertexInputBinding::Classification QRhiVertexInputBinding::classification() const
1644 \return the input data classification.
1645 */
1646
1647/*!
1648 \fn void QRhiVertexInputBinding::setClassification(Classification c)
1649 Sets the input data classification \a c. By default this is set to PerVertex.
1650 */
1651
1652/*!
1653 \fn quint32 QRhiVertexInputBinding::instanceStepRate() const
1654 \return the instance step rate.
1655 */
1656
1657/*!
1658 \fn void QRhiVertexInputBinding::setInstanceStepRate(quint32 rate)
1659 Sets the instance step \a rate. By default this is set to 1.
1660 */
1661
1662/*!
1663 \fn bool QRhiVertexInputBinding::operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1664
1665 \return \c true if the values in the two QRhiVertexInputBinding objects
1666 \a a and \a b are equal.
1667 */
1668
1669/*!
1670 \fn bool QRhiVertexInputBinding::operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1671
1672 \return \c false if the values in the two QRhiVertexInputBinding
1673 objects \a a and \a b are equal; otherwise returns \c true.
1674*/
1675
1676/*!
1677 \fn size_t QRhiVertexInputBinding::qHash(const QRhiVertexInputBinding &key, size_t seed)
1678 \qhash{QRhiVertexInputBinding}
1679 */
1680
1681#ifndef QT_NO_DEBUG_STREAM
1682QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
1683{
1684 QDebugStateSaver saver(dbg);
1685 dbg.nospace() << "QRhiVertexInputBinding(stride=" << b.stride()
1686 << " cls=" << b.classification()
1687 << " step-rate=" << b.instanceStepRate()
1688 << ')';
1689 return dbg;
1690}
1691#endif
1692
1693/*!
1694 \class QRhiVertexInputAttribute
1695 \inmodule QtGuiPrivate
1696 \inheaderfile rhi/qrhi.h
1697 \since 6.6
1698 \brief Describes a single vertex input element.
1699
1700 The members specify the binding number, location, format, and offset for a
1701 single vertex input element.
1702
1703 \note For HLSL it is assumed that the vertex shader translated from SPIR-V
1704 uses
1705 \c{TEXCOORD<location>} as the semantic for each input. Hence no separate
1706 semantic name and index.
1707
1708 As an example, assume a vertex shader with the following inputs:
1709
1710 \badcode
1711 layout(location = 0) in vec4 position;
1712 layout(location = 1) in vec2 texcoord;
1713 \endcode
1714
1715 Now let's assume that we have 3 component vertex positions \c{(x, y, z)}
1716 and 2 component texture coordinates \c{(u, v)} are provided in a
1717 non-interleaved format in a buffer (or separate buffers even). Once two
1718 bindings are defined, the attributes could be specified as:
1719
1720 \code
1721 QRhiVertexInputLayout inputLayout;
1722 inputLayout.setBindings({
1723 { 3 * sizeof(float) },
1724 { 2 * sizeof(float) }
1725 });
1726 inputLayout.setAttributes({
1727 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1728 { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
1729 });
1730 \endcode
1731
1732 Once a graphics pipeline with this vertex input layout is bound, the vertex
1733 inputs could be set up like the following for drawing a cube with 36
1734 vertices, assuming we have a single buffer with first the positions and
1735 then the texture coordinates:
1736
1737 \code
1738 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1739 { cubeBuf, 0 },
1740 { cubeBuf, 36 * 3 * sizeof(float) }
1741 };
1742 cb->setVertexInput(0, 2, vbufBindings);
1743 \endcode
1744
1745 When working with interleaved data, there will typically be just one
1746 binding, with multiple attributes referring to that same buffer binding
1747 point:
1748
1749 \code
1750 QRhiVertexInputLayout inputLayout;
1751 inputLayout.setBindings({
1752 { 5 * sizeof(float) }
1753 });
1754 inputLayout.setAttributes({
1755 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1756 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
1757 });
1758 \endcode
1759
1760 and then:
1761
1762 \code
1763 const QRhiCommandBuffer::VertexInput vbufBinding(interleavedCubeBuf, 0);
1764 cb->setVertexInput(0, 1, &vbufBinding);
1765 \endcode
1766
1767 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1768 for details.
1769
1770 \sa QRhiCommandBuffer::setVertexInput()
1771 */
1772
1773/*!
1774 \enum QRhiVertexInputAttribute::Format
1775 Specifies the type of the element data.
1776
1777 \value Float4 Four component float vector
1778 \value Float3 Three component float vector
1779 \value Float2 Two component float vector
1780 \value Float Float
1781 \value UNormByte4 Four component normalized unsigned byte vector
1782 \value UNormByte2 Two component normalized unsigned byte vector
1783 \value UNormByte Normalized unsigned byte
1784 \value UInt4 Four component unsigned integer vector
1785 \value UInt3 Three component unsigned integer vector
1786 \value UInt2 Two component unsigned integer vector
1787 \value UInt Unsigned integer
1788 \value SInt4 Four component signed integer vector
1789 \value SInt3 Three component signed integer vector
1790 \value SInt2 Two component signed integer vector
1791 \value SInt Signed integer
1792 \value Half4 Four component half precision (16 bit) float vector
1793 \value Half3 Three component half precision (16 bit) float vector
1794 \value Half2 Two component half precision (16 bit) float vector
1795 \value Half Half precision (16 bit) float
1796 \value UShort4 Four component unsigned short (16 bit) integer vector
1797 \value UShort3 Three component unsigned short (16 bit) integer vector
1798 \value UShort2 Two component unsigned short (16 bit) integer vector
1799 \value UShort Unsigned short (16 bit) integer
1800 \value SShort4 Four component signed short (16 bit) integer vector
1801 \value SShort3 Three component signed short (16 bit) integer vector
1802 \value SShort2 Two component signed short (16 bit) integer vector
1803 \value SShort Signed short (16 bit) integer
1804
1805 \note Support for half precision floating point attributes is indicated at
1806 run time by the QRhi::Feature::HalfAttributes feature flag.
1807
1808 \note Direct3D 11/12 supports 16 bit input attributes, but does not support
1809 the Half3, UShort3 or SShort3 types. The D3D backends pass through Half3 as
1810 Half4, UShort3 as UShort4, and SShort3 as SShort4. To ensure cross platform
1811 compatibility, 16 bit inputs should be padded to 8 bytes.
1812 */
1813
1814/*!
1815 \fn QRhiVertexInputAttribute::QRhiVertexInputAttribute() = default
1816
1817 Constructs a default vertex input attribute description.
1818 */
1819
1820/*!
1821 Constructs a vertex input attribute description with the specified \a
1822 binding number, \a location, \a format, and \a offset.
1823
1824 \a matrixSlice should be -1 except when this attribute corresponds to a row
1825 or column of a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming
1826 4 consecutive vertex input locations), in which case it is the index of the
1827 row or column. \c{location - matrixSlice} must always be equal to the \c
1828 location for the first row or column of the unrolled matrix.
1829 */
1830QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset, int matrixSlice)
1831 : m_binding(binding),
1832 m_location(location),
1833 m_format(format),
1834 m_offset(offset),
1835 m_matrixSlice(matrixSlice)
1836{
1837}
1838
1839/*!
1840 \fn int QRhiVertexInputAttribute::binding() const
1841 \return the binding point index.
1842 */
1843
1844/*!
1845 \fn void QRhiVertexInputAttribute::setBinding(int b)
1846 Sets the binding point index to \a b.
1847 By default this is set to 0.
1848 */
1849
1850/*!
1851 \fn int QRhiVertexInputAttribute::location() const
1852 \return the location of the vertex input element.
1853 */
1854
1855/*!
1856 \fn void QRhiVertexInputAttribute::setLocation(int loc)
1857 Sets the location of the vertex input element to \a loc.
1858 By default this is set to 0.
1859 */
1860
1861/*!
1862 \fn QRhiVertexInputAttribute::Format QRhiVertexInputAttribute::format() const
1863 \return the format of the vertex input element.
1864 */
1865
1866/*!
1867 \fn void QRhiVertexInputAttribute::setFormat(Format f)
1868 Sets the format of the vertex input element to \a f.
1869 By default this is set to Float4.
1870 */
1871
1872/*!
1873 \fn quint32 QRhiVertexInputAttribute::offset() const
1874 \return the byte offset for the input element.
1875 */
1876
1877/*!
1878 \fn void QRhiVertexInputAttribute::setOffset(quint32 ofs)
1879 Sets the byte offset for the input element to \a ofs.
1880 */
1881
1882/*!
1883 \fn int QRhiVertexInputAttribute::matrixSlice() const
1884
1885 \return the matrix slice if the input element corresponds to a row or
1886 column of a matrix, or -1 if not relevant.
1887 */
1888
1889/*!
1890 \fn void QRhiVertexInputAttribute::setMatrixSlice(int slice)
1891
1892 Sets the matrix \a slice. By default this is set to -1, and should be set
1893 to a >= 0 value only when this attribute corresponds to a row or column of
1894 a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming 4
1895 consecutive vertex input locations), in which case it is the index of the
1896 row or column. \c{location - matrixSlice} must always be equal to the \c
1897 location for the first row or column of the unrolled matrix.
1898 */
1899
1900/*!
1901 \fn bool QRhiVertexInputAttribute::operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
1902
1903 \return \c true if the values in the two QRhiVertexInputAttribute objects
1904 \a a and \a b are equal.
1905 */
1906
1907/*!
1908 \fn bool QRhiVertexInputAttribute::operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
1909
1910 \return \c false if the values in the two QRhiVertexInputAttribute
1911 objects \a a and \a b are equal; otherwise returns \c true.
1912*/
1913
1914/*!
1915 \fn size_t QRhiVertexInputAttribute::qHash(const QRhiVertexInputAttribute &key, size_t seed)
1916 \qhash{QRhiVertexInputAttribute}
1917 */
1918
1919#ifndef QT_NO_DEBUG_STREAM
1920QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a)
1921{
1922 QDebugStateSaver saver(dbg);
1923 dbg.nospace() << "QRhiVertexInputAttribute(binding=" << a.binding()
1924 << " location=" << a.location()
1925 << " format=" << a.format()
1926 << " offset=" << a.offset()
1927 << ')';
1928 return dbg;
1929}
1930#endif
1931
1932QRhiVertexInputAttribute::Format QRhiImplementation::shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const
1933{
1934 switch (type) {
1935 case QShaderDescription::Vec4:
1936 return QRhiVertexInputAttribute::Float4;
1937 case QShaderDescription::Vec3:
1938 return QRhiVertexInputAttribute::Float3;
1939 case QShaderDescription::Vec2:
1940 return QRhiVertexInputAttribute::Float2;
1941 case QShaderDescription::Float:
1942 return QRhiVertexInputAttribute::Float;
1943
1944 case QShaderDescription::Int4:
1945 return QRhiVertexInputAttribute::SInt4;
1946 case QShaderDescription::Int3:
1947 return QRhiVertexInputAttribute::SInt3;
1948 case QShaderDescription::Int2:
1949 return QRhiVertexInputAttribute::SInt2;
1950 case QShaderDescription::Int:
1951 return QRhiVertexInputAttribute::SInt;
1952
1953 case QShaderDescription::Uint4:
1954 return QRhiVertexInputAttribute::UInt4;
1955 case QShaderDescription::Uint3:
1956 return QRhiVertexInputAttribute::UInt3;
1957 case QShaderDescription::Uint2:
1958 return QRhiVertexInputAttribute::UInt2;
1959 case QShaderDescription::Uint:
1960 return QRhiVertexInputAttribute::UInt;
1961
1962 case QShaderDescription::Half4:
1963 return QRhiVertexInputAttribute::Half4;
1964 case QShaderDescription::Half3:
1965 return QRhiVertexInputAttribute::Half3;
1966 case QShaderDescription::Half2:
1967 return QRhiVertexInputAttribute::Half2;
1968 case QShaderDescription::Half:
1969 return QRhiVertexInputAttribute::Half;
1970
1971 default:
1972 Q_UNREACHABLE_RETURN(QRhiVertexInputAttribute::Float);
1973 }
1974}
1975
1976quint32 QRhiImplementation::byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const
1977{
1978 switch (format) {
1979 case QRhiVertexInputAttribute::Float4:
1980 return 4 * sizeof(float);
1981 case QRhiVertexInputAttribute::Float3:
1982 return 4 * sizeof(float); // vec3 still takes 16 bytes
1983 case QRhiVertexInputAttribute::Float2:
1984 return 2 * sizeof(float);
1985 case QRhiVertexInputAttribute::Float:
1986 return sizeof(float);
1987
1988 case QRhiVertexInputAttribute::UNormByte4:
1989 return 4 * sizeof(quint8);
1990 case QRhiVertexInputAttribute::UNormByte2:
1991 return 2 * sizeof(quint8);
1992 case QRhiVertexInputAttribute::UNormByte:
1993 return sizeof(quint8);
1994
1995 case QRhiVertexInputAttribute::UInt4:
1996 return 4 * sizeof(quint32);
1997 case QRhiVertexInputAttribute::UInt3:
1998 return 4 * sizeof(quint32); // ivec3 still takes 16 bytes
1999 case QRhiVertexInputAttribute::UInt2:
2000 return 2 * sizeof(quint32);
2001 case QRhiVertexInputAttribute::UInt:
2002 return sizeof(quint32);
2003
2004 case QRhiVertexInputAttribute::SInt4:
2005 return 4 * sizeof(qint32);
2006 case QRhiVertexInputAttribute::SInt3:
2007 return 4 * sizeof(qint32); // uvec3 still takes 16 bytes
2008 case QRhiVertexInputAttribute::SInt2:
2009 return 2 * sizeof(qint32);
2010 case QRhiVertexInputAttribute::SInt:
2011 return sizeof(qint32);
2012
2013 case QRhiVertexInputAttribute::Half4:
2014 return 4 * sizeof(qfloat16);
2015 case QRhiVertexInputAttribute::Half3:
2016 return 4 * sizeof(qfloat16); // half3 still takes 8 bytes
2017 case QRhiVertexInputAttribute::Half2:
2018 return 2 * sizeof(qfloat16);
2019 case QRhiVertexInputAttribute::Half:
2020 return sizeof(qfloat16);
2021
2022 case QRhiVertexInputAttribute::UShort4:
2023 return 4 * sizeof(quint16);
2024 case QRhiVertexInputAttribute::UShort3:
2025 return 4 * sizeof(quint16); // ivec3 still takes 8 bytes
2026 case QRhiVertexInputAttribute::UShort2:
2027 return 2 * sizeof(quint16);
2028 case QRhiVertexInputAttribute::UShort:
2029 return sizeof(quint16);
2030
2031 case QRhiVertexInputAttribute::SShort4:
2032 return 4 * sizeof(qint16);
2033 case QRhiVertexInputAttribute::SShort3:
2034 return 4 * sizeof(qint16); // uvec3 still takes 8 bytes
2035 case QRhiVertexInputAttribute::SShort2:
2036 return 2 * sizeof(qint16);
2037 case QRhiVertexInputAttribute::SShort:
2038 return sizeof(qint16);
2039
2040 default:
2041 Q_UNREACHABLE_RETURN(1);
2042 }
2043}
2044
2045/*!
2046 \class QRhiVertexInputLayout
2047 \inmodule QtGuiPrivate
2048 \inheaderfile rhi/qrhi.h
2049 \since 6.6
2050 \brief Describes the layout of vertex inputs consumed by a vertex shader.
2051
2052 The vertex input layout is defined by the collections of
2053 QRhiVertexInputBinding and QRhiVertexInputAttribute.
2054
2055 As an example, let's assume that we have a single buffer with 3 component
2056 vertex positions and 2 component UV coordinates interleaved (\c x, \c y, \c
2057 z, \c u, \c v), that the position and UV are expected at input locations 0
2058 and 1 by the vertex shader, and that the vertex buffer will be bound at
2059 binding point 0 using
2060 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()} later on:
2061
2062 \code
2063 QRhiVertexInputLayout inputLayout;
2064 inputLayout.setBindings({
2065 { 5 * sizeof(float) }
2066 });
2067 inputLayout.setAttributes({
2068 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
2069 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
2070 });
2071 \endcode
2072
2073 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2074 for details.
2075 */
2076
2077/*!
2078 \fn QRhiVertexInputLayout::QRhiVertexInputLayout() = default
2079
2080 Constructs an empty vertex input layout description.
2081 */
2082
2083/*!
2084 \fn void QRhiVertexInputLayout::setBindings(std::initializer_list<QRhiVertexInputBinding> list)
2085 Sets the bindings from the specified \a list.
2086 */
2087
2088/*!
2089 \fn template<typename InputIterator> void QRhiVertexInputLayout::setBindings(InputIterator first, InputIterator last)
2090 Sets the bindings using the iterators \a first and \a last.
2091 */
2092
2093/*!
2094 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cbeginBindings() const
2095 \return a const iterator pointing to the first item in the binding list.
2096 */
2097
2098/*!
2099 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cendBindings() const
2100 \return a const iterator pointing just after the last item in the binding list.
2101 */
2102
2103/*!
2104 \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::bindingAt(qsizetype index) const
2105 \return the binding at the given \a index.
2106 */
2107
2108/*!
2109 \fn qsizetype QRhiVertexInputLayout::bindingCount() const
2110 \return the number of bindings.
2111 */
2112
2113/*!
2114 \fn void QRhiVertexInputLayout::setAttributes(std::initializer_list<QRhiVertexInputAttribute> list)
2115 Sets the attributes from the specified \a list.
2116 */
2117
2118/*!
2119 \fn template<typename InputIterator> void QRhiVertexInputLayout::setAttributes(InputIterator first, InputIterator last)
2120 Sets the attributes using the iterators \a first and \a last.
2121 */
2122
2123/*!
2124 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cbeginAttributes() const
2125 \return a const iterator pointing to the first item in the attribute list.
2126 */
2127
2128/*!
2129 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cendAttributes() const
2130 \return a const iterator pointing just after the last item in the attribute list.
2131 */
2132
2133/*!
2134 \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::attributeAt(qsizetype index) const
2135 \return the attribute at the given \a index.
2136 */
2137
2138/*!
2139 \fn qsizetype QRhiVertexInputLayout::attributeCount() const
2140 \return the number of attributes.
2141 */
2142
2143/*!
2144 \fn bool QRhiVertexInputLayout::operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2145
2146 \return \c true if the values in the two QRhiVertexInputLayout objects
2147 \a a and \a b are equal.
2148 */
2149
2150/*!
2151 \fn bool QRhiVertexInputLayout::operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2152
2153 \return \c false if the values in the two QRhiVertexInputLayout
2154 objects \a a and \a b are equal; otherwise returns \c true.
2155*/
2156
2157/*!
2158 \fn size_t QRhiVertexInputLayout::qHash(const QRhiVertexInputLayout &key, size_t seed)
2159 \qhash{QRhiVertexInputLayout}
2160 */
2161
2162#ifndef QT_NO_DEBUG_STREAM
2163QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
2164{
2165 QDebugStateSaver saver(dbg);
2166 dbg.nospace() << "QRhiVertexInputLayout(bindings=" << v.m_bindings
2167 << " attributes=" << v.m_attributes
2168 << ')';
2169 return dbg;
2170}
2171#endif
2172
2173/*!
2174 \class QRhiShaderStage
2175 \inmodule QtGuiPrivate
2176 \inheaderfile rhi/qrhi.h
2177 \since 6.6
2178 \brief Specifies the type and the shader code for a shader stage in the pipeline.
2179
2180 When setting up a QRhiGraphicsPipeline, a collection of shader stages are
2181 specified. The QRhiShaderStage contains a QShader and some associated
2182 metadata, such as the graphics pipeline stage, and the
2183 \l{QShader::Variant}{shader variant} to select. There is no need to specify
2184 the shader language or version because the QRhi backend in use at runtime
2185 will take care of choosing the appropriate shader version from the
2186 collection within the QShader.
2187
2188 The typical usage is in combination with
2189 QRhiGraphicsPipeline::setShaderStages(), shown here with a simple approach
2190 to load the QShader from \c{.qsb} files generated offline or at build time:
2191
2192 \code
2193 QShader getShader(const QString &name)
2194 {
2195 QFile f(name);
2196 return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
2197 }
2198
2199 QShader vs = getShader("material.vert.qsb");
2200 QShader fs = getShader("material.frag.qsb");
2201 pipeline->setShaderStages({
2202 { QRhiShaderStage::Vertex, vs },
2203 { QRhiShaderStage::Fragment, fs }
2204 });
2205 \endcode
2206
2207 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2208 for details.
2209 */
2210
2211/*!
2212 \enum QRhiShaderStage::Type
2213 Specifies the type of the shader stage.
2214
2215 \value Vertex Vertex stage
2216
2217 \value TessellationControl Tessellation control (hull shader) stage. Must
2218 be used only when the QRhi::Tessellation feature is supported.
2219
2220 \value TessellationEvaluation Tessellation evaluation (domain shader)
2221 stage. Must be used only when the QRhi::Tessellation feature is supported.
2222
2223 \value Fragment Fragment (pixel shader) stage
2224
2225 \value Compute Compute stage. Must be used only when the QRhi::Compute
2226 feature is supported.
2227
2228 \value Geometry Geometry stage. Must be used only when the
2229 QRhi::GeometryShader feature is supported.
2230 */
2231
2232/*!
2233 \fn QRhiShaderStage::QRhiShaderStage() = default
2234
2235 Constructs a shader stage description for the vertex stage with an empty
2236 QShader.
2237 */
2238
2239/*!
2240 \fn QRhiShaderStage::Type QRhiShaderStage::type() const
2241 \return the type of the stage.
2242 */
2243
2244/*!
2245 \fn void QRhiShaderStage::setType(Type t)
2246
2247 Sets the type of the stage to \a t. Setters should rarely be needed in
2248 pratice. Most applications will likely use the QRhiShaderStage constructor
2249 in most cases.
2250 */
2251
2252/*!
2253 \fn QShader QRhiShaderStage::shader() const
2254 \return the QShader to be used for this stage in the graphics pipeline.
2255 */
2256
2257/*!
2258 \fn void QRhiShaderStage::setShader(const QShader &s)
2259 Sets the shader collection \a s.
2260 */
2261
2262/*!
2263 \fn QShader::Variant QRhiShaderStage::shaderVariant() const
2264 \return the requested shader variant.
2265 */
2266
2267/*!
2268 \fn void QRhiShaderStage::setShaderVariant(QShader::Variant v)
2269 Sets the requested shader variant \a v.
2270 */
2271
2272/*!
2273 Constructs a shader stage description with the \a type of the stage and the
2274 \a shader.
2275
2276 The shader variant \a v defaults to QShader::StandardShader. A
2277 QShader contains multiple source and binary versions of a shader.
2278 In addition, it can also contain variants of the shader with slightly
2279 modified code. \a v can then be used to select the desired variant.
2280 */
2281QRhiShaderStage::QRhiShaderStage(Type type, const QShader &shader, QShader::Variant v)
2282 : m_type(type),
2283 m_shader(shader),
2284 m_shaderVariant(v)
2285{
2286}
2287
2288/*!
2289 \fn bool QRhiShaderStage::operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2290
2291 \return \c true if the values in the two QRhiShaderStage objects
2292 \a a and \a b are equal.
2293 */
2294
2295/*!
2296 \fn bool QRhiShaderStage::operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2297
2298 \return \c false if the values in the two QRhiShaderStage
2299 objects \a a and \a b are equal; otherwise returns \c true.
2300*/
2301
2302/*!
2303 \fn size_t QRhiShaderStage::qHash(const QRhiShaderStage &key, size_t seed)
2304 \qhash{QRhiShaderStage}
2305 */
2306
2307#ifndef QT_NO_DEBUG_STREAM
2308QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
2309{
2310 QDebugStateSaver saver(dbg);
2311 dbg.nospace() << "QRhiShaderStage(type=" << s.type()
2312 << " shader=" << s.shader()
2313 << " variant=" << s.shaderVariant()
2314 << ')';
2315 return dbg;
2316}
2317#endif
2318
2319/*!
2320 \class QRhiColorAttachment
2321 \inmodule QtGuiPrivate
2322 \inheaderfile rhi/qrhi.h
2323 \since 6.6
2324 \brief Describes the a single color attachment of a render target.
2325
2326 A color attachment is either a QRhiTexture or a QRhiRenderBuffer. The
2327 former, i.e. when texture() is set, is used in most cases.
2328 QRhiColorAttachment is commonly used in combination with
2329 QRhiTextureRenderTargetDescription.
2330
2331 \note texture() and renderBuffer() cannot be both set (be non-null at the
2332 same time).
2333
2334 Setting renderBuffer instead is recommended only when multisampling is
2335 needed. Relying on QRhi::MultisampleRenderBuffer is a better choice than
2336 QRhi::MultisampleTexture in practice since the former is available in more
2337 run time configurations (e.g. when running on OpenGL ES 3.0 which has no
2338 support for multisample textures, but does support multisample
2339 renderbuffers).
2340
2341 When targeting a non-multisample texture, the layer() and level() indicate
2342 the targeted layer (face index \c{0-5} for cubemaps) and mip level. For 3D
2343 textures layer() specifies the slice (one 2D image within the 3D texture)
2344 to render to. For texture arrays layer() is the array index.
2345
2346 When texture() or renderBuffer() is multisample, resolveTexture() can be
2347 set optionally. When set, samples are resolved automatically into that
2348 (non-multisample) texture at the end of the render pass. When rendering
2349 into a multisample renderbuffers, this is the only way to get resolved,
2350 non-multisample content out of them. Multisample textures allow sampling in
2351 shaders so for them this is just one option.
2352
2353 \note when resolving is enabled, the multisample data may not be written
2354 out at all. This means that the multisample texture() must not be used
2355 afterwards with shaders for sampling when resolveTexture() is set.
2356
2357 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2358 for details.
2359
2360 \sa QRhiTextureRenderTargetDescription
2361 */
2362
2363/*!
2364 \fn QRhiColorAttachment::QRhiColorAttachment() = default
2365
2366 Constructs an empty color attachment description.
2367 */
2368
2369/*!
2370 Constructs a color attachment description that specifies \a texture as the
2371 associated color buffer.
2372 */
2373QRhiColorAttachment::QRhiColorAttachment(QRhiTexture *texture)
2374 : m_texture(texture)
2375{
2376}
2377
2378/*!
2379 Constructs a color attachment description that specifies \a renderBuffer as
2380 the associated color buffer.
2381 */
2382QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
2383 : m_renderBuffer(renderBuffer)
2384{
2385}
2386
2387/*!
2388 \fn QRhiTexture *QRhiColorAttachment::texture() const
2389
2390 \return the texture this attachment description references, or \nullptr if
2391 there is none.
2392 */
2393
2394/*!
2395 \fn void QRhiColorAttachment::setTexture(QRhiTexture *tex)
2396
2397 Sets the texture \a tex.
2398
2399 \note texture() and renderBuffer() cannot be both set (be non-null at the
2400 same time).
2401 */
2402
2403/*!
2404 \fn QRhiRenderBuffer *QRhiColorAttachment::renderBuffer() const
2405
2406 \return the renderbuffer this attachment description references, or
2407 \nullptr if there is none.
2408
2409 In practice associating a QRhiRenderBuffer with a QRhiColorAttachment makes
2410 the most sense when setting up multisample rendering via a multisample
2411 \l{QRhiRenderBuffer::Type}{color} renderbuffer that is then resolved into a
2412 non-multisample texture at the end of the render pass.
2413 */
2414
2415/*!
2416 \fn void QRhiColorAttachment::setRenderBuffer(QRhiRenderBuffer *rb)
2417
2418 Sets the renderbuffer \a rb.
2419
2420 \note texture() and renderBuffer() cannot be both set (be non-null at the
2421 same time).
2422 */
2423
2424/*!
2425 \fn int QRhiColorAttachment::layer() const
2426 \return the layer index (cubemap face or array layer). 0 by default.
2427 */
2428
2429/*!
2430 \fn void QRhiColorAttachment::setLayer(int layer)
2431 Sets the \a layer index.
2432 */
2433
2434/*!
2435 \fn int QRhiColorAttachment::level() const
2436 \return the mip level. 0 by default.
2437 */
2438
2439/*!
2440 \fn void QRhiColorAttachment::setLevel(int level)
2441 Sets the mip \a level.
2442 */
2443
2444/*!
2445 \fn QRhiTexture *QRhiColorAttachment::resolveTexture() const
2446
2447 \return the resolve texture this attachment description references, or
2448 \nullptr if there is none.
2449
2450 Setting a non-null resolve texture is applicable when the attachment
2451 references a multisample texture or renderbuffer. The QRhiTexture in the
2452 resolveTexture() is then a non-multisample 2D texture (or texture array)
2453 with the same size (but a sample count of 1). The multisample content is
2454 automatically resolved into this texture at the end of each render pass.
2455 */
2456
2457/*!
2458 \fn void QRhiColorAttachment::setResolveTexture(QRhiTexture *tex)
2459
2460 Sets the resolve texture \a tex.
2461
2462 \a tex is expected to be a 2D texture or a 2D texture array. In either
2463 case, resolving targets a single mip level of a single layer (array
2464 element) of \a tex. The mip level and array layer are specified by
2465 resolveLevel() and resolveLayer().
2466
2467 An exception is \l{setMultiViewCount()}{multiview}: when the color
2468 attachment is associated with a texture array and multiview is enabled, the
2469 resolve texture must also be a texture array with sufficient elements for
2470 all views. In this case all elements that correspond to views are resolved
2471 automatically; the behavior is similar to the following pseudo-code:
2472 \badcode
2473 for (i = 0; i < multiViewCount(); ++i)
2474 resolve texture's layer() + i into resolveTexture's resolveLayer() + i
2475 \endcode
2476
2477 Setting a non-multisample texture to resolve a multisample texture or
2478 renderbuffer automatically at the end of the render pass is often
2479 preferable to working with multisample textures (and not setting a resolve
2480 texture), because it avoids the need for writing dedicated fragment shaders
2481 that work exclusively with multisample textures (\c sampler2DMS, \c
2482 texelFetch, etc.), and rather allows using the same shader as one would if
2483 the attachment's texture was not multisampled to begin with. This comes at
2484 the expense of an additional resource (the non-multisample \a tex).
2485 */
2486
2487/*!
2488 \fn int QRhiColorAttachment::resolveLayer() const
2489 \return the currently set resolve texture layer. Defaults to 0.
2490 */
2491
2492/*!
2493 \fn void QRhiColorAttachment::setResolveLayer(int layer)
2494 Sets the resolve texture \a layer to use.
2495 */
2496
2497/*!
2498 \fn int QRhiColorAttachment::resolveLevel() const
2499 \return the currently set resolve texture mip level. Defaults to 0.
2500 */
2501
2502/*!
2503 \fn void QRhiColorAttachment::setResolveLevel(int level)
2504 Sets the resolve texture mip \a level to use.
2505 */
2506
2507/*!
2508 \fn int QRhiColorAttachment::multiViewCount() const
2509
2510 \return the currently set number of views. Defaults to 0 which indicates
2511 the render target with this color attachment is not going to be used with
2512 multiview rendering.
2513
2514 \since 6.7
2515 */
2516
2517/*!
2518 \fn void QRhiColorAttachment::setMultiViewCount(int count)
2519
2520 Sets the view \a count. Setting a value larger than 1 indicates that the
2521 render target with this color attachment is going to be used with multiview
2522 rendering. The default value is 0. Values smaller than 2 indicate no
2523 multiview rendering.
2524
2525 When \a count is set to \c 2 or greater, the color attachment must be
2526 associated with a 2D texture array. layer() and multiViewCount() together
2527 define the range of texture array elements that are targeted during
2528 multiview rendering.
2529
2530 For example, if \c layer is \c 0 and \c multiViewCount is \c 2, the texture
2531 array must have 2 (or more) elements, and the multiview rendering will
2532 target elements 0 and 1. The \c{gl_ViewIndex} variable in the shaders has a
2533 value of \c 0 or \c 1 then, where view \c 0 corresponds to the texture array
2534 element \c 0, and view \c 1 to the array element \c 1.
2535
2536 \note Setting a \a count larger than 1, using a texture array as texture(),
2537 and calling \l{QRhiCommandBuffer::beginPass()}{beginPass()} on a
2538 QRhiTextureRenderTarget with this color attachment implies multiview
2539 rendering for the entire render pass. multiViewCount() should not be set
2540 unless multiview rendering is wanted. Multiview cannot be used with texture
2541 types other than 2D texture arrays. (although 3D textures may work,
2542 depending on the graphics API and backend; applications are nonetheless
2543 advised not to rely on that and only use 2D texture arrays as the render
2544 targets of multiview rendering)
2545
2546 See
2547 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2548 for more details regarding multiview rendering. Do note that Qt requires
2549 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview2.txt}{GL_OVR_multiview2}
2550 as well, when running on OpenGL (ES).
2551
2552 Multiview rendering is available only when the
2553 \l{QRhi::MultiView}{MultiView} feature is reported as supported from
2554 \l{QRhi::isFeatureSupported()}{isFeatureSupported()}.
2555
2556 \note For portability, be aware of limitations that exist for multiview
2557 rendering with some of the graphics APIs. It is recommended that multiview
2558 render passes do not rely on any of the features that
2559 \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2560 declares as unsupported. The one exception is shader stage outputs other
2561 than \c{gl_Position} depending on \c{gl_ViewIndex}: that can be relied on
2562 (even with OpenGL) because QRhi never reports multiview as supported without
2563 \c{GL_OVR_multiview2} also being present.
2564
2565 \note Multiview rendering is not supported in combination with tessellation
2566 or geometry shaders, even though some implementations of some graphics APIs
2567 may allow this.
2568
2569 \since 6.7
2570 */
2571
2572/*!
2573 \class QRhiTextureRenderTargetDescription
2574 \inmodule QtGuiPrivate
2575 \inheaderfile rhi/qrhi.h
2576 \since 6.6
2577 \brief Describes the color and depth or depth/stencil attachments of a render target.
2578
2579 A texture render target has zero or more textures as color attachments,
2580 zero or one renderbuffer as combined depth/stencil buffer or zero or one
2581 texture as depth buffer.
2582
2583 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2584 non-null at the same time).
2585
2586 Let's look at some example usages in combination with
2587 QRhiTextureRenderTarget.
2588
2589 Due to the constructors, the targeting a texture (and no depth/stencil
2590 buffer) is simple:
2591
2592 \code
2593 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256), 1, QRhiTexture::RenderTarget);
2594 texture->create();
2595 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture }));
2596 \endcode
2597
2598 The following creates a texture render target that is set up to target mip
2599 level #2 of a texture:
2600
2601 \code
2602 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget | QRhiTexture::MipMapped);
2603 texture->create();
2604 QRhiColorAttachment colorAtt(texture);
2605 colorAtt.setLevel(2);
2606 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt });
2607 \endcode
2608
2609 Another example, this time to render into a depth texture:
2610
2611 \code
2612 QRhiTexture *shadowMap = rhi->newTexture(QRhiTexture::D32F, QSize(1024, 1024), 1, QRhiTexture::RenderTarget);
2613 shadowMap->create();
2614 QRhiTextureRenderTargetDescription rtDesc;
2615 rtDesc.setDepthTexture(shadowMap);
2616 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2617 \endcode
2618
2619 A very common case, having a texture as the color attachment and a
2620 renderbuffer as depth/stencil to enable depth testing:
2621
2622 \code
2623 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2624 texture->create();
2625 QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512));
2626 depthStencil->create();
2627 QRhiTextureRenderTargetDescription rtDesc({ texture }, depthStencil);
2628 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2629 \endcode
2630
2631 Finally, to enable multisample rendering in a portable manner (so also
2632 supporting OpenGL ES 3.0), using a QRhiRenderBuffer as the (multisample)
2633 color buffer and then resolving into a regular (non-multisample) 2D
2634 texture. To enable depth testing, a depth-stencil buffer, which also must
2635 use the same sample count, is used as well:
2636
2637 \code
2638 QRhiRenderBuffer *colorBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4); // 4x MSAA
2639 colorBuffer->create();
2640 QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512), 4);
2641 depthStencil->create();
2642 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2643 texture->create();
2644 QRhiColorAttachment colorAtt(colorBuffer);
2645 colorAtt.setResolveTexture(texture);
2646 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt, depthStencil });
2647 \endcode
2648
2649 \note when multisample resolving is enabled, the multisample data may not be
2650 written out at all. This means that the multisample texture in a color
2651 attachment must not be used afterwards with shaders for sampling (or other
2652 purposes) whenever a resolve texture is set, since the multisample color
2653 buffer is merely an intermediate storage then that gets no data written back
2654 on some GPU architectures at all. See
2655 \l{QRhiTextureRenderTarget::Flag}{PreserveColorContents} for more details.
2656
2657 \note When using setDepthTexture(), not setDepthStencilBuffer(), and the
2658 depth (stencil) data is not of interest afterwards, set the
2659 DoNotStoreDepthStencilContents flag on the QRhiTextureRenderTarget. This
2660 allows indicating to the underlying 3D API that the depth/stencil data can
2661 be discarded, leading potentially to better performance with tiled GPU
2662 architectures. When the depth-stencil buffer is a QRhiRenderBuffer (and also
2663 for the multisample color texture, see previous note) this is implicit, but
2664 with a depth (stencil) QRhiTexture the intention needs to be declared
2665 explicitly. By default QRhi assumes that the data is of interest (e.g., the
2666 depth texture is sampled in a shader afterwards).
2667
2668 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2669 for details.
2670
2671 \sa QRhiColorAttachment, QRhiTextureRenderTarget
2672 */
2673
2674/*!
2675 \fn QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription() = default
2676
2677 Constructs an empty texture render target description.
2678 */
2679
2680/*!
2681 Constructs a texture render target description with one attachment
2682 described by \a colorAttachment.
2683 */
2684QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment)
2685{
2686 m_colorAttachments.append(colorAttachment);
2687}
2688
2689/*!
2690 Constructs a texture render target description with two attachments, a
2691 color attachment described by \a colorAttachment, and a depth/stencil
2692 attachment with \a depthStencilBuffer.
2693 */
2694QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2695 QRhiRenderBuffer *depthStencilBuffer)
2696 : m_depthStencilBuffer(depthStencilBuffer)
2697{
2698 m_colorAttachments.append(colorAttachment);
2699}
2700
2701/*!
2702 Constructs a texture render target description with two attachments, a
2703 color attachment described by \a colorAttachment, and a depth attachment
2704 with \a depthTexture.
2705
2706 \note \a depthTexture must have a suitable format, such as QRhiTexture::D16
2707 or QRhiTexture::D32F.
2708 */
2709QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2710 QRhiTexture *depthTexture)
2711 : m_depthTexture(depthTexture)
2712{
2713 m_colorAttachments.append(colorAttachment);
2714}
2715
2716/*!
2717 \fn void QRhiTextureRenderTargetDescription::setColorAttachments(std::initializer_list<QRhiColorAttachment> list)
2718 Sets the \a list of color attachments.
2719 */
2720
2721/*!
2722 \fn template<typename InputIterator> void QRhiTextureRenderTargetDescription::setColorAttachments(InputIterator first, InputIterator last)
2723 Sets the list of color attachments via the iterators \a first and \a last.
2724 */
2725
2726/*!
2727 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cbeginColorAttachments() const
2728 \return a const iterator pointing to the first item in the attachment list.
2729 */
2730
2731/*!
2732 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cendColorAttachments() const
2733 \return a const iterator pointing just after the last item in the attachment list.
2734 */
2735
2736/*!
2737 \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::colorAttachmentAt(qsizetype index) const
2738 \return the color attachment at the specified \a index.
2739 */
2740
2741/*!
2742 \fn qsizetype QRhiTextureRenderTargetDescription::colorAttachmentCount() const
2743 \return the number of currently set color attachments.
2744 */
2745
2746/*!
2747 \fn QRhiRenderBuffer *QRhiTextureRenderTargetDescription::depthStencilBuffer() const
2748 \return the renderbuffer used as depth-stencil buffer, or \nullptr if none was set.
2749 */
2750
2751/*!
2752 \fn void QRhiTextureRenderTargetDescription::setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer)
2753
2754 Sets the \a renderBuffer for depth-stencil. Not mandatory, e.g. when no
2755 depth test/write or stencil-related features are used within any graphics
2756 pipelines in any of the render passes for this render target, it can be
2757 left set to \nullptr.
2758
2759 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2760 non-null at the same time).
2761
2762 Using a QRhiRenderBuffer over a 2D QRhiTexture as the depth or
2763 depth/stencil buffer is very common, and is the recommended approach for
2764 applications. Using a QRhiTexture, and so setDepthTexture() becomes
2765 relevant if the depth data is meant to be accessed (e.g. sampled in a
2766 shader) afterwards, or when
2767 \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering} is
2768 involved (because then the depth texture must be a texture array).
2769
2770 \sa setDepthTexture()
2771 */
2772
2773/*!
2774 \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthTexture() const
2775 \return the currently referenced depth texture, or \nullptr if none was set.
2776 */
2777
2778/*!
2779 \fn void QRhiTextureRenderTargetDescription::setDepthTexture(QRhiTexture *texture)
2780
2781 Sets the \a texture for depth-stencil. This is an alternative to
2782 setDepthStencilBuffer(), where instead of a QRhiRenderBuffer a QRhiTexture
2783 with a suitable type (e.g., QRhiTexture::D32F) is provided.
2784
2785 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2786 non-null at the same time).
2787
2788 \a texture can either be a 2D texture or a 2D texture array (when texture
2789 arrays are supported). Specifying a texture array is relevant in particular
2790 with
2791 \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering}.
2792
2793 \note If \a texture is a format with a stencil component, such as
2794 \l QRhiTexture::D24S8, it will serve as the stencil buffer as well.
2795
2796 \sa setDepthStencilBuffer()
2797 */
2798
2799/*!
2800 \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthResolveTexture() const
2801
2802 \return the texture to which a multisample depth (or depth-stencil) texture
2803 (or texture array) is resolved to. \nullptr if there is none, which is the
2804 most common case.
2805
2806 \since 6.8
2807 \sa QRhiColorAttachment::resolveTexture(), depthTexture()
2808 */
2809
2810/*!
2811 \fn void QRhiTextureRenderTargetDescription::setDepthResolveTexture(QRhiTexture *tex)
2812
2813 Sets the depth (or depth-stencil) resolve texture \a tex.
2814
2815 \a tex is expected to be a 2D texture or a 2D texture array with a format
2816 matching the texture set via setDepthTexture().
2817
2818 \note Resolving depth (or depth-stencil) data is only functional when the
2819 \l QRhi::ResolveDepthStencil feature is reported as supported at run time.
2820 Support for depth-stencil resolve is not universally available among the
2821 graphics APIs. Designs assuming unconditional availability of depth-stencil
2822 resolve are therefore non-portable, and should be avoided.
2823
2824 \note As an additional limitation for OpenGL ES in particular, setting a
2825 depth resolve texture may only be functional in combination with
2826 setDepthTexture(), not with setDepthStencilBuffer().
2827
2828 \since 6.8
2829 \sa QRhiColorAttachment::setResolveTexture(), setDepthTexture()
2830 */
2831
2832/*!
2833 \fn QRhiShadingRateMap *QRhiTextureRenderTargetDescription::shadingRateMap() const
2834 \return the currently set QRhiShadingRateMap. By default this is \nullptr.
2835 \since 6.9
2836 */
2837
2838/*!
2839 \fn void QRhiTextureRenderTargetDescription::setShadingRateMap(QRhiShadingRateMap *map)
2840
2841 Associates with the specified QRhiShadingRateMap \a map. This is functional
2842 only when the \l QRhi::VariableRateShadingMap feature is reported as
2843 supported.
2844
2845 When QRhiCommandBuffer::setShadingRate() is also called, the higher of two
2846 the shading rates are used for each tile. There is currently no control
2847 offered over the combiner behavior.
2848
2849 \note When the render target had already been built (create() was called
2850 successfully), setting a shading rate map implies that a different, new
2851 QRhiRenderPassDescriptor is needed and thus a rebuild is needed. Call
2852 setRenderPassDescriptor() again (outside of a render pass) and then rebuild
2853 by calling create(). This has other rolling consequences as well, for
2854 example for graphics pipelines: those also need to be associated with the
2855 new QRhiRenderPassDescriptor and then rebuilt. See \l
2856 QRhiRenderPassDescriptor::serializedFormat() for some suggestions on how to
2857 deal with this. Remember to set the QRhiGraphicsPipeline::UsesShadingRate
2858 flag as well.
2859
2860 \since 6.9
2861 */
2862
2863/*!
2864 \class QRhiTextureSubresourceUploadDescription
2865 \inmodule QtGuiPrivate
2866 \inheaderfile rhi/qrhi.h
2867 \since 6.6
2868 \brief Describes the source for one mip level in a layer in a texture upload operation.
2869
2870 The source content is specified either as a QImage or as a raw blob. The
2871 former is only allowed for uncompressed textures with a format that can be
2872 mapped to QImage, while the latter is supported for all formats, including
2873 floating point and compressed.
2874
2875 \note image() and data() cannot be both set at the same time.
2876
2877 destinationTopLeft() specifies the top-left corner of the target
2878 rectangle. Defaults to (0, 0).
2879
2880 An empty sourceSize() (the default) indicates that size is assumed to be
2881 the size of the subresource. With QImage-based uploads this implies that
2882 the size of the source image() must match the subresource. When providing
2883 raw data instead, sufficient number of bytes must be provided in data().
2884
2885 sourceTopLeft() is supported only for QImage-based uploads, and specifies
2886 the top-left corner of the source rectangle.
2887
2888 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
2889 internally, depending on the format and the backend.
2890
2891 When providing raw data, and the stride is not specified via
2892 setDataStride(), the stride (row pitch, row length in bytes) of the
2893 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
2894 the number of bytes used for one pixel, and there must be no additional
2895 padding between rows. There is no row start alignment requirement.
2896
2897 When there is unused data at the end of each row in the input raw data,
2898 call setDataStride() with the total number of bytes per row. The stride
2899 must always be a multiple of the number of bytes for one pixel. The row
2900 stride is only applicable to image data for textures with an uncompressed
2901 format.
2902
2903 \note The format of the source data must be compatible with the texture
2904 format. With many graphics APIs the data is copied as-is into a staging
2905 buffer, there is no intermediate format conversion provided by QRhi. This
2906 applies to floating point formats as well, with, for example, RGBA16F
2907 requiring half floats in the source data.
2908
2909 \note Setting the stride via setDataStride() is only functional when
2910 QRhi::ImageDataStride is reported as
2911 \l{QRhi::isFeatureSupported()}{supported}. In practice this can be expected
2912 to be supported everywhere except for OpenGL ES 2.0.
2913
2914 \note When a QImage is given, the stride returned from
2915 QImage::bytesPerLine() is taken into account automatically.
2916
2917 \warning When a QImage is given and the QImage does not own the underlying
2918 pixel data, it is up to the caller to ensure that the associated data stays
2919 valid until the end of the frame. (just submitting the resource update batch
2920 is not sufficient, the data must stay valid until QRhi::endFrame() is called
2921 in order to be portable across all backends) If this cannot be ensured, the
2922 caller is strongly encouraged to call QImage::detach() on the image before
2923 passing it to uploadTexture().
2924
2925 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2926 for details.
2927
2928 \sa QRhiTextureUploadDescription
2929 */
2930
2931/*!
2932 \fn QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription() = default
2933
2934 Constructs an empty subresource description.
2935
2936 \note an empty QRhiTextureSubresourceUploadDescription is not useful on its
2937 own and should not be submitted to a QRhiTextureUploadEntry. At minimum
2938 image or data must be set first.
2939 */
2940
2941/*!
2942 Constructs a mip level description with a \a image.
2943
2944 The \l{QImage::size()}{size} of \a image must match the size of the mip
2945 level. For level 0 that is the \l{QRhiTexture::pixelSize()}{texture size}.
2946
2947 The bit depth of \a image must be compatible with the
2948 \l{QRhiTexture::Format}{texture format}.
2949
2950 To describe a partial upload, call setSourceSize(), setSourceTopLeft(), or
2951 setDestinationTopLeft() afterwards.
2952 */
2953QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QImage &image)
2954 : m_image(image)
2955{
2956}
2957
2958/*!
2959 Constructs a mip level description with the image data is specified by \a
2960 data and \a size. This is suitable for floating point and compressed
2961 formats as well.
2962
2963 \a data can safely be destroyed or changed once this function returns.
2964 */
2965QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const void *data, quint32 size)
2966 : m_data(reinterpret_cast<const char *>(data), size)
2967{
2968}
2969
2970/*!
2971 Constructs a mip level description with the image data specified by \a
2972 data. This is suitable for floating point and compressed formats as well.
2973 */
2974QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QByteArray &data)
2975 : m_data(data)
2976{
2977}
2978
2979/*!
2980 \fn QImage QRhiTextureSubresourceUploadDescription::image() const
2981 \return the currently set QImage.
2982 */
2983
2984/*!
2985 \fn void QRhiTextureSubresourceUploadDescription::setImage(const QImage &image)
2986
2987 Sets \a image.
2988 Upon textures loading, the image data will be read as is, with no formats conversions.
2989
2990 \note image() and data() cannot be both set at the same time.
2991 */
2992
2993/*!
2994 \fn QByteArray QRhiTextureSubresourceUploadDescription::data() const
2995 \return the currently set raw pixel data.
2996 */
2997
2998/*!
2999 \fn void QRhiTextureSubresourceUploadDescription::setData(const QByteArray &data)
3000
3001 Sets \a data.
3002
3003 \note image() and data() cannot be both set at the same time.
3004 */
3005
3006/*!
3007 \fn quint32 QRhiTextureSubresourceUploadDescription::dataStride() const
3008 \return the currently set data stride.
3009 */
3010
3011/*!
3012 \fn void QRhiTextureSubresourceUploadDescription::setDataStride(quint32 stride)
3013
3014 Sets the data \a stride in bytes. By default this is 0 and not always
3015 relevant. When providing raw data(), and the stride is not specified via
3016 setDataStride(), the stride (row pitch, row length in bytes) of the
3017 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
3018 the number of bytes used for one pixel, and there must be no additional
3019 padding between rows. Otherwise, if there is additional space between the
3020 lines, set a non-zero \a stride. All this is applicable only when raw image
3021 data is provided, and is not necessary when working QImage since that has
3022 its own \l{QImage::bytesPerLine()}{stride} value.
3023
3024 \note Setting the stride via setDataStride() is only functional when
3025 QRhi::ImageDataStride is reported as
3026 \l{QRhi::isFeatureSupported()}{supported}.
3027
3028 \note When a QImage is given, the stride returned from
3029 QImage::bytesPerLine() is taken into account automatically and therefore
3030 there is no need to set the data stride manually.
3031 */
3032
3033/*!
3034 \fn QPoint QRhiTextureSubresourceUploadDescription::destinationTopLeft() const
3035 \return the currently set destination top-left position. Defaults to (0, 0).
3036 */
3037
3038/*!
3039 \fn void QRhiTextureSubresourceUploadDescription::setDestinationTopLeft(const QPoint &p)
3040 Sets the destination top-left position \a p.
3041
3042 \note In the most common case of sourcing the image data from a QImage, Qt
3043 performs clamping of invalid texture upload sizes when the destination
3044 position + the source size exceeds the size of the targeted texture
3045 subresource (i.e, the size at the given mip level). There is also a
3046 qWarning() message printed on the debug output in this case. This is done in
3047 order to avoid confusion when the underlying 3D APIs crash and lead to GPU
3048 device removals at a later point when submitting the commands. Regardless,
3049 developers are encouraged to always validate applications by running with the
3050 Vulkan, D3D12, or Metal validation/debug layers enabled, since those offer a
3051 much wider range of checks on API usage.
3052 */
3053
3054/*!
3055 \fn QSize QRhiTextureSubresourceUploadDescription::sourceSize() const
3056
3057 \return the source size in pixels. Defaults to a default-constructed QSize,
3058 which indicates the entire subresource.
3059 */
3060
3061/*!
3062 \fn void QRhiTextureSubresourceUploadDescription::setSourceSize(const QSize &size)
3063
3064 Sets the source \a size in pixels.
3065
3066 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3067 internally, depending on the format and the backend.
3068 */
3069
3070/*!
3071 \fn QPoint QRhiTextureSubresourceUploadDescription::sourceTopLeft() const
3072 \return the currently set source top-left position. Defaults to (0, 0).
3073 */
3074
3075/*!
3076 \fn void QRhiTextureSubresourceUploadDescription::setSourceTopLeft(const QPoint &p)
3077
3078 Sets the source top-left position \a p.
3079
3080 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3081 internally, depending on the format and the backend.
3082 */
3083
3084/*!
3085 \class QRhiTextureUploadEntry
3086 \inmodule QtGuiPrivate
3087 \inheaderfile rhi/qrhi.h
3088 \since 6.6
3089
3090 \brief Describes one layer (face for cubemaps, slice for 3D textures,
3091 element for texture arrays) in a texture upload operation.
3092
3093 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3094 for details.
3095 */
3096
3097/*!
3098 \fn QRhiTextureUploadEntry::QRhiTextureUploadEntry()
3099
3100 Constructs an empty QRhiTextureUploadEntry targeting layer 0 and level 0.
3101
3102 \note an empty QRhiTextureUploadEntry should not be submitted without
3103 setting a QRhiTextureSubresourceUploadDescription via setDescription()
3104 first.
3105 */
3106
3107/*!
3108 Constructs a QRhiTextureUploadEntry targeting the given \a layer and mip
3109 \a level, with the subresource contents described by \a desc.
3110 */
3111QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
3112 const QRhiTextureSubresourceUploadDescription &desc)
3113 : m_layer(layer),
3114 m_level(level),
3115 m_desc(desc)
3116{
3117}
3118
3119/*!
3120 \fn int QRhiTextureUploadEntry::layer() const
3121 \return the currently set layer index (cubemap face, array layer). Defaults to 0.
3122 */
3123
3124/*!
3125 \fn void QRhiTextureUploadEntry::setLayer(int layer)
3126 Sets the \a layer.
3127 */
3128
3129/*!
3130 \fn int QRhiTextureUploadEntry::level() const
3131 \return the currently set mip level. Defaults to 0.
3132 */
3133
3134/*!
3135 \fn void QRhiTextureUploadEntry::setLevel(int level)
3136 Sets the mip \a level.
3137 */
3138
3139/*!
3140 \fn QRhiTextureSubresourceUploadDescription QRhiTextureUploadEntry::description() const
3141 \return the currently set subresource description.
3142 */
3143
3144/*!
3145 \fn void QRhiTextureUploadEntry::setDescription(const QRhiTextureSubresourceUploadDescription &desc)
3146 Sets the subresource description \a desc.
3147 */
3148
3149/*!
3150 \class QRhiTextureUploadDescription
3151 \inmodule QtGuiPrivate
3152 \inheaderfile rhi/qrhi.h
3153 \since 6.6
3154 \brief Describes a texture upload operation.
3155
3156 Used with QRhiResourceUpdateBatch::uploadTexture(). That function has two
3157 variants: one taking a QImage and one taking a
3158 QRhiTextureUploadDescription. The former is a convenience version,
3159 internally creating a QRhiTextureUploadDescription with a single image
3160 targeting level 0 for layer 0.
3161
3162 An example of the the common, simple case of wanting to upload the contents
3163 of a QImage to a QRhiTexture with a matching pixel size:
3164
3165 \code
3166 QImage image(256, 256, QImage::Format_RGBA8888);
3167 image.fill(Qt::green); // or could use a QPainter targeting image
3168 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256));
3169 texture->create();
3170 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
3171 u->uploadTexture(texture, image);
3172 \endcode
3173
3174 When cubemaps, pre-generated mip images, compressed textures, or partial
3175 uploads are involved, applications will have to use this class instead.
3176
3177 QRhiTextureUploadDescription also enables specifying batched uploads, which
3178 are useful for example when generating an atlas or glyph cache texture:
3179 multiple, partial uploads for the same subresource (meaning the same layer
3180 and level) are supported, and can be, depending on the backend and the
3181 underlying graphics API, more efficient when batched into the same
3182 QRhiTextureUploadDescription as opposed to issuing individual
3183 \l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} commands for
3184 each of them.
3185
3186 \note Cubemaps have one layer for each of the six faces in the order +X,
3187 -X, +Y, -Y, +Z, -Z.
3188
3189 For example, specifying the faces of a cubemap could look like the following:
3190
3191 \code
3192 QImage faces[6];
3193 // ...
3194 QVarLengthArray<QRhiTextureUploadEntry, 6> entries;
3195 for (int i = 0; i < 6; ++i)
3196 entries.append(QRhiTextureUploadEntry(i, 0, faces[i]));
3197 QRhiTextureUploadDescription desc;
3198 desc.setEntries(entries.cbegin(), entries.cend());
3199 resourceUpdates->uploadTexture(texture, desc);
3200 \endcode
3201
3202 Another example that specifies mip images for a compressed texture:
3203
3204 \code
3205 QList<QRhiTextureUploadEntry> entries;
3206 const int mipCount = rhi->mipLevelsForSize(compressedTexture->pixelSize());
3207 for (int level = 0; level < mipCount; ++level) {
3208 const QByteArray compressedDataForLevel = ..
3209 entries.append(QRhiTextureUploadEntry(0, level, compressedDataForLevel));
3210 }
3211 QRhiTextureUploadDescription desc;
3212 desc.setEntries(entries.cbegin(), entries.cend());
3213 resourceUpdates->uploadTexture(compressedTexture, desc);
3214 \endcode
3215
3216 With partial uploads targeting the same subresource, it is recommended to
3217 batch them into a single upload request, whenever possible:
3218
3219 \code
3220 QRhiTextureSubresourceUploadDescription subresDesc(image);
3221 subresDesc.setSourceSize(QSize(10, 10));
3222 subResDesc.setDestinationTopLeft(QPoint(50, 40));
3223 QRhiTextureUploadEntry entry(0, 0, subresDesc); // layer 0, level 0
3224
3225 QRhiTextureSubresourceUploadDescription subresDesc2(image);
3226 subresDesc2.setSourceSize(QSize(30, 40));
3227 subResDesc2.setDestinationTopLeft(QPoint(100, 200));
3228 QRhiTextureUploadEntry entry2(0, 0, subresDesc2); // layer 0, level 0, i.e. same subresource
3229
3230 QRhiTextureUploadDescription desc({ entry, entry2});
3231 resourceUpdates->uploadTexture(texture, desc);
3232 \endcode
3233
3234 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3235 for details.
3236
3237 \sa QRhiResourceUpdateBatch
3238 */
3239
3240/*!
3241 \fn QRhiTextureUploadDescription::QRhiTextureUploadDescription()
3242
3243 Constructs an empty texture upload description.
3244 */
3245
3246/*!
3247 Constructs a texture upload description with a single subresource upload
3248 described by \a entry.
3249 */
3250QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry)
3251{
3252 m_entries.append(entry);
3253}
3254
3255/*!
3256 Constructs a texture upload description with the specified \a list of entries.
3257
3258 \note \a list can also contain multiple QRhiTextureUploadEntry elements
3259 with the same layer and level. This makes sense when those uploads are
3260 partial, meaning their subresource description has a source size or image
3261 smaller than the subresource dimensions, and can be more efficient than
3262 issuing separate uploadTexture()'s.
3263 */
3264QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list)
3265 : m_entries(list)
3266{
3267}
3268
3269/*!
3270 \fn void QRhiTextureUploadDescription::setEntries(std::initializer_list<QRhiTextureUploadEntry> list)
3271 Sets the \a list of entries.
3272 */
3273
3274/*!
3275 \fn template<typename InputIterator> void QRhiTextureUploadDescription::setEntries(InputIterator first, InputIterator last)
3276 Sets the list of entries using the iterators \a first and \a last.
3277 */
3278
3279/*!
3280 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cbeginEntries() const
3281 \return a const iterator pointing to the first item in the entry list.
3282 */
3283
3284/*!
3285 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cendEntries() const
3286 \return a const iterator pointing just after the last item in the entry list.
3287 */
3288
3289/*!
3290 \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::entryAt(qsizetype index) const
3291 \return the entry at \a index.
3292 */
3293
3294/*!
3295 \fn qsizetype QRhiTextureUploadDescription::entryCount() const
3296 \return the number of entries.
3297 */
3298
3299/*!
3300 \class QRhiTextureCopyDescription
3301 \inmodule QtGuiPrivate
3302 \inheaderfile rhi/qrhi.h
3303 \since 6.6
3304 \brief Describes a texture-to-texture copy operation.
3305
3306 An empty pixelSize() indicates that the entire subresource is to be copied.
3307 A default constructed copy description therefore leads to copying the
3308 entire subresource at level 0 of layer 0.
3309
3310 \note The source texture must be created with
3311 QRhiTexture::UsedAsTransferSource.
3312
3313 \note The source and destination rectangles defined by pixelSize(),
3314 sourceTopLeft(), and destinationTopLeft() must fit the source and
3315 destination textures, respectively. The behavior is undefined otherwise.
3316
3317 With cubemaps, 3D textures, and texture arrays one face or slice can be
3318 copied at a time. The face or slice is specified by the source and
3319 destination layer indices. With mipmapped textures one mip level can be
3320 copied at a time. The source and destination layer and mip level indices can
3321 differ, but the size and position must be carefully controlled to avoid out
3322 of bounds copies, in which case the behavior is undefined.
3323
3324 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3325 for details.
3326 */
3327
3328/*!
3329 \fn QRhiTextureCopyDescription::QRhiTextureCopyDescription()
3330
3331 Constructs an empty texture copy description.
3332 */
3333
3334/*!
3335 \fn QSize QRhiTextureCopyDescription::pixelSize() const
3336 \return the size of the region to copy.
3337
3338 \note An empty pixelSize() indicates that the entire subresource is to be
3339 copied. A default constructed copy description therefore leads to copying
3340 the entire subresource at level 0 of layer 0.
3341 */
3342
3343/*!
3344 \fn void QRhiTextureCopyDescription::setPixelSize(const QSize &sz)
3345 Sets the size of the region to copy to \a sz.
3346 */
3347
3348/*!
3349 \fn int QRhiTextureCopyDescription::sourceLayer() const
3350 \return the source array layer (cubemap face or array layer index). Defaults to 0.
3351 */
3352
3353/*!
3354 \fn void QRhiTextureCopyDescription::setSourceLayer(int layer)
3355 Sets the source array \a layer.
3356 */
3357
3358/*!
3359 \fn int QRhiTextureCopyDescription::sourceLevel() const
3360 \return the source mip level. Defaults to 0.
3361 */
3362
3363/*!
3364 \fn void QRhiTextureCopyDescription::setSourceLevel(int level)
3365 Sets the source mip \a level.
3366 */
3367
3368/*!
3369 \fn QPoint QRhiTextureCopyDescription::sourceTopLeft() const
3370 \return the source top-left position (in pixels). Defaults to (0, 0).
3371 */
3372
3373/*!
3374 \fn void QRhiTextureCopyDescription::setSourceTopLeft(const QPoint &p)
3375 Sets the source top-left position to \a p.
3376 */
3377
3378/*!
3379 \fn int QRhiTextureCopyDescription::destinationLayer() const
3380 \return the destination array layer (cubemap face or array layer index). Default to 0.
3381 */
3382
3383/*!
3384 \fn void QRhiTextureCopyDescription::setDestinationLayer(int layer)
3385 Sets the destination array \a layer.
3386 */
3387
3388/*!
3389 \fn int QRhiTextureCopyDescription::destinationLevel() const
3390 \return the destionation mip level. Defaults to 0.
3391 */
3392
3393/*!
3394 \fn void QRhiTextureCopyDescription::setDestinationLevel(int level)
3395 Sets the destination mip \a level.
3396 */
3397
3398/*!
3399 \fn QPoint QRhiTextureCopyDescription::destinationTopLeft() const
3400 \return the destionation top-left position in pixels. Defaults to (0, 0).
3401 */
3402
3403/*!
3404 \fn void QRhiTextureCopyDescription::setDestinationTopLeft(const QPoint &p)
3405 Sets the destination top-left position \a p.
3406 */
3407
3408/*!
3409 \class QRhiReadbackDescription
3410 \inmodule QtGuiPrivate
3411 \inheaderfile rhi/qrhi.h
3412 \since 6.6
3413 \brief Describes a readback (reading back texture contents from possibly GPU-only memory) operation.
3414
3415 The source of the readback operation is either a QRhiTexture or the
3416 current backbuffer of the currently targeted QRhiSwapChain. When
3417 texture() is not set, the swapchain is used. Otherwise the specified
3418 QRhiTexture is treated as the source.
3419
3420 \note Textures used in readbacks must be created with
3421 QRhiTexture::UsedAsTransferSource.
3422
3423 \note Swapchains used in readbacks must be created with
3424 QRhiSwapChain::UsedAsTransferSource.
3425
3426 layer() and level() are only applicable when the source is a QRhiTexture.
3427
3428 \note Multisample textures cannot be read back. Readbacks are supported for
3429 multisample swapchain buffers however.
3430
3431 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3432 for details.
3433 */
3434
3435/*!
3436 \fn QRhiReadbackDescription::QRhiReadbackDescription() = default
3437
3438 Constructs an empty texture readback description.
3439
3440 \note The source texture is set to null by default, which is still a valid
3441 readback: it specifies that the backbuffer of the current swapchain is to
3442 be read back. (current meaning the frame's target swapchain at the time of
3443 committing the QRhiResourceUpdateBatch with the
3444 \l{QRhiResourceUpdateBatch::readBackTexture()}{texture readback} on it)
3445 */
3446
3447/*!
3448 Constructs an texture readback description that specifies that level 0 of
3449 layer 0 of \a texture is to be read back.
3450
3451 \note \a texture can also be null in which case this constructor is
3452 identical to the argumentless variant.
3453 */
3454QRhiReadbackDescription::QRhiReadbackDescription(QRhiTexture *texture)
3455 : m_texture(texture)
3456{
3457}
3458
3459/*!
3460 \fn QRhiTexture *QRhiReadbackDescription::texture() const
3461
3462 \return the QRhiTexture that is read back. Can be left set to \nullptr
3463 which indicates that the backbuffer of the current swapchain is to be used
3464 instead.
3465 */
3466
3467/*!
3468 \fn void QRhiReadbackDescription::setTexture(QRhiTexture *tex)
3469
3470 Sets the texture \a tex as the source of the readback operation.
3471
3472 Setting \nullptr is valid too, in which case the current swapchain's
3473 current backbuffer is used. (but then the readback cannot be issued in a
3474 non-swapchain-based frame)
3475
3476 \note Multisample textures cannot be read back. Readbacks are supported for
3477 multisample swapchain buffers however.
3478
3479 \note Textures used in readbacks must be created with
3480 QRhiTexture::UsedAsTransferSource.
3481
3482 \note Swapchains used in readbacks must be created with
3483 QRhiSwapChain::UsedAsTransferSource.
3484 */
3485
3486/*!
3487 \fn int QRhiReadbackDescription::layer() const
3488
3489 \return the currently set array layer (cubemap face, array index). Defaults to 0.
3490
3491 Applicable only when the source of the readback is a QRhiTexture.
3492 */
3493
3494/*!
3495 \fn void QRhiReadbackDescription::setLayer(int layer)
3496 Sets the array \a layer to read back.
3497 */
3498
3499/*!
3500 \fn int QRhiReadbackDescription::level() const
3501
3502 \return the currently set mip level. Defaults to 0.
3503
3504 Applicable only when the source of the readback is a QRhiTexture.
3505 */
3506
3507/*!
3508 \fn void QRhiReadbackDescription::setLevel(int level)
3509 Sets the mip \a level to read back.
3510 */
3511
3512/*!
3513 \fn const QRect &QRhiReadbackDescription::rect() const
3514 \since 6.10
3515
3516 \return the rectangle to read back. Defaults to an invalid rectangle.
3517
3518 If invalid, the entire texture or swapchain backbuffer is read back.
3519 */
3520
3521/*!
3522 \fn void QRhiReadbackDescription::setRect(const QRect &rectangle)
3523 \since 6.10
3524
3525 Sets the \a rectangle to read back.
3526 */
3527
3528/*!
3529 \class QRhiReadbackResult
3530 \inmodule QtGuiPrivate
3531 \inheaderfile rhi/qrhi.h
3532 \since 6.6
3533 \brief Describes the results of a potentially asynchronous buffer or texture readback operation.
3534
3535 When \l completed is set, the function is invoked when the \l data is
3536 available. \l format and \l pixelSize are set upon completion together with
3537 \l data.
3538
3539 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3540 for details.
3541 */
3542
3543/*!
3544 \variable QRhiReadbackResult::completed
3545
3546 Callback that is invoked upon completion, on the thread the QRhi operates
3547 on. Can be left set to \nullptr, in which case no callback is invoked.
3548 */
3549
3550/*!
3551 \variable QRhiReadbackResult::format
3552
3553 Valid only for textures, the texture format.
3554 */
3555
3556/*!
3557 \variable QRhiReadbackResult::pixelSize
3558
3559 Valid only for textures, the size in pixels.
3560 */
3561
3562/*!
3563 \variable QRhiReadbackResult::data
3564
3565 The buffer or image data.
3566
3567 \sa QRhiResourceUpdateBatch::readBackTexture(), QRhiResourceUpdateBatch::readBackBuffer()
3568 */
3569
3570
3571/*!
3572 \class QRhiNativeHandles
3573 \inmodule QtGuiPrivate
3574 \inheaderfile rhi/qrhi.h
3575 \since 6.6
3576 \brief Base class for classes exposing backend-specific collections of native resource objects.
3577
3578 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3579 for details.
3580 */
3581
3582/*!
3583 \class QRhiResource
3584 \inmodule QtGuiPrivate
3585 \inheaderfile rhi/qrhi.h
3586 \since 6.6
3587 \brief Base class for classes encapsulating native resource objects.
3588
3589 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3590 for details.
3591 */
3592
3593/*!
3594 \enum QRhiResource::Type
3595 Specifies type of the resource.
3596
3597 \value Buffer
3598 \value Texture
3599 \value Sampler
3600 \value RenderBuffer
3601 \value RenderPassDescriptor
3602 \value SwapChainRenderTarget
3603 \value TextureRenderTarget
3604 \value ShaderResourceBindings
3605 \value GraphicsPipeline
3606 \value SwapChain
3607 \value ComputePipeline
3608 \value CommandBuffer
3609 \value ShadingRateMap
3610 */
3611
3612/*!
3613 \fn virtual QRhiResource::Type QRhiResource::resourceType() const = 0
3614
3615 \return the type of the resource.
3616 */
3617
3618/*!
3619 \internal
3620 */
3621QRhiResource::QRhiResource(QRhiImplementation *rhi)
3622 : m_rhi(rhi)
3623{
3624 m_id = QRhiGlobalObjectIdGenerator::newId();
3625}
3626
3627/*!
3628 Destructor.
3629
3630 Releases (or requests deferred releasing of) the underlying native graphics
3631 resources, if there are any.
3632
3633 \note Resources referenced by commands for the current frame should not be
3634 released until the frame is submitted by QRhi::endFrame().
3635
3636 \sa destroy()
3637 */
3638QRhiResource::~QRhiResource()
3639{
3640 // destroy() cannot be called here, due to virtuals; it is up to the
3641 // subclasses to do that.
3642}
3643
3644/*!
3645 \fn virtual void QRhiResource::destroy() = 0
3646
3647 Releases (or requests deferred releasing of) the underlying native graphics
3648 resources. Safe to call multiple times, subsequent invocations will be a
3649 no-op then.
3650
3651 Once destroy() is called, the QRhiResource instance can be reused, by
3652 calling \c create() again. That will then result in creating new native
3653 graphics resources underneath.
3654
3655 \note Resources referenced by commands for the current frame should not be
3656 released until the frame is submitted by QRhi::endFrame().
3657
3658 The QRhiResource destructor also performs the same task, so calling this
3659 function is not necessary before deleting a QRhiResource.
3660
3661 \sa deleteLater()
3662 */
3663
3664/*!
3665 When called without a frame being recorded, this function is equivalent to
3666 deleting the object. Between a QRhi::beginFrame() and QRhi::endFrame()
3667 however the behavior is different: the QRhiResource will not be destroyed
3668 until the frame is submitted via QRhi::endFrame(), thus satisfying the QRhi
3669 requirement of not altering QRhiResource objects that are referenced by the
3670 frame being recorded.
3671
3672 If the QRhi that created this object is already destroyed, the object is
3673 deleted immediately.
3674
3675 Using deleteLater() can be a useful convenience in many cases, and it
3676 complements the low-level guarantee (that the underlying native graphics
3677 objects are never destroyed until it is safe to do so and it is known for
3678 sure that they are not used by the GPU in an still in-flight frame), by
3679 offering a way to make sure the C++ object instances (of QRhiBuffer,
3680 QRhiTexture, etc.) themselves also stay valid until the end of the current
3681 frame.
3682
3683 The following example shows a convenient way of creating a throwaway buffer
3684 that is only used in one frame and gets automatically released in
3685 endFrame(). (when it comes to the underlying native buffer(s), the usual
3686 guarantee applies: the QRhi backend defers the releasing of those until it
3687 is guaranteed that the frame in which the buffer is accessed by the GPU has
3688 completed)
3689
3690 \code
3691 rhi->beginFrame(swapchain);
3692 QRhiBuffer *buf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, 256);
3693 buf->deleteLater(); // !
3694 u = rhi->nextResourceUpdateBatch();
3695 u->uploadStaticBuffer(buf, data);
3696 // ... draw with buf
3697 rhi->endFrame();
3698 \endcode
3699
3700 \sa destroy()
3701 */
3702void QRhiResource::deleteLater()
3703{
3704 if (m_rhi)
3705 m_rhi->addDeleteLater(this);
3706 else
3707 delete this;
3708}
3709
3710/*!
3711 \return the currently set object name. By default the name is empty.
3712 */
3713QByteArray QRhiResource::name() const
3714{
3715 return m_objectName;
3716}
3717
3718/*!
3719 Sets a \a name for the object.
3720
3721 This allows getting descriptive names for the native graphics
3722 resources visible in graphics debugging tools, such as
3723 \l{https://renderdoc.org/}{RenderDoc} and
3724 \l{https://developer.apple.com/xcode/}{XCode}.
3725
3726 When it comes to naming native objects by relaying the name via the
3727 appropriate graphics API, note that the name is ignored when
3728 QRhi::DebugMarkers are not supported, and may, depending on the backend,
3729 also be ignored when QRhi::EnableDebugMarkers is not set.
3730
3731 \note The name may be ignored for objects other than buffers,
3732 renderbuffers, and textures, depending on the backend.
3733
3734 \note The name may be modified. For slotted resources, such as a QRhiBuffer
3735 backed by multiple native buffers, QRhi will append a suffix to make the
3736 underlying native buffers easily distinguishable from each other.
3737 */
3738void QRhiResource::setName(const QByteArray &name)
3739{
3740 m_objectName = name;
3741}
3742
3743/*!
3744 \return the global, unique identifier of this QRhiResource.
3745
3746 User code rarely needs to deal with the value directly. It is used
3747 internally for tracking and bookkeeping purposes.
3748 */
3749quint64 QRhiResource::globalResourceId() const
3750{
3751 return m_id;
3752}
3753
3754/*!
3755 \return the QRhi that created this resource.
3756
3757 If the QRhi that created this object is already destroyed, the result is
3758 \nullptr.
3759 */
3760QRhi *QRhiResource::rhi() const
3761{
3762 return m_rhi ? m_rhi->q : nullptr;
3763}
3764
3765/*!
3766 \class QRhiBuffer
3767 \inmodule QtGuiPrivate
3768 \inheaderfile rhi/qrhi.h
3769 \since 6.6
3770 \brief Vertex, index, or uniform (constant) buffer resource.
3771
3772 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3773 for details.
3774
3775 A QRhiBuffer encapsulates zero, one, or more native buffer objects (such as
3776 a \c VkBuffer or \c MTLBuffer). With some graphics APIs and backends
3777 certain types of buffers may not use a native buffer object at all (e.g.
3778 OpenGL if uniform buffer objects are not used), but this is transparent to
3779 the user of the QRhiBuffer API. Similarly, the fact that some types of
3780 buffers may use two or three native buffers underneath, in order to allow
3781 efficient per-frame content update without stalling the GPU pipeline, is
3782 mostly invisible to the applications and libraries.
3783
3784 A QRhiBuffer instance is always created by calling
3785 \l{QRhi::newBuffer()}{the QRhi's newBuffer() function}. This creates no
3786 native graphics resources. To do that, call create() after setting the
3787 appropriate options, such as the type, usage flags, size, although in most cases these
3788 are already set based on the arguments passed to
3789 \l{QRhi::newBuffer()}{newBuffer()}.
3790
3791 \section2 Example usage
3792
3793 To create a uniform buffer for a shader where the GLSL uniform block
3794 contains a single \c mat4 member, and update the contents:
3795
3796 \code
3797 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64);
3798 if (!ubuf->create()) { error(); }
3799 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3800 QMatrix4x4 mvp;
3801 // ... set up the modelview-projection matrix
3802 batch->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
3803 // ...
3804 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
3805 \endcode
3806
3807 An example of creating a buffer with vertex data:
3808
3809 \code
3810 const float vertices[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f };
3811 QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices));
3812 if (!vbuf->create()) { error(); }
3813 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3814 batch->uploadStaticBuffer(vbuf, vertices);
3815 // ...
3816 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
3817 \endcode
3818
3819 An index buffer:
3820
3821 \code
3822 static const quint16 indices[] = { 0, 1, 2 };
3823 QRhiBuffer *ibuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices));
3824 if (!ibuf->create()) { error(); }
3825 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3826 batch->uploadStaticBuffer(ibuf, indices);
3827 // ...
3828 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
3829 \endcode
3830
3831 \section2 Common patterns
3832
3833 A call to create() destroys any existing native resources if create() was
3834 successfully called before. If those native resources are still in use by
3835 an in-flight frame (i.e., there's a chance they are still read by the GPU),
3836 the destroying of those resources is deferred automatically. Thus a very
3837 common and convenient pattern to safely increase the size of an already
3838 initialized buffer is the following. In practice this drops and creates a
3839 whole new set of native resources underneath, so it is not necessarily a
3840 cheap operation, but is more convenient and still faster than the
3841 alternatives, because by not destroying the \c buf object itself, all
3842 references to it stay valid in other data structures (e.g., in any
3843 QRhiShaderResourceBinding the QRhiBuffer is referenced from).
3844
3845 \code
3846 if (buf->size() < newSize) {
3847 buf->setSize(newSize);
3848 if (!buf->create()) { error(); }
3849 }
3850 // continue using buf, fill it with new data
3851 \endcode
3852
3853 When working with uniform buffers, it will sometimes be necessary to
3854 combine data for multiple draw calls into a single buffer for efficiency
3855 reasons. Be aware of the aligment requirements: with some graphics APIs
3856 offsets for a uniform buffer must be aligned to 256 bytes. This applies
3857 both to QRhiShaderResourceBinding and to the dynamic offsets passed to
3858 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}. Use the
3859 \l{QRhi::ubufAlignment()}{ubufAlignment()} and
3860 \l{QRhi::ubufAligned()}{ubufAligned()} functions to create portable code.
3861 As an example, the following is an outline for issuing multiple (\c N) draw
3862 calls with the same pipeline and geometry, but with a different data in the
3863 uniform buffers exposed at binding point 0. This assumes the buffer is
3864 exposed via
3865 \l{QRhiShaderResourceBinding::uniformBufferWithDynamicOffset()}{uniformBufferWithDynamicOffset()}
3866 which allows passing a QRhiCommandBuffer::DynamicOffset list to
3867 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}.
3868
3869 \code
3870 const int N = 2;
3871 const int UB_SIZE = 64 + 4; // assuming a uniform block with { mat4 matrix; float opacity; }
3872 const int ONE_UBUF_SIZE = rhi->ubufAligned(UB_SIZE);
3873 const int TOTAL_UBUF_SIZE = N * ONE_UBUF_SIZE;
3874 QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, TOTAL_UBUF_SIZE);
3875 if (!ubuf->create()) { error(); }
3876 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3877 for (int i = 0; i < N; ++i) {
3878 batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE, 64, matrix.constData());
3879 batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE + 64, 4, &opacity);
3880 }
3881 // ...
3882 // beginPass(), set pipeline, etc., and then:
3883 for (int i = 0; i < N; ++i) {
3884 QRhiCommandBuffer::DynamicOffset dynOfs[] = { { 0, i * ONE_UBUF_SIZE } };
3885 cb->setShaderResources(srb, 1, dynOfs);
3886 cb->draw(36);
3887 }
3888 \endcode
3889
3890 \sa QRhiResourceUpdateBatch, QRhi, QRhiCommandBuffer
3891 */
3892
3893/*!
3894 \enum QRhiBuffer::Type
3895 Specifies storage type of buffer resource.
3896
3897 \value Immutable Indicates that the data is not expected to change ever
3898 after the initial upload. Under the hood such buffer resources are
3899 typically placed in device local (GPU) memory (on systems where
3900 applicable). Uploading new data is possible, but may be expensive. The
3901 upload typically happens by copying to a separate, host visible staging
3902 buffer from which a GPU buffer-to-buffer copy is issued into the actual
3903 GPU-only buffer.
3904
3905 \value Static Indicates that the data is expected to change only
3906 infrequently. Typically placed in device local (GPU) memory, where
3907 applicable. On backends where host visible staging buffers are used for
3908 uploading, the staging buffers are kept around for this type, unlike with
3909 Immutable, so subsequent uploads do not suffer in performance. Frequent
3910 updates, especially updates in consecutive frames, should be avoided.
3911
3912 \value Dynamic Indicates that the data is expected to change frequently.
3913 Not recommended for large buffers. Typically backed by host visible memory
3914 in 2 copies in order to allow for changing without stalling the graphics
3915 pipeline. The double buffering is managed transparently to the applications
3916 and is not exposed in the API here in any form. This is the recommended,
3917 and, with some backends, the only possible, type for buffers with
3918 UniformBuffer usage.
3919 */
3920
3921/*!
3922 \enum QRhiBuffer::UsageFlag
3923 Flag values to specify how the buffer is going to be used.
3924
3925 \value VertexBuffer Vertex buffer. This allows the QRhiBuffer to be used in
3926 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
3927
3928 \value IndexBuffer Index buffer. This allows the QRhiBuffer to be used in
3929 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
3930
3931 \value UniformBuffer Uniform buffer (also called constant buffer). This
3932 allows the QRhiBuffer to be used in combination with
3933 \l{QRhiShaderResourceBinding::UniformBuffer}{UniformBuffer}. When
3934 \l{QRhi::NonDynamicUniformBuffers}{NonDynamicUniformBuffers} is reported as
3935 not supported, this usage can only be combined with the type Dynamic.
3936
3937 \value StorageBuffer Storage buffer. This allows the QRhiBuffer to be used
3938 in combination with \l{QRhiShaderResourceBinding::BufferLoad}{BufferLoad},
3939 \l{QRhiShaderResourceBinding::BufferStore}{BufferStore}, or
3940 \l{QRhiShaderResourceBinding::BufferLoadStore}{BufferLoadStore}. This usage
3941 can only be combined with the types Immutable or Static, and is only
3942 available when the \l{QRhi::Compute}{Compute feature} is reported as
3943 supported.
3944 */
3945
3946/*!
3947 \class QRhiBuffer::NativeBuffer
3948 \inmodule QtGuiPrivate
3949 \inheaderfile rhi/qrhi.h
3950 \brief Contains information about the underlying native resources of a buffer.
3951 */
3952
3953/*!
3954 \variable QRhiBuffer::NativeBuffer::objects
3955 \brief an array with pointers to the native object handles.
3956
3957 With OpenGL, the native handle is a GLuint value, so the elements in the \c
3958 objects array are pointers to a GLuint. With Vulkan, the native handle is a
3959 VkBuffer, so the elements of the array are pointers to a VkBuffer. With
3960 Direct3D 11 and Metal the elements are pointers to a ID3D11Buffer or
3961 MTLBuffer pointer, respectively. With Direct3D 12, the elements are
3962 pointers to a ID3D12Resource.
3963
3964 \note Pay attention to the fact that the elements are always pointers to
3965 the native buffer handle type, even if the native type itself is a pointer.
3966 (so the elements are \c{VkBuffer *} on Vulkan, even though VkBuffer itself
3967 is a pointer on 64-bit architectures).
3968 */
3969
3970/*!
3971 \variable QRhiBuffer::NativeBuffer::slotCount
3972 \brief Specifies the number of valid elements in the objects array.
3973
3974 The value can be 0, 1, 2, or 3 in practice. 0 indicates that the QRhiBuffer
3975 is not backed by any native buffer objects. This can happen with
3976 QRhiBuffers with the usage UniformBuffer when the underlying API does not
3977 support (or the backend chooses not to use) native uniform buffers. 1 is
3978 commonly used for Immutable and Static types (but some backends may
3979 differ). 2 or 3 is typical when the type is Dynamic (but some backends may
3980 differ).
3981
3982 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
3983 */
3984
3985/*!
3986 \internal
3987 */
3988QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, quint32 size_)
3989 : QRhiResource(rhi),
3990 m_type(type_), m_usage(usage_), m_size(size_)
3991{
3992}
3993
3994/*!
3995 \return the resource type.
3996 */
3997QRhiResource::Type QRhiBuffer::resourceType() const
3998{
3999 return Buffer;
4000}
4001
4002/*!
4003 \fn virtual bool QRhiBuffer::create() = 0
4004
4005 Creates the corresponding native graphics resources. If there are already
4006 resources present due to an earlier create() with no corresponding
4007 destroy(), then destroy() is called implicitly first.
4008
4009 \return \c true when successful, \c false when a graphics operation failed.
4010 Regardless of the return value, calling destroy() is always safe.
4011 */
4012
4013/*!
4014 \fn QRhiBuffer::Type QRhiBuffer::type() const
4015 \return the buffer type.
4016 */
4017
4018/*!
4019 \fn void QRhiBuffer::setType(Type t)
4020 Sets the buffer's type to \a t.
4021 */
4022
4023/*!
4024 \fn QRhiBuffer::UsageFlags QRhiBuffer::usage() const
4025 \return the buffer's usage flags.
4026 */
4027
4028/*!
4029 \fn void QRhiBuffer::setUsage(UsageFlags u)
4030 Sets the buffer's usage flags to \a u.
4031 */
4032
4033/*!
4034 \fn quint32 QRhiBuffer::size() const
4035
4036 \return the buffer's size in bytes.
4037
4038 This is always the value that was passed to setSize() or QRhi::newBuffer().
4039 Internally, the native buffers may be bigger if that is required by the
4040 underlying graphics API.
4041 */
4042
4043/*!
4044 \fn void QRhiBuffer::setSize(quint32 sz)
4045
4046 Sets the size of the buffer in bytes. The size is normally specified in
4047 QRhi::newBuffer() so this function is only used when the size has to be
4048 changed. As with other setters, the size only takes effect when calling
4049 create(), and for already created buffers this involves releasing the previous
4050 native resource and creating new ones under the hood.
4051
4052 Backends may choose to allocate buffers bigger than \a sz in order to
4053 fulfill alignment requirements. This is hidden from the applications and
4054 size() will always report the size requested in \a sz.
4055 */
4056
4057/*!
4058 \return the underlying native resources for this buffer. The returned value
4059 will be empty if exposing the underlying native resources is not supported by
4060 the backend.
4061
4062 A QRhiBuffer may be backed by multiple native buffer objects, depending on
4063 the type() and the QRhi backend in use. When this is the case, all of them
4064 are returned in the objects array in the returned struct, with slotCount
4065 specifying the number of native buffer objects. While
4066 \l{QRhi::beginFrame()}{recording a frame}, QRhi::currentFrameSlot() can be
4067 used to determine which of the native buffers QRhi is using for operations
4068 that read or write from this QRhiBuffer within the frame being recorded.
4069
4070 In some cases a QRhiBuffer will not be backed by a native buffer object at
4071 all. In this case slotCount will be set to 0 and no valid native objects
4072 are returned. This is not an error, and is perfectly valid when a given
4073 backend does not use native buffers for QRhiBuffers with certain types or
4074 usages.
4075
4076 \note Be aware that QRhi backends may employ various buffer update
4077 strategies. Unlike textures, where uploading image data always means
4078 recording a buffer-to-image (or similar) copy command on the command
4079 buffer, buffers, in particular Dynamic and UniformBuffer ones, can operate
4080 in many different ways. For example, a QRhiBuffer with usage type
4081 UniformBuffer may not even be backed by a native buffer object at all if
4082 uniform buffers are not used or supported by a given backend and graphics
4083 API. There are also differences to how data is written to the buffer and
4084 the type of backing memory used. For buffers backed by host visible memory,
4085 calling this function guarantees that pending host writes are executed for
4086 all the returned native buffers.
4087
4088 \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4089 */
4090QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
4091{
4092 return { {}, 0 };
4093}
4094
4095/*!
4096 \return a pointer to a memory block with the host visible buffer data.
4097
4098 This is a shortcut for medium-to-large dynamic uniform buffers that have
4099 their \b entire contents (or at least all regions that are read by the
4100 shaders in the current frame) changed \b{in every frame} and the
4101 QRhiResourceUpdateBatch-based update mechanism is seen too heavy due to the
4102 amount of data copying involved.
4103
4104 The call to this function must be eventually followed by a call to
4105 endFullDynamicUniformBufferUpdateForCurrentFrame(), before recording any
4106 render or compute pass that relies on this buffer.
4107
4108 \warning Updating data via this method is not compatible with
4109 QRhiResourceUpdateBatch-based updates and readbacks. Unexpected behavior
4110 may occur when attempting to combine the two update models for the same
4111 buffer. Similarly, the data updated this direct way may not be visible to
4112 \l{QRhiResourceUpdateBatch::readBackBuffer()}{readBackBuffer operations},
4113 depending on the backend.
4114
4115 \warning When updating buffer data via this method, the update must be done
4116 in every frame, otherwise backends that perform double or triple buffering
4117 of resources may end up in unexpected behavior.
4118
4119 \warning Partial updates are not possible with this approach since some
4120 backends may choose a strategy where the previous contents of the buffer is
4121 lost upon calling this function. Data must be written to all regions that
4122 are read by shaders in the frame currently being prepared.
4123
4124 \warning This function can only be called when recording a frame, so
4125 between QRhi::beginFrame() and QRhi::endFrame().
4126
4127 \warning This function can only be called on Dynamic buffers.
4128 */
4129char *QRhiBuffer::beginFullDynamicBufferUpdateForCurrentFrame()
4130{
4131 return nullptr;
4132}
4133
4134/*!
4135 To be called when the entire contents of the buffer data has been updated
4136 in the memory block returned from
4137 beginFullDynamicBufferUpdateForCurrentFrame().
4138 */
4139void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
4140{
4141}
4142
4143/*!
4144 \internal
4145 */
4146void QRhiBuffer::fullDynamicBufferUpdateForCurrentFrame(const void *data, quint32 size)
4147{
4148 char *p = beginFullDynamicBufferUpdateForCurrentFrame();
4149 if (p) {
4150 memcpy(p, data, size > 0 ? size : m_size);
4151 endFullDynamicBufferUpdateForCurrentFrame();
4152 }
4153}
4154
4155/*!
4156 \class QRhiRenderBuffer
4157 \inmodule QtGuiPrivate
4158 \inheaderfile rhi/qrhi.h
4159 \since 6.6
4160 \brief Renderbuffer resource.
4161
4162 Renderbuffers cannot be sampled or read but have some benefits over
4163 textures in some cases:
4164
4165 A \l DepthStencil renderbuffer may be lazily allocated and be backed by
4166 transient memory with some APIs. On some platforms this may mean the
4167 depth/stencil buffer uses no physical backing at all.
4168
4169 \l Color renderbuffers are useful since QRhi::MultisampleRenderBuffer may be
4170 supported even when QRhi::MultisampleTexture is not.
4171
4172 How the renderbuffer is implemented by a backend is not exposed to the
4173 applications. In some cases it may be backed by ordinary textures, while in
4174 others there may be a different kind of native resource used.
4175
4176 Renderbuffers that are used as (and are only used as) depth-stencil buffers
4177 in combination with a QRhiSwapChain's color buffers should have the
4178 UsedWithSwapChainOnly flag set. This serves a double purpose: such buffers,
4179 depending on the backend and the underlying APIs, be more efficient, and
4180 QRhi provides automatic sizing behavior to match the color buffers, which
4181 means calling setPixelSize() and create() are not necessary for such
4182 renderbuffers.
4183
4184 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4185 for details.
4186 */
4187
4188/*!
4189 \enum QRhiRenderBuffer::Type
4190 Specifies the type of the renderbuffer
4191
4192 \value DepthStencil Combined depth/stencil
4193 \value Color Color
4194 */
4195
4196/*!
4197 \struct QRhiRenderBuffer::NativeRenderBuffer
4198 \inmodule QtGuiPrivate
4199 \inheaderfile rhi/qrhi.h
4200 \brief Wraps a native renderbuffer object.
4201 */
4202
4203/*!
4204 \variable QRhiRenderBuffer::NativeRenderBuffer::object
4205 \brief 64-bit integer containing the native object handle.
4206
4207 Used with QRhiRenderBuffer::createFrom().
4208
4209 With OpenGL the native handle is a GLuint value. \c object is expected to
4210 be a valid OpenGL renderbuffer object ID.
4211 */
4212
4213/*!
4214 \enum QRhiRenderBuffer::Flag
4215 Flag values for flags() and setFlags()
4216
4217 \value UsedWithSwapChainOnly For DepthStencil renderbuffers this indicates
4218 that the renderbuffer is only used in combination with a QRhiSwapChain, and
4219 never in any other way. This provides automatic sizing and resource
4220 rebuilding, so calling setPixelSize() or create() is not needed whenever
4221 this flag is set. This flag value may also trigger backend-specific
4222 behavior, for example with OpenGL, where a separate windowing system
4223 interface API is in use (EGL, GLX, etc.), the flag is especially important
4224 as it avoids creating any actual renderbuffer resource as there is already
4225 a windowing system provided depth/stencil buffer as requested by
4226 QSurfaceFormat.
4227 */
4228
4229/*!
4230 \internal
4231 */
4232QRhiRenderBuffer::QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
4233 int sampleCount_, Flags flags_,
4234 QRhiTexture::Format backingFormatHint_)
4235 : QRhiResource(rhi),
4236 m_type(type_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_),
4237 m_backingFormatHint(backingFormatHint_)
4238{
4239}
4240
4241/*!
4242 \return the resource type.
4243 */
4244QRhiResource::Type QRhiRenderBuffer::resourceType() const
4245{
4246 return RenderBuffer;
4247}
4248
4249/*!
4250 \fn virtual bool QRhiRenderBuffer::create() = 0
4251
4252 Creates the corresponding native graphics resources. If there are already
4253 resources present due to an earlier create() with no corresponding
4254 destroy(), then destroy() is called implicitly first.
4255
4256 \return \c true when successful, \c false when a graphics operation failed.
4257 Regardless of the return value, calling destroy() is always safe.
4258 */
4259
4260/*!
4261 Similar to create() except that no new native renderbuffer objects are
4262 created. Instead, the native renderbuffer object specified by \a src is
4263 used.
4264
4265 This allows importing an existing renderbuffer object (which must belong to
4266 the same device or sharing context, depending on the graphics API) from an
4267 external graphics engine.
4268
4269 \note This is currently applicable to OpenGL only. This function exists
4270 solely to allow importing a renderbuffer object that is bound to some
4271 special, external object, such as an EGLImageKHR. Once the application
4272 performed the glEGLImageTargetRenderbufferStorageOES call, the renderbuffer
4273 object can be passed to this function to create a wrapping
4274 QRhiRenderBuffer, which in turn can be passed in as a color attachment to
4275 a QRhiTextureRenderTarget to enable rendering to the EGLImage.
4276
4277 \note pixelSize(), sampleCount(), and flags() must still be set correctly.
4278 Passing incorrect sizes and other values to QRhi::newRenderBuffer() and
4279 then following it with a createFrom() expecting that the native
4280 renderbuffer object alone is sufficient to deduce such values is \b wrong
4281 and will lead to problems.
4282
4283 \note QRhiRenderBuffer does not take ownership of the native object, and
4284 destroy() will not release that object.
4285
4286 \note This function is only implemented when the QRhi::RenderBufferImport
4287 feature is reported as \l{QRhi::isFeatureSupported()}{supported}. Otherwise,
4288 the function does nothing and the return value is \c false.
4289
4290 \return \c true when successful, \c false when not supported.
4291 */
4292bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
4293{
4294 Q_UNUSED(src);
4295 return false;
4296}
4297
4298/*!
4299 \fn QRhiRenderBuffer::Type QRhiRenderBuffer::type() const
4300 \return the renderbuffer type.
4301 */
4302
4303/*!
4304 \fn void QRhiRenderBuffer::setType(Type t)
4305 Sets the type to \a t.
4306 */
4307
4308/*!
4309 \fn QSize QRhiRenderBuffer::pixelSize() const
4310 \return the pixel size.
4311 */
4312
4313/*!
4314 \fn void QRhiRenderBuffer::setPixelSize(const QSize &sz)
4315 Sets the size (in pixels) to \a sz.
4316 */
4317
4318/*!
4319 \fn int QRhiRenderBuffer::sampleCount() const
4320 \return the sample count. 1 means no multisample antialiasing.
4321 */
4322
4323/*!
4324 \fn void QRhiRenderBuffer::setSampleCount(int s)
4325 Sets the sample count to \a s.
4326 */
4327
4328/*!
4329 \fn QRhiRenderBuffer::Flags QRhiRenderBuffer::flags() const
4330 \return the flags.
4331 */
4332
4333/*!
4334 \fn void QRhiRenderBuffer::setFlags(Flags f)
4335 Sets the flags to \a f.
4336 */
4337
4338/*!
4339 \fn virtual QRhiTexture::Format QRhiRenderBuffer::backingFormat() const = 0
4340
4341 \internal
4342 */
4343
4344/*!
4345 \class QRhiTexture
4346 \inmodule QtGuiPrivate
4347 \inheaderfile rhi/qrhi.h
4348 \since 6.6
4349 \brief Texture resource.
4350
4351 A QRhiTexture encapsulates a native texture object, such as a \c VkImage or
4352 \c MTLTexture.
4353
4354 A QRhiTexture instance is always created by calling
4355 \l{QRhi::newTexture()}{the QRhi's newTexture() function}. This creates no
4356 native graphics resources. To do that, call create() after setting the
4357 appropriate options, such as the format and size, although in most cases
4358 these are already set based on the arguments passed to
4359 \l{QRhi::newTexture()}{newTexture()}.
4360
4361 Setting the \l{QRhiTexture::Flags}{flags} correctly is essential, otherwise
4362 various errors can occur depending on the underlying QRhi backend and
4363 graphics API. For example, when a texture will be rendered into from a
4364 render pass via QRhiTextureRenderTarget, the texture must be created with
4365 the \l RenderTarget flag set. Similarly, when the texture is going to be
4366 \l{QRhiResourceUpdateBatch::readBackTexture()}{read back}, the \l
4367 UsedAsTransferSource flag must be set upfront. Mipmapped textures must have
4368 the MipMapped flag set. And so on. It is not possible to change the flags
4369 once create() has succeeded. To release the existing and create a new
4370 native texture object with the changed settings, call the setters and call
4371 create() again. This then might be a potentially expensive operation.
4372
4373 \section2 Example usage
4374
4375 To create a 2D texture with a size of 512x512 pixels and set its contents to all green:
4376
4377 \code
4378 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512));
4379 if (!texture->create()) { error(); }
4380 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4381 QImage image(512, 512, QImage::Format_RGBA8888);
4382 image.fill(Qt::green);
4383 batch->uploadTexture(texture, image);
4384 // ...
4385 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4386 \endcode
4387
4388 \section2 Common patterns
4389
4390 A call to create() destroys any existing native resources if create() was
4391 successfully called before. If those native resources are still in use by
4392 an in-flight frame (i.e., there's a chance they are still read by the GPU),
4393 the destroying of those resources is deferred automatically. Thus a very
4394 common and convenient pattern to safely change the size of an already
4395 existing texture is the following. In practice this drops and creates a
4396 whole new native texture resource underneath, so it is not necessarily a
4397 cheap operation, but is more convenient and still faster than the
4398 alternatives, because by not destroying the \c texture object itself, all
4399 references to it stay valid in other data structures (e.g., in any
4400 QShaderResourceBinding the QRhiTexture is referenced from).
4401
4402 \code
4403 // determine newSize, e.g. based on the swapchain's output size or other factors
4404 if (texture->pixelSize() != newSize) {
4405 texture->setPixelSize(newSize);
4406 if (!texture->create()) { error(); }
4407 }
4408 // continue using texture, fill it with new data
4409 \endcode
4410
4411 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4412 for details.
4413
4414 \sa QRhiResourceUpdateBatch, QRhi, QRhiTextureRenderTarget
4415 */
4416
4417/*!
4418 \enum QRhiTexture::Flag
4419
4420 Flag values to specify how the texture is going to be used. Not honoring
4421 the flags set before create() and attempting to use the texture in ways that
4422 was not declared upfront can lead to unspecified behavior or decreased
4423 performance depending on the backend and the underlying graphics API.
4424
4425 \value RenderTarget The texture going to be used in combination with
4426 QRhiTextureRenderTarget.
4427
4428 \value CubeMap The texture is a cubemap. Such textures have 6 layers, one
4429 for each face in the order of +X, -X, +Y, -Y, +Z, -Z. Cubemap textures
4430 cannot be multisample.
4431
4432 \value MipMapped The texture has mipmaps. The appropriate mip count is
4433 calculated automatically and can also be retrieved via
4434 QRhi::mipLevelsForSize(). The images for the mip levels have to be
4435 provided in the texture uploaded or generated via
4436 QRhiResourceUpdateBatch::generateMips(). Multisample textures cannot have
4437 mipmaps.
4438
4439 \value sRGB Use an sRGB format.
4440
4441 \value UsedAsTransferSource The texture is used as the source of a texture
4442 copy or readback, meaning the texture is given as the source in
4443 QRhiResourceUpdateBatch::copyTexture() or
4444 QRhiResourceUpdateBatch::readBackTexture().
4445
4446 \value UsedWithGenerateMips The texture is going to be used with
4447 QRhiResourceUpdateBatch::generateMips().
4448
4449 \value UsedWithLoadStore The texture is going to be used with image
4450 load/store operations, for example, in a compute shader.
4451
4452 \value UsedAsCompressedAtlas The texture has a compressed format and the
4453 dimensions of subresource uploads may not match the texture size.
4454
4455 \value ExternalOES The texture should use the GL_TEXTURE_EXTERNAL_OES
4456 target with OpenGL. This flag is ignored with other graphics APIs.
4457
4458 \value ThreeDimensional The texture is a 3D texture. Such textures should
4459 be created with the QRhi::newTexture() overload taking a depth in addition
4460 to width and height. A 3D texture can have mipmaps but cannot be
4461 multisample. When rendering into, or uploading data to a 3D texture, the \c
4462 layer specified in the render target's color attachment or the upload
4463 description refers to a single slice in range [0..depth-1]. The underlying
4464 graphics API may not support 3D textures at run time. Support is indicated
4465 by the QRhi::ThreeDimensionalTextures feature.
4466
4467 \value TextureRectangleGL The texture should use the GL_TEXTURE_RECTANGLE
4468 target with OpenGL. This flag is ignored with other graphics APIs. Just
4469 like ExternalOES, this flag is useful when working with platform APIs where
4470 native OpenGL texture objects received from the platform are wrapped in a
4471 QRhiTexture, and the platform can only provide textures for a non-2D
4472 texture target.
4473
4474 \value TextureArray The texture is a texture array, i.e. a single texture
4475 object that is a homogeneous array of 2D textures. Texture arrays are
4476 created with QRhi::newTextureArray(). The underlying graphics API may not
4477 support texture array objects at run time. Support is indicated by the
4478 QRhi::TextureArrays feature. When rendering into, or uploading data to a
4479 texture array, the \c layer specified in the render target's color
4480 attachment or the upload description selects a single element in the array.
4481
4482 \value OneDimensional The texture is a 1D texture. Such textures can be
4483 created by passing a 0 height and depth to QRhi::newTexture(). Note that
4484 there can be limitations on one dimensional textures depending on the
4485 underlying graphics API. For example, rendering to them or using them with
4486 mipmap-based filtering may be unsupported. This is indicated by the
4487 QRhi::OneDimensionalTextures and QRhi::OneDimensionalTextureMipmaps
4488 feature flags.
4489
4490 \value UsedAsShadingRateMap
4491 */
4492
4493/*!
4494 \enum QRhiTexture::Format
4495
4496 Specifies the texture format. See also QRhi::isTextureFormatSupported() and
4497 note that flags() can modify the format when QRhiTexture::sRGB is set.
4498
4499 \value UnknownFormat Not a valid format. This cannot be passed to setFormat().
4500
4501 \value RGBA8 Four components, unsigned normalized 8-bit per component. Always supported. (32 bits total)
4502
4503 \value BGRA8 Four components, unsigned normalized 8-bit per component. (32 bits total)
4504
4505 \value R8 One component, unsigned normalized 8-bit. (8 bits total)
4506
4507 \value RG8 Two components, unsigned normalized 8-bit. (16 bits total)
4508
4509 \value R16 One component, unsigned normalized 16-bit. (16 bits total)
4510
4511 \value RG16 Two components, unsigned normalized 16-bit. (32 bits total)
4512
4513 \value RED_OR_ALPHA8 Either same as R8, or is a similar format with the component swizzled to alpha,
4514 depending on \l{QRhi::RedOrAlpha8IsRed}{RedOrAlpha8IsRed}. (8 bits total)
4515
4516 \value RGBA16F Four components, 16-bit float. (64 bits total)
4517
4518 \value RGBA32F Four components, 32-bit float. (128 bits total)
4519
4520 \value R16F One component, 16-bit float. (16 bits total)
4521
4522 \value R32F One component, 32-bit float. (32 bits total)
4523
4524 \value RGB10A2 Four components, unsigned normalized 10 bit R, G, and B,
4525 2-bit alpha. This is a packed format so native endianness applies. Note
4526 that there is no BGR10A2. This is because RGB10A2 maps to
4527 DXGI_FORMAT_R10G10B10A2_UNORM with D3D, MTLPixelFormatRGB10A2Unorm with
4528 Metal, VK_FORMAT_A2B10G10R10_UNORM_PACK32 with Vulkan, and
4529 GL_RGB10_A2/GL_RGB/GL_UNSIGNED_INT_2_10_10_10_REV on OpenGL (ES). This is
4530 the only universally supported RGB30 option. The corresponding QImage
4531 formats are QImage::Format_BGR30 and QImage::Format_A2BGR30_Premultiplied.
4532 (32 bits total)
4533
4534 \value D16 16-bit depth (normalized unsigned integer)
4535
4536 \value D24 24-bit depth (normalized unsigned integer)
4537
4538 \value D24S8 24-bit depth (normalized unsigned integer), 8 bit stencil
4539
4540 \value D32F 32-bit depth (32-bit float)
4541
4542 \value [since 6.9] D32FS8 32-bit depth (32-bit float), 8 bits of stencil, 24 bits unused
4543 (64 bits total)
4544
4545 \value BC1
4546 \value BC2
4547 \value BC3
4548 \value BC4
4549 \value BC5
4550 \value BC6H
4551 \value BC7
4552
4553 \value ETC2_RGB8
4554 \value ETC2_RGB8A1
4555 \value ETC2_RGBA8
4556
4557 \value ASTC_4x4
4558 \value ASTC_5x4
4559 \value ASTC_5x5
4560 \value ASTC_6x5
4561 \value ASTC_6x6
4562 \value ASTC_8x5
4563 \value ASTC_8x6
4564 \value ASTC_8x8
4565 \value ASTC_10x5
4566 \value ASTC_10x6
4567 \value ASTC_10x8
4568 \value ASTC_10x10
4569 \value ASTC_12x10
4570 \value ASTC_12x12
4571
4572 \value [since 6.9] R8UI One component, unsigned 8-bit. (8 bits total)
4573 \value [since 6.9] R32UI One component, unsigned 32-bit. (32 bits total)
4574 \value [since 6.9] RG32UI Two components, unsigned 32-bit. (64 bits total)
4575 \value [since 6.9] RGBA32UI Four components, unsigned 32-bit. (128 bits total)
4576
4577 \value [since 6.10] R8SI One component, signed 8-bit. (8 bits total)
4578 \value [since 6.10] R32SI One component, signed 32-bit. (32 bits total)
4579 \value [since 6.10] RG32SI Two components, signed 32-bit. (64 bits total)
4580 \value [since 6.10] RGBA32SI Four components, signed 32-bit. (128 bits total)
4581 */
4582
4583// When adding new texture formats, update void tst_QRhi::textureFormats_data().
4584
4585/*!
4586 \struct QRhiTexture::NativeTexture
4587 \inmodule QtGuiPrivate
4588 \inheaderfile rhi/qrhi.h
4589 \brief Contains information about the underlying native resources of a texture.
4590 */
4591
4592/*!
4593 \variable QRhiTexture::NativeTexture::object
4594 \brief 64-bit integer containing the native object handle.
4595
4596 With OpenGL, the native handle is a GLuint value, so \c object can then be
4597 cast to a GLuint. With Vulkan, the native handle is a VkImage, so \c object
4598 can be cast to a VkImage. With Direct3D 11 and Metal \c object contains a
4599 ID3D11Texture2D or MTLTexture pointer, respectively. With Direct3D 12
4600 \c object contains a ID3D12Resource pointer.
4601 */
4602
4603/*!
4604 \variable QRhiTexture::NativeTexture::layout
4605 \brief Specifies the current image layout for APIs like Vulkan.
4606
4607 For Vulkan, \c layout contains a \c VkImageLayout value.
4608 */
4609
4610/*!
4611 \internal
4612 */
4613QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
4614 int arraySize_, int sampleCount_, Flags flags_)
4615 : QRhiResource(rhi),
4616 m_format(format_), m_pixelSize(pixelSize_), m_depth(depth_),
4617 m_arraySize(arraySize_), m_sampleCount(sampleCount_), m_flags(flags_)
4618{
4619}
4620
4621/*!
4622 \return the resource type.
4623 */
4624QRhiResource::Type QRhiTexture::resourceType() const
4625{
4626 return Texture;
4627}
4628
4629/*!
4630 \fn virtual bool QRhiTexture::create() = 0
4631
4632 Creates the corresponding native graphics resources. If there are already
4633 resources present due to an earlier create() with no corresponding
4634 destroy(), then destroy() is called implicitly first.
4635
4636 \return \c true when successful, \c false when a graphics operation failed.
4637 Regardless of the return value, calling destroy() is always safe.
4638 */
4639
4640/*!
4641 \return the underlying native resources for this texture. The returned value
4642 will be empty if exposing the underlying native resources is not supported by
4643 the backend.
4644
4645 \sa createFrom()
4646 */
4647QRhiTexture::NativeTexture QRhiTexture::nativeTexture()
4648{
4649 return {};
4650}
4651
4652/*!
4653 Similar to create(), except that no new native textures are created.
4654 Instead, the native texture resources specified by \a src is used.
4655
4656 This allows importing an existing native texture object (which must belong
4657 to the same device or sharing context, depending on the graphics API) from
4658 an external graphics engine.
4659
4660 \return true if the specified existing native texture object has been
4661 successfully wrapped as a non-owning QRhiTexture.
4662
4663 \note format(), pixelSize(), sampleCount(), and flags() must still be set
4664 correctly. Passing incorrect sizes and other values to QRhi::newTexture()
4665 and then following it with a createFrom() expecting that the native texture
4666 object alone is sufficient to deduce such values is \b wrong and will lead
4667 to problems.
4668
4669 \note QRhiTexture does not take ownership of the texture object. destroy()
4670 does not free the object or any associated memory.
4671
4672 The opposite of this operation, exposing a QRhiTexture-created native
4673 texture object to a foreign engine, is possible via nativeTexture().
4674
4675 \note When importing a 3D texture, or a texture array object, or, with
4676 OpenGL ES, an external texture, it is then especially important to set the
4677 corresponding flags (ThreeDimensional, TextureArray, ExternalOES) via
4678 setFlags() before calling this function.
4679*/
4680bool QRhiTexture::createFrom(QRhiTexture::NativeTexture src)
4681{
4682 Q_UNUSED(src);
4683 return false;
4684}
4685
4686/*!
4687 With some graphics APIs, such as Vulkan, integrating custom rendering code
4688 that uses the graphics API directly needs special care when it comes to
4689 image layouts. This function allows communicating the expected \a layout the
4690 image backing the QRhiTexture is in after the native rendering commands.
4691
4692 For example, consider rendering into a QRhiTexture's VkImage directly with
4693 Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and
4694 QRhiCommandBuffer::endExternal(), followed by using the image for texture
4695 sampling in a QRhi-based render pass. To avoid potentially incorrect image
4696 layout transitions, this function can be used to indicate what the image
4697 layout will be once the commands recorded in said code block complete.
4698
4699 Calling this function makes sense only after
4700 QRhiCommandBuffer::endExternal() and before a subsequent
4701 QRhiCommandBuffer::beginPass().
4702
4703 This function has no effect with QRhi backends where the underlying
4704 graphics API does not expose a concept of image layouts.
4705
4706 \note With Vulkan \a layout is a \c VkImageLayout. With Direct 3D 12 \a
4707 layout is a value composed of the bits from \c D3D12_RESOURCE_STATES.
4708 */
4709void QRhiTexture::setNativeLayout(int layout)
4710{
4711 Q_UNUSED(layout);
4712}
4713
4714/*!
4715 \fn QRhiTexture::Format QRhiTexture::format() const
4716 \return the texture format.
4717 */
4718
4719/*!
4720 \fn void QRhiTexture::setFormat(QRhiTexture::Format fmt)
4721
4722 Sets the requested texture format to \a fmt.
4723
4724 \note The value set is only taken into account upon the next call to
4725 create(), i.e. when the underlying graphics resource are (re)created.
4726 Setting a new value is futile otherwise and must be avoided since it can
4727 lead to inconsistent state.
4728 */
4729
4730/*!
4731 \fn QSize QRhiTexture::pixelSize() const
4732 \return the size in pixels.
4733 */
4734
4735/*!
4736 \fn void QRhiTexture::setPixelSize(const QSize &sz)
4737
4738 Sets the texture size, specified in pixels, to \a sz.
4739
4740 \note The value set is only taken into account upon the next call to
4741 create(), i.e. when the underlying graphics resource are (re)created.
4742 Setting a new value is futile otherwise and must be avoided since it can
4743 lead to inconsistent state. The same applies to all other setters as well.
4744 */
4745
4746/*!
4747 \fn int QRhiTexture::depth() const
4748 \return the depth for 3D textures.
4749 */
4750
4751/*!
4752 \fn void QRhiTexture::setDepth(int depth)
4753 Sets the \a depth for a 3D texture.
4754 */
4755
4756/*!
4757 \fn int QRhiTexture::arraySize() const
4758 \return the texture array size.
4759 */
4760
4761/*!
4762 \fn void QRhiTexture::setArraySize(int arraySize)
4763 Sets the texture \a arraySize.
4764 */
4765
4766/*!
4767 \fn int QRhiTexture::arrayRangeStart() const
4768
4769 \return the first array layer when setArrayRange() was called.
4770
4771 \sa setArrayRange()
4772 */
4773
4774/*!
4775 \fn int QRhiTexture::arrayRangeLength() const
4776
4777 \return the exposed array range size when setArrayRange() was called.
4778
4779 \sa setArrayRange()
4780*/
4781
4782/*!
4783 \fn void QRhiTexture::setArrayRange(int startIndex, int count)
4784
4785 Normally all array layers are exposed and it is up to the shader to select
4786 the layer via the third coordinate passed to the \c{texture()} GLSL
4787 function when sampling the \c sampler2DArray. When QRhi::TextureArrayRange
4788 is reported as supported, calling setArrayRange() before create() or
4789 createFrom() requests selecting only the specified range, \a count elements
4790 starting from \a startIndex. The shader logic can then be written with this
4791 in mind.
4792
4793 \sa QRhi::TextureArrayRange
4794 */
4795
4796/*!
4797 \fn Flags QRhiTexture::flags() const
4798 \return the texture flags.
4799 */
4800
4801/*!
4802 \fn void QRhiTexture::setFlags(Flags f)
4803 Sets the texture flags to \a f.
4804 */
4805
4806/*!
4807 \fn int QRhiTexture::sampleCount() const
4808 \return the sample count. 1 means no multisample antialiasing.
4809 */
4810
4811/*!
4812 \fn void QRhiTexture::setSampleCount(int s)
4813 Sets the sample count to \a s.
4814 */
4815
4816/*!
4817 \struct QRhiTexture::ViewFormat
4818 \inmodule QtGuiPrivate
4819 \inheaderfile rhi/qrhi.h
4820 \since 6.8
4821 \brief Specifies the view format for reading or writing from or to the texture.
4822
4823 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4824 for details.
4825 */
4826
4827/*!
4828 \variable QRhiTexture::ViewFormat::format
4829 */
4830
4831/*!
4832 \variable QRhiTexture::ViewFormat::srgb
4833 */
4834
4835/*!
4836 \fn QRhiTexture::ViewFormat QRhiTexture::readViewFormat() const
4837 \since 6.8
4838 \return the view format used when sampling the texture. When not called, the view
4839 format is assumed to be the same as format().
4840 */
4841
4842/*!
4843 \fn void QRhiTexture::setReadViewFormat(const ViewFormat &fmt)
4844 \since 6.8
4845
4846 Sets the shader resource view format (or the format of the view used for
4847 sampling the texture) to \a fmt. By default the same format (and sRGB-ness)
4848 is used as the texture itself, and in most cases this function does not need
4849 to be called.
4850
4851 This setting is only taken into account when the \l QRhi::TextureViewFormat
4852 feature is reported as supported.
4853
4854 \note This functionality is provided to allow "casting" between
4855 non-sRGB and sRGB in order to get the shader reads perform, or not perform,
4856 the implicit sRGB conversions. Other types of casting may or may not be
4857 functional.
4858 */
4859
4860/*!
4861 \fn QRhiTexture::ViewFormat QRhiTexture::writeViewFormat() const
4862 \since 6.8
4863 \return the view format used when writing to the texture and when using it
4864 with image load/store. When not called, the view format is assumed to be the
4865 same as format().
4866 */
4867
4868/*!
4869 \fn void QRhiTexture::setWriteViewFormat(const ViewFormat &fmt)
4870 \since 6.8
4871
4872 Sets the render target view format to \a fmt. By default the same format
4873 (and sRGB-ness) is used as the texture itself, and in most cases this
4874 function does not need to be called.
4875
4876 One common use case for providing a write view format is working with
4877 externally provided textures that, outside of our control, use an sRGB
4878 format with 3D APIs such as Vulkan or Direct 3D, but the rendering engine is
4879 already prepared to handle linearization and conversion to sRGB at the end
4880 of its shading pipeline. In this case what is wanted when rendering into
4881 such a texture is a render target view (e.g. VkImageView) that has the same,
4882 but non-sRGB format. (if e.g. from an OpenXR implementation one gets a
4883 VK_FORMAT_R8G8B8A8_SRGB texture, it is likely that rendering into it should
4884 be done using a VK_FORMAT_R8G8B8A8_UNORM view, if that is what the rendering
4885 engine's pipeline requires; in this example one would call this function
4886 with a ViewFormat that has a format of QRhiTexture::RGBA8 and \c srgb set to
4887 \c false).
4888
4889 This setting is only taken into account when the \l QRhi::TextureViewFormat
4890 feature is reported as supported.
4891
4892 \note This functionality is provided to allow "casting" between
4893 non-sRGB and sRGB in order to get the shader write not perform, or perform,
4894 the implicit sRGB conversions. Other types of casting may or may not be
4895 functional.
4896 */
4897
4898/*!
4899 \class QRhiSampler
4900 \inmodule QtGuiPrivate
4901 \inheaderfile rhi/qrhi.h
4902 \since 6.6
4903 \brief Sampler resource.
4904
4905 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4906 for details.
4907 */
4908
4909/*!
4910 \enum QRhiSampler::Filter
4911 Specifies the minification, magnification, or mipmap filtering
4912
4913 \value None Applicable only for mipmapMode(), indicates no mipmaps to be used
4914 \value Nearest
4915 \value Linear
4916 */
4917
4918/*!
4919 \enum QRhiSampler::AddressMode
4920 Specifies the addressing mode
4921
4922 \value Repeat
4923 \value ClampToEdge
4924 \value Mirror
4925 */
4926
4927/*!
4928 \enum QRhiSampler::CompareOp
4929 Specifies the texture comparison function.
4930
4931 \value Never (default)
4932 \value Less
4933 \value Equal
4934 \value LessOrEqual
4935 \value Greater
4936 \value NotEqual
4937 \value GreaterOrEqual
4938 \value Always
4939 */
4940
4941/*!
4942 \internal
4943 */
4944QRhiSampler::QRhiSampler(QRhiImplementation *rhi,
4945 Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
4946 AddressMode u_, AddressMode v_, AddressMode w_)
4947 : QRhiResource(rhi),
4948 m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_),
4949 m_addressU(u_), m_addressV(v_), m_addressW(w_),
4950 m_compareOp(QRhiSampler::Never)
4951{
4952}
4953
4954/*!
4955 \return the resource type.
4956 */
4957QRhiResource::Type QRhiSampler::resourceType() const
4958{
4959 return Sampler;
4960}
4961
4962/*!
4963 \fn QRhiSampler::Filter QRhiSampler::magFilter() const
4964 \return the magnification filter mode.
4965 */
4966
4967/*!
4968 \fn void QRhiSampler::setMagFilter(Filter f)
4969 Sets the magnification filter mode to \a f.
4970 */
4971
4972/*!
4973 \fn QRhiSampler::Filter QRhiSampler::minFilter() const
4974 \return the minification filter mode.
4975 */
4976
4977/*!
4978 \fn void QRhiSampler::setMinFilter(Filter f)
4979 Sets the minification filter mode to \a f.
4980 */
4981
4982/*!
4983 \fn QRhiSampler::Filter QRhiSampler::mipmapMode() const
4984 \return the mipmap filter mode.
4985 */
4986
4987/*!
4988 \fn void QRhiSampler::setMipmapMode(Filter f)
4989
4990 Sets the mipmap filter mode to \a f.
4991
4992 Leave this set to None when the texture has no mip levels, or when the mip
4993 levels are not to be taken into account.
4994 */
4995
4996/*!
4997 \fn QRhiSampler::AddressMode QRhiSampler::addressU() const
4998 \return the horizontal wrap mode.
4999 */
5000
5001/*!
5002 \fn void QRhiSampler::setAddressU(AddressMode mode)
5003 Sets the horizontal wrap \a mode.
5004 */
5005
5006/*!
5007 \fn QRhiSampler::AddressMode QRhiSampler::addressV() const
5008 \return the vertical wrap mode.
5009 */
5010
5011/*!
5012 \fn void QRhiSampler::setAddressV(AddressMode mode)
5013 Sets the vertical wrap \a mode.
5014 */
5015
5016/*!
5017 \fn QRhiSampler::AddressMode QRhiSampler::addressW() const
5018 \return the depth wrap mode.
5019 */
5020
5021/*!
5022 \fn void QRhiSampler::setAddressW(AddressMode mode)
5023 Sets the depth wrap \a mode.
5024 */
5025
5026/*!
5027 \fn QRhiSampler::CompareOp QRhiSampler::textureCompareOp() const
5028 \return the texture comparison function.
5029 */
5030
5031/*!
5032 \fn void QRhiSampler::setTextureCompareOp(CompareOp op)
5033 Sets the texture comparison function \a op.
5034 */
5035
5036/*!
5037 \class QRhiShadingRateMap
5038 \inmodule QtGuiPrivate
5039 \inheaderfile rhi/qrhi.h
5040 \since 6.9
5041 \brief An object that wraps a texture or another kind of native 3D API object.
5042
5043 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5044 for details.
5045
5046 For an introduction to Variable Rate Shading (VRS), see
5047 \l{https://learn.microsoft.com/en-us/windows/win32/direct3d12/vrs}. Qt
5048 supports a subset of the VRS features offered by Direct 3D 12 and Vulkan. In
5049 addition, Metal's somewhat different mechanism is supported by making it
5050 possible to set up a QRhiShadingRateMap with an existing
5051 MTLRasterizationRateMap object.
5052 */
5053
5054/*!
5055 \struct QRhiShadingRateMap::NativeShadingRateMap
5056 \inmodule QtGuiPrivate
5057 \inheaderfile rhi/qrhi.h
5058 \since 6.9
5059 \brief Wraps a native shading rate map.
5060
5061 An example is MTLRasterizationRateMap with Metal. Other 3D APIs that use
5062 textures for image-based VRS do not use this struct since those can function
5063 via the QRhiTexture-based overload of QRhiShadingRate::createFrom().
5064 */
5065
5066/*!
5067 \variable QRhiShadingRateMap::NativeShadingRateMap::object
5068 \brief 64-bit integer containing the native object handle.
5069
5070 Used with QRhiShadingRateMap::createFrom(). For example, with Metal,
5071 \c object is expected to be an id<MTLRasterizationRateMap>.
5072 */
5073
5074/*!
5075 \internal
5076 */
5077QRhiShadingRateMap::QRhiShadingRateMap(QRhiImplementation *rhi)
5078 : QRhiResource(rhi)
5079{
5080}
5081
5082/*!
5083 \return the resource type.
5084 */
5085QRhiResource::Type QRhiShadingRateMap::resourceType() const
5086{
5087 return ShadingRateMap;
5088}
5089
5090/*!
5091 Sets up the shading rate map to use a native 3D API shading rate object
5092 \a src.
5093
5094 \return \c true when successful, \c false when not supported.
5095
5096 \note This is functional only when the QRhi::VariableRateShadingMap feature
5097 is reported as supported, while QRhi::VariableShadingRateMapWithTexture
5098 feature is not. Currently this is true for Metal, assuming variable rate
5099 shading is supported by the GPU.
5100
5101 \note With Metal, the \c object field of \a src is expected to contain an
5102 id<MTLRasterizationRateMap>. Note that Qt does not perform anything else
5103 apart from passing the MTLRasterizationRateMap on to the
5104 MTLRenderPassDescriptor. If any special scaling is required, it is up to the
5105 application (or the XR compositor) to perform that.
5106 */
5107bool QRhiShadingRateMap::createFrom(NativeShadingRateMap src)
5108{
5109 Q_UNUSED(src);
5110 return false;
5111}
5112
5113/*!
5114 Sets up the shading rate map to use the texture \a src as the
5115 image containing the per-tile shading rates.
5116
5117 \return \c true when successful, \c false when not supported.
5118
5119 The QRhiShadingRateMap does not take ownership of \a src.
5120
5121 \note This is functional only when the
5122 QRhi::VariableRateShadingMapWithTexture feature is reported as supported. In
5123 practice may be supported on Vulkan and Direct 3D 12 when using modern
5124 graphics cards. It will never be supported on OpenGL or Metal, for example.
5125
5126 \note \a src must have a format of QRhiTexture::R8UI.
5127
5128 \note \a src must have a width of \c{ceil(render_target_pixel_width /
5129 (float)tile_width)} and a height of \c{ceil(render_target_pixel_height /
5130 (float)tile_height)}. It is up to the application to ensure the size of the
5131 texture is as expected, using the above formula, at all times. The tile size
5132 can be queried via \l QRhi::resourceLimit() and
5133 QRhi::ShadingRateImageTileSize.
5134
5135 Each byte (texel) in the texture corresponds to the shading rate value for
5136 one tile. 0 indicates 1x1, while a value of 10 indicates 4x4. See
5137 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shading_rate}{D3D12_SHADING_RATE}
5138 for other possible values.
5139 */
5140bool QRhiShadingRateMap::createFrom(QRhiTexture *src)
5141{
5142 Q_UNUSED(src);
5143 return false;
5144}
5145
5146/*!
5147 \class QRhiRenderPassDescriptor
5148 \inmodule QtGuiPrivate
5149 \inheaderfile rhi/qrhi.h
5150 \since 6.6
5151 \brief Render pass resource.
5152
5153 A render pass, if such a concept exists in the underlying graphics API, is
5154 a collection of attachments (color, depth, stencil) and describes how those
5155 attachments are used.
5156
5157 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5158 for details.
5159 */
5160
5161/*!
5162 \internal
5163 */
5164QRhiRenderPassDescriptor::QRhiRenderPassDescriptor(QRhiImplementation *rhi)
5165 : QRhiResource(rhi)
5166{
5167}
5168
5169/*!
5170 \return the resource type.
5171 */
5172QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
5173{
5174 return RenderPassDescriptor;
5175}
5176
5177/*!
5178 \fn virtual bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const = 0
5179
5180 \return true if the \a other QRhiRenderPassDescriptor is compatible with
5181 this one, meaning \c this and \a other can be used interchangebly in
5182 QRhiGraphicsPipeline::setRenderPassDescriptor().
5183
5184 The concept of the compatibility of renderpass descriptors is similar to
5185 the \l{QRhiShaderResourceBindings::isLayoutCompatible}{layout
5186 compatibility} of QRhiShaderResourceBindings instances. They allow better
5187 reuse of QRhiGraphicsPipeline instances: for example, a
5188 QRhiGraphicsPipeline instance cache is expected to use these functions to
5189 look for a matching pipeline, instead of just comparing pointers, thus
5190 allowing a different QRhiRenderPassDescriptor and
5191 QRhiShaderResourceBindings to be used in combination with the pipeline, as
5192 long as they are compatible.
5193
5194 The exact details of compatibility depend on the underlying graphics API.
5195 Two renderpass descriptors
5196 \l{QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()}{created}
5197 from the same QRhiTextureRenderTarget are always compatible.
5198
5199 Similarly to QRhiShaderResourceBindings, compatibility can also be tested
5200 without having two existing objects available. Extracting the opaque blob by
5201 calling serializedFormat() allows testing for compatibility by comparing the
5202 returned vector to another QRhiRenderPassDescriptor's
5203 serializedFormat(). This has benefits in certain situations, because it
5204 allows testing the compatibility of a QRhiRenderPassDescriptor with a
5205 QRhiGraphicsPipeline even when the QRhiRenderPassDescriptor the pipeline was
5206 originally built was is no longer available (but the data returned from its
5207 serializedFormat() still is).
5208
5209 \sa newCompatibleRenderPassDescriptor(), serializedFormat()
5210 */
5211
5212/*!
5213 \fn virtual QRhiRenderPassDescriptor *QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor() const = 0
5214
5215 \return a new QRhiRenderPassDescriptor that is
5216 \l{isCompatible()}{compatible} with this one.
5217
5218 This function allows cloning a QRhiRenderPassDescriptor. The returned
5219 object is ready to be used, and the ownership is transferred to the caller.
5220 Cloning a QRhiRenderPassDescriptor object can become useful in situations
5221 where the object is stored in data structures related to graphics pipelines
5222 (in order to allow creating new pipelines which in turn requires a
5223 renderpass descriptor object), and the lifetime of the renderpass
5224 descriptor created from a render target may be shorter than the pipelines.
5225 (for example, because the engine manages and destroys renderpasses together
5226 with the textures and render targets it was created from) In such a
5227 situation, it can be beneficial to store a cloned version in the data
5228 structures, and thus transferring ownership as well.
5229
5230 \sa isCompatible()
5231 */
5232
5233/*!
5234 \fn virtual QVector<quint32> QRhiRenderPassDescriptor::serializedFormat() const = 0
5235
5236 \return a vector of integers containing an opaque blob describing the data
5237 relevant for \l{isCompatible()}{compatibility}.
5238
5239 Given two QRhiRenderPassDescriptor objects \c rp1 and \c rp2, if the data
5240 returned from this function is identical, then \c{rp1->isCompatible(rp2)},
5241 and vice versa hold true as well.
5242
5243 \note The returned data is meant to be used for storing in memory and
5244 comparisons during the lifetime of the QRhi the object belongs to. It is not
5245 meant for storing on disk, reusing between processes, or using with multiple
5246 QRhi instances with potentially different backends.
5247
5248 \note Calling this function is expected to be a cheap operation since the
5249 backends are not supposed to calculate the data in this function, but rather
5250 return an already calculated series of data.
5251
5252 When creating reusable components as part of a library, where graphics
5253 pipelines are created and maintained while targeting a QRhiRenderTarget (be
5254 it a swapchain or a texture) managed by the client of the library, the
5255 components must be able to deal with a changing QRhiRenderPassDescriptor.
5256 For example, because the render target changes and so invalidates the
5257 previously QRhiRenderPassDescriptor (with regards to the new render target
5258 at least) due to having a potentially different color format and attachments
5259 now. Or because \l{QRhiShadingRateMap}{variable rate shading} is taken into
5260 use dynamically. A simple pattern that helps dealing with this is performing
5261 the following check on every frame, to recognize the case when the pipeline
5262 needs to be associated with a new QRhiRenderPassDescriptor, because
5263 something is different about the render target now, compared to earlier
5264 frames:
5265
5266 \code
5267 QRhiRenderPassDescriptor *rp = m_renderTarget->renderPassDescriptor();
5268 if (m_pipeline && rp->serializedFormat() != m_renderPassFormat) {
5269 m_pipeline->setRenderPassDescriptor(rp);
5270 m_renderPassFormat = rp->serializedFormat();
5271 m_pipeline->create();
5272 }
5273 // remember to store m_renderPassFormat also when creating m_pipeline the first time
5274 \endcode
5275
5276 \sa isCompatible()
5277 */
5278
5279/*!
5280 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
5281 QRhiVulkanRenderPassNativeHandles. The returned value is \nullptr when exposing
5282 the underlying native resources is not supported by the backend.
5283
5284 \sa QRhiVulkanRenderPassNativeHandles
5285 */
5286const QRhiNativeHandles *QRhiRenderPassDescriptor::nativeHandles()
5287{
5288 return nullptr;
5289}
5290
5291/*!
5292 \class QRhiRenderTarget
5293 \inmodule QtGuiPrivate
5294 \inheaderfile rhi/qrhi.h
5295 \since 6.6
5296 \brief Represents an onscreen (swapchain) or offscreen (texture) render target.
5297
5298 Applications do not create an instance of this class directly. Rather, it
5299 is the subclass QRhiTextureRenderTarget that is instantiable by clients of
5300 the API via \l{QRhi::newTextureRenderTarget()}{newTextureRenderTarget()}.
5301 The other subclass is QRhiSwapChainRenderTarget, which is the type
5302 QRhiSwapChain returns when calling
5303 \l{QRhiSwapChain::currentFrameRenderTarget()}{currentFrameRenderTarget()}.
5304
5305 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5306 for details.
5307
5308 \sa QRhiSwapChainRenderTarget, QRhiTextureRenderTarget
5309 */
5310
5311/*!
5312 \internal
5313 */
5314QRhiRenderTarget::QRhiRenderTarget(QRhiImplementation *rhi)
5315 : QRhiResource(rhi)
5316{
5317}
5318
5319/*!
5320 \fn virtual QSize QRhiRenderTarget::pixelSize() const = 0
5321
5322 \return the size in pixels.
5323
5324 Valid only after create() has been called successfully. Until then the
5325 result is a default-constructed QSize.
5326
5327 With QRhiTextureRenderTarget the returned size is the size of the
5328 associated attachments at the time of create(), in practice the size of the
5329 first color attachment, or the depth/stencil buffer if there are no color
5330 attachments. If the associated textures or renderbuffers are resized and
5331 rebuilt afterwards, then pixelSize() performs an implicit call to create()
5332 in order to rebuild the underlying data structures. This implicit check is
5333 similar to what QRhiCommandBuffer::beginPass() does, and ensures that the
5334 returned size is always up-to-date.
5335 */
5336
5337/*!
5338 \fn virtual float QRhiRenderTarget::devicePixelRatio() const = 0
5339
5340 \return the device pixel ratio. For QRhiTextureRenderTarget this is always
5341 1. For targets retrieved from a QRhiSwapChain the value reflects the
5342 \l{QWindow::devicePixelRatio()}{device pixel ratio} of the targeted
5343 QWindow.
5344 */
5345
5346/*!
5347 \fn virtual int QRhiRenderTarget::sampleCount() const = 0
5348
5349 \return the sample count or 1 if multisample antialiasing is not relevant for
5350 this render target.
5351 */
5352
5353/*!
5354 \fn QRhiRenderPassDescriptor *QRhiRenderTarget::renderPassDescriptor() const
5355
5356 \return the associated QRhiRenderPassDescriptor.
5357 */
5358
5359/*!
5360 \fn void QRhiRenderTarget::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
5361
5362 Sets the QRhiRenderPassDescriptor \a desc for use with this render target.
5363 */
5364
5365/*!
5366 \internal
5367 */
5368QRhiSwapChainRenderTarget::QRhiSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain_)
5369 : QRhiRenderTarget(rhi),
5370 m_swapchain(swapchain_)
5371{
5372}
5373
5374/*!
5375 \class QRhiSwapChainRenderTarget
5376 \inmodule QtGuiPrivate
5377 \inheaderfile rhi/qrhi.h
5378 \since 6.6
5379 \brief Swapchain render target resource.
5380
5381 When targeting the color buffers of a swapchain, active render target is a
5382 QRhiSwapChainRenderTarget. This is what
5383 QRhiSwapChain::currentFrameRenderTarget() returns.
5384
5385 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5386 for details.
5387
5388 \sa QRhiSwapChain
5389 */
5390
5391/*!
5392 \return the resource type.
5393 */
5394QRhiResource::Type QRhiSwapChainRenderTarget::resourceType() const
5395{
5396 return SwapChainRenderTarget;
5397}
5398
5399/*!
5400 \fn QRhiSwapChain *QRhiSwapChainRenderTarget::swapChain() const
5401
5402 \return the swapchain object.
5403 */
5404
5405/*!
5406 \class QRhiTextureRenderTarget
5407 \inmodule QtGuiPrivate
5408 \inheaderfile rhi/qrhi.h
5409 \since 6.6
5410 \brief Texture render target resource.
5411
5412 A texture render target allows rendering into one or more textures,
5413 optionally with a depth texture or depth/stencil renderbuffer.
5414
5415 For multisample rendering the common approach is to use a renderbuffer as
5416 the color attachment and set the non-multisample destination texture as the
5417 \c{resolve texture}. For more information, read the detailed description of
5418 the \l QRhiColorAttachment class.
5419
5420 \note Textures used in combination with QRhiTextureRenderTarget must be
5421 created with the QRhiTexture::RenderTarget flag.
5422
5423 The simplest example of creating a render target with a texture as its
5424 single color attachment:
5425
5426 \code
5427 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
5428 texture->create();
5429 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture });
5430 rp = rt->newCompatibleRenderPassDescriptor();
5431 rt->setRenderPassDescriptor(rp);
5432 rt->create();
5433 // rt can now be used with beginPass()
5434 \endcode
5435
5436 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5437 for details.
5438 */
5439
5440/*!
5441 \enum QRhiTextureRenderTarget::Flag
5442
5443 Flag values describing the load/store behavior for the render target. The
5444 load/store behavior may be baked into native resources under the hood,
5445 depending on the backend, and therefore it needs to be known upfront and
5446 cannot be changed without rebuilding (and so releasing and creating new
5447 native resources).
5448
5449 \value PreserveColorContents Indicates that the contents of the color
5450 attachments is to be loaded when starting a render pass, instead of
5451 clearing. This is potentially more expensive, especially on mobile (tiled)
5452 GPUs, but allows preserving the existing contents between passes. When doing
5453 multisample rendering with a resolve texture set, setting this flag also
5454 requests the multisample color data to be stored (written out) to the
5455 multisample texture or render buffer. (for non-multisample rendering the
5456 color data is always stored, but for MSAA storing the multisample data
5457 decreases efficiency for certain GPU architectures, hence defaulting to not
5458 writing it out) Note however that this is non-portable: in some cases there
5459 is no intermediate multisample texture on the graphics API level, e.g. when
5460 using OpenGL ES's \c{GL_EXT_multisampled_render_to_texture} as it is all
5461 implicit, handled by the OpenGL ES implementation. In that case,
5462 PreserveColorContents will likely have no effect. Therefore, avoid relying
5463 on this flag when using multisample rendering and the color attachment is
5464 using a multisample QRhiTexture (not QRhiRenderBuffer).
5465
5466 \value PreserveDepthStencilContents Indicates that the contents of the
5467 depth texture is to be loaded when starting a render pass, instead
5468 clearing. Only applicable when a texture is used as the depth buffer
5469 (QRhiTextureRenderTargetDescription::depthTexture() is set) because
5470 depth/stencil renderbuffers may not have any physical backing and data may
5471 not be written out in the first place.
5472
5473 \value DoNotStoreDepthStencilContents Indicates that the contents of the
5474 depth texture does not need to be written out. Relevant only when a
5475 QRhiTexture, not QRhiRenderBuffer, is used as the depth-stencil buffer,
5476 because for QRhiRenderBuffer this is implicit. When a depthResolveTexture is
5477 set, the flag is not relevant, because the behavior is then as if the flag
5478 was set. This enum value is introduced in Qt 6.8.
5479 */
5480
5481/*!
5482 \internal
5483 */
5484QRhiTextureRenderTarget::QRhiTextureRenderTarget(QRhiImplementation *rhi,
5485 const QRhiTextureRenderTargetDescription &desc_,
5486 Flags flags_)
5487 : QRhiRenderTarget(rhi),
5488 m_desc(desc_),
5489 m_flags(flags_)
5490{
5491}
5492
5493/*!
5494 \return the resource type.
5495 */
5496QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
5497{
5498 return TextureRenderTarget;
5499}
5500
5501/*!
5502 \fn virtual QRhiRenderPassDescriptor *QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() = 0
5503
5504 \return a new QRhiRenderPassDescriptor that is compatible with this render
5505 target.
5506
5507 The returned value is used in two ways: it can be passed to
5508 setRenderPassDescriptor() and
5509 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
5510 describes the attachments (color, depth/stencil) and the load/store
5511 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
5512 be used in combination with a render target that has a
5513 \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
5514 QRhiRenderPassDescriptor set.
5515
5516 Two QRhiTextureRenderTarget instances can share the same render pass
5517 descriptor as long as they have the same number and type of attachments.
5518 The associated QRhiTexture or QRhiRenderBuffer instances are not part of
5519 the render pass descriptor so those can differ in the two
5520 QRhiTextureRenderTarget instances.
5521
5522 \note resources, such as QRhiTexture instances, referenced in description()
5523 must already have create() called on them.
5524
5525 \sa create()
5526 */
5527
5528/*!
5529 \fn virtual bool QRhiTextureRenderTarget::create() = 0
5530
5531 Creates the corresponding native graphics resources. If there are already
5532 resources present due to an earlier create() with no corresponding
5533 destroy(), then destroy() is called implicitly first.
5534
5535 \note renderPassDescriptor() must be set before calling create(). To obtain
5536 a QRhiRenderPassDescriptor compatible with the render target, call
5537 newCompatibleRenderPassDescriptor() before create() but after setting all
5538 other parameters, such as description() and flags(). To save resources,
5539 reuse the same QRhiRenderPassDescriptor with multiple
5540 QRhiTextureRenderTarget instances, whenever possible. Sharing the same
5541 render pass descriptor is only possible when the render targets have the
5542 same number and type of attachments (the actual textures can differ) and
5543 the same flags.
5544
5545 \note resources, such as QRhiTexture instances, referenced in description()
5546 must already have create() called on them.
5547
5548 \return \c true when successful, \c false when a graphics operation failed.
5549 Regardless of the return value, calling destroy() is always safe.
5550 */
5551
5552/*!
5553 \fn QRhiTextureRenderTargetDescription QRhiTextureRenderTarget::description() const
5554 \return the render target description.
5555 */
5556
5557/*!
5558 \fn void QRhiTextureRenderTarget::setDescription(const QRhiTextureRenderTargetDescription &desc)
5559 Sets the render target description \a desc.
5560 */
5561
5562/*!
5563 \fn QRhiTextureRenderTarget::Flags QRhiTextureRenderTarget::flags() const
5564 \return the currently set flags.
5565 */
5566
5567/*!
5568 \fn void QRhiTextureRenderTarget::setFlags(Flags f)
5569 Sets the flags to \a f.
5570 */
5571
5572/*!
5573 \class QRhiShaderResourceBindings
5574 \inmodule QtGuiPrivate
5575 \inheaderfile rhi/qrhi.h
5576 \since 6.6
5577 \brief Encapsulates resources for making buffer, texture, sampler resources visible to shaders.
5578
5579 A QRhiShaderResourceBindings is a collection of QRhiShaderResourceBinding
5580 objects, each of which describe a single binding.
5581
5582 Take a fragment shader with the following interface:
5583
5584 \badcode
5585 layout(std140, binding = 0) uniform buf {
5586 mat4 mvp;
5587 int flip;
5588 } ubuf;
5589
5590 layout(binding = 1) uniform sampler2D tex;
5591 \endcode
5592
5593 To make resources visible to the shader, the following
5594 QRhiShaderResourceBindings could be created and then passed to
5595 QRhiGraphicsPipeline::setShaderResourceBindings():
5596
5597 \code
5598 QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings();
5599 srb->setBindings({
5600 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf),
5601 QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler)
5602 });
5603 srb->create();
5604 // ...
5605 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
5606 // ...
5607 ps->setShaderResourceBindings(srb);
5608 ps->create();
5609 // ...
5610 cb->setGraphicsPipeline(ps);
5611 cb->setShaderResources(); // binds srb
5612 \endcode
5613
5614 This assumes that \c ubuf is a QRhiBuffer, \c texture is a QRhiTexture,
5615 while \a sampler is a QRhiSampler. The example also assumes that the
5616 uniform block is present in the vertex shader as well so the same buffer is
5617 made visible to the vertex stage too.
5618
5619 \section3 Advanced usage
5620
5621 Building on the above example, let's assume that a pass now needs to use
5622 the exact same pipeline and shaders with a different texture. Creating a
5623 whole separate QRhiGraphicsPipeline just for this would be an overkill.
5624 This is why QRhiCommandBuffer::setShaderResources() allows specifying a \a
5625 srb argument. As long as the layouts (so the number of bindings and the
5626 binding points) match between two QRhiShaderResourceBindings, they can both
5627 be used with the same pipeline, assuming the pipeline was created with one of
5628 them in the first place. See isLayoutCompatible() for more details.
5629
5630 \code
5631 QRhiShaderResourceBindings *srb2 = rhi->newShaderResourceBindings();
5632 // ...
5633 cb->setGraphicsPipeline(ps);
5634 cb->setShaderResources(srb2); // binds srb2
5635 \endcode
5636
5637 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5638 for details.
5639 */
5640
5641/*!
5642 \typedef QRhiShaderResourceBindingSet
5643 \relates QRhi
5644 \since 6.7
5645
5646 Synonym for QRhiShaderResourceBindings.
5647*/
5648
5649/*!
5650 \internal
5651 */
5652QRhiShaderResourceBindings::QRhiShaderResourceBindings(QRhiImplementation *rhi)
5653 : QRhiResource(rhi)
5654{
5655 m_layoutDesc.reserve(BINDING_PREALLOC * QRhiShaderResourceBinding::LAYOUT_DESC_ENTRIES_PER_BINDING);
5656}
5657
5658/*!
5659 \return the resource type.
5660 */
5661QRhiResource::Type QRhiShaderResourceBindings::resourceType() const
5662{
5663 return ShaderResourceBindings;
5664}
5665
5666/*!
5667 \return \c true if the layout is compatible with \a other. The layout does
5668 not include the actual resource (such as, buffer or texture) and related
5669 parameters (such as, offset or size). It does include the binding point,
5670 pipeline stage, and resource type, however. The number and order of the
5671 bindings must also match in order to be compatible.
5672
5673 When there is a QRhiGraphicsPipeline created with this
5674 QRhiShaderResourceBindings, and the function returns \c true, \a other can
5675 then safely be passed to QRhiCommandBuffer::setShaderResources(), and so
5676 be used with the pipeline in place of this QRhiShaderResourceBindings.
5677
5678 \note This function must only be called after a successful create(), because
5679 it relies on data generated during the baking of the underlying data
5680 structures. This way the function can implement a comparison approach that
5681 is more efficient than iterating through two binding lists and calling
5682 QRhiShaderResourceBinding::isLayoutCompatible() on each pair. This becomes
5683 relevant especially when this function is called at a high frequency.
5684
5685 \sa serializedLayoutDescription()
5686 */
5687bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBindings *other) const
5688{
5689 if (other == this)
5690 return true;
5691
5692 if (!other)
5693 return false;
5694
5695 // This can become a hot code path. Therefore we do not iterate and call
5696 // isLayoutCompatible() on m_bindings, but rather check a pre-calculated
5697 // hash code and then, if the hash matched, do a uint array comparison
5698 // (that's still more cache friendly).
5699
5700 return m_layoutDescHash == other->m_layoutDescHash
5701 && m_layoutDesc == other->m_layoutDesc;
5702}
5703
5704/*!
5705 \fn QVector<quint32> QRhiShaderResourceBindings::serializedLayoutDescription() const
5706
5707 \return a vector of integers containing an opaque blob describing the layout
5708 of the binding list, i.e. the data relevant for
5709 \l{isLayoutCompatible()}{layout compatibility tests}.
5710
5711 Given two objects \c srb1 and \c srb2, if the data returned from this
5712 function is identical, then \c{srb1->isLayoutCompatible(srb2)}, and vice
5713 versa hold true as well.
5714
5715 \note The returned data is meant to be used for storing in memory and
5716 comparisons during the lifetime of the QRhi the object belongs to. It is not
5717 meant for storing on disk, reusing between processes, or using with multiple
5718 QRhi instances with potentially different backends.
5719
5720 \sa isLayoutCompatible()
5721 */
5722
5723void QRhiImplementation::updateLayoutDesc(QRhiShaderResourceBindings *srb)
5724{
5725 srb->m_layoutDescHash = 0;
5726 srb->m_layoutDesc.clear();
5727 auto layoutDescAppender = std::back_inserter(srb->m_layoutDesc);
5728 for (const QRhiShaderResourceBinding &b : std::as_const(srb->m_bindings)) {
5729 const QRhiShaderResourceBinding::Data *d = &b.d;
5730 srb->m_layoutDescHash ^= uint(d->binding) ^ uint(d->stage) ^ uint(d->type)
5731 ^ uint(d->arraySize());
5732 layoutDescAppender = d->serialize(layoutDescAppender);
5733 }
5734}
5735
5736/*!
5737 \fn virtual bool QRhiShaderResourceBindings::create() = 0
5738
5739 Creates the corresponding resource binding set. Depending on the underlying
5740 graphics API, this may involve creating native graphics resources, and
5741 therefore it should not be assumed that this is a cheap operation.
5742
5743 If create() has been called before with no corresponding destroy(), then
5744 destroy() is called implicitly first.
5745
5746 \return \c true when successful, \c false when failed.
5747 Regardless of the return value, calling destroy() is always safe.
5748 */
5749
5750/*!
5751 \fn void QRhiShaderResourceBindings::setBindings(std::initializer_list<QRhiShaderResourceBinding> list)
5752 Sets the \a list of bindings.
5753 */
5754
5755/*!
5756 \fn template<typename InputIterator> void QRhiShaderResourceBindings::setBindings(InputIterator first, InputIterator last)
5757 Sets the list of bindings from the iterators \a first and \a last.
5758 */
5759
5760/*!
5761 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cbeginBindings() const
5762 \return a const iterator pointing to the first item in the binding list.
5763 */
5764
5765/*!
5766 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cendBindings() const
5767 \return a const iterator pointing just after the last item in the binding list.
5768 */
5769
5770/*!
5771 \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::bindingAt(qsizetype index) const
5772 \return the binding at the specified \a index.
5773 */
5774
5775/*!
5776 \fn qsizetype QRhiShaderResourceBindings::bindingCount() const
5777 \return the number of bindings.
5778 */
5779
5780/*!
5781 \class QRhiShaderResourceBinding
5782 \inmodule QtGuiPrivate
5783 \inheaderfile rhi/qrhi.h
5784 \since 6.6
5785 \brief Describes the shader resource for a single binding point.
5786
5787 A QRhiShaderResourceBinding cannot be constructed directly. Instead, use the
5788 static functions such as uniformBuffer() or sampledTexture() to get an
5789 instance.
5790
5791 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5792 for details.
5793 */
5794
5795/*!
5796 \enum QRhiShaderResourceBinding::Type
5797 Specifies type of the shader resource bound to a binding point
5798
5799 \value UniformBuffer Uniform buffer
5800
5801 \value SampledTexture Combined image sampler (a texture and sampler pair).
5802 Even when the shading language associated with the underlying 3D API has no
5803 support for this concept (e.g. D3D and HLSL), this is still supported
5804 because the shader translation layer takes care of the appropriate
5805 translation and remapping of binding points or shader registers.
5806
5807 \value Texture Texture (separate)
5808
5809 \value Sampler Sampler (separate)
5810
5811 \value ImageLoad Image load (with GLSL this maps to doing imageLoad() on a
5812 single level - and either one or all layers - of a texture exposed to the
5813 shader as an image object)
5814
5815 \value ImageStore Image store (with GLSL this maps to doing imageStore() or
5816 imageAtomic*() on a single level - and either one or all layers - of a
5817 texture exposed to the shader as an image object)
5818
5819 \value ImageLoadStore Image load and store
5820
5821 \value BufferLoad Storage buffer load (with GLSL this maps to reading from
5822 a shader storage buffer)
5823
5824 \value BufferStore Storage buffer store (with GLSL this maps to writing to
5825 a shader storage buffer)
5826
5827 \value BufferLoadStore Storage buffer load and store
5828 */
5829
5830/*!
5831 \enum QRhiShaderResourceBinding::StageFlag
5832 Flag values to indicate which stages the shader resource is visible in
5833
5834 \value VertexStage Vertex stage
5835 \value TessellationControlStage Tessellation control (hull shader) stage
5836 \value TessellationEvaluationStage Tessellation evaluation (domain shader) stage
5837 \value FragmentStage Fragment (pixel shader) stage
5838 \value ComputeStage Compute stage
5839 \value GeometryStage Geometry stage
5840 */
5841
5842/*!
5843 \return \c true if the layout is compatible with \a other. The layout does not
5844 include the actual resource (such as, buffer or texture) and related
5845 parameters (such as, offset or size).
5846
5847 For example, \c a and \c b below are not equal, but are compatible layout-wise:
5848
5849 \code
5850 auto a = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buffer);
5851 auto b = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, someOtherBuffer, 256);
5852 \endcode
5853 */
5854bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBinding &other) const
5855{
5856 // everything that goes into a VkDescriptorSetLayoutBinding must match
5857 return d.binding == other.d.binding
5858 && d.stage == other.d.stage
5859 && d.type == other.d.type
5860 && d.arraySize() == other.d.arraySize();
5861}
5862
5863/*!
5864 \return a shader resource binding for the given binding number, pipeline
5865 stages, and buffer specified by \a binding, \a stage, and \a buf.
5866
5867 \note When \a buf is not null, it must have been created with
5868 QRhiBuffer::UniformBuffer.
5869
5870 \note \a buf can be null. It is valid to create a
5871 QRhiShaderResourceBindings with unspecified resources, but such an object
5872 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
5873 suitable for creating pipelines. Such a pipeline must then always be used
5874 together with another, layout compatible QRhiShaderResourceBindings with
5875 resources present passed to QRhiCommandBuffer::setShaderResources().
5876
5877 \note If the size of \a buf exceeds the limit reported for
5878 QRhi::MaxUniformBufferRange, unexpected errors may occur.
5879 */
5880QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
5881 int binding, StageFlags stage, QRhiBuffer *buf)
5882{
5883 QRhiShaderResourceBinding b;
5884 b.d.binding = binding;
5885 b.d.stage = stage;
5886 b.d.type = UniformBuffer;
5887 b.d.u.ubuf.buf = buf;
5888 b.d.u.ubuf.offset = 0;
5889 b.d.u.ubuf.maybeSize = 0; // entire buffer
5890 b.d.u.ubuf.hasDynamicOffset = false;
5891 return b;
5892}
5893
5894/*!
5895 \return a shader resource binding for the given binding number, pipeline
5896 stages, and buffer specified by \a binding, \a stage, and \a buf. This
5897 overload binds a region only, as specified by \a offset and \a size.
5898
5899 \note It is up to the user to ensure the offset is aligned to
5900 QRhi::ubufAlignment().
5901
5902 \note \a size must be greater than 0.
5903
5904 \note When \a buf is not null, it must have been created with
5905 QRhiBuffer::UniformBuffer.
5906
5907 \note \a buf can be null. It is valid to create a
5908 QRhiShaderResourceBindings with unspecified resources, but such an object
5909 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
5910 suitable for creating pipelines. Such a pipeline must then always be used
5911 together with another, layout compatible QRhiShaderResourceBindings with
5912 resources present passed to QRhiCommandBuffer::setShaderResources().
5913
5914 \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
5915 unexpected errors may occur.
5916 */
5917QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
5918 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
5919{
5920 Q_ASSERT(size > 0);
5921 QRhiShaderResourceBinding b;
5922 b.d.binding = binding;
5923 b.d.stage = stage;
5924 b.d.type = UniformBuffer;
5925 b.d.u.ubuf.buf = buf;
5926 b.d.u.ubuf.offset = offset;
5927 b.d.u.ubuf.maybeSize = size;
5928 b.d.u.ubuf.hasDynamicOffset = false;
5929 return b;
5930}
5931
5932/*!
5933 \return a shader resource binding for the given binding number, pipeline
5934 stages, and buffer specified by \a binding, \a stage, and \a buf. The
5935 uniform buffer is assumed to have dynamic offset. The dynamic offset can be
5936 specified in QRhiCommandBuffer::setShaderResources(), thus allowing using
5937 varying offset values without creating new bindings for the buffer. The
5938 size of the bound region is specified by \a size. Like with non-dynamic
5939 offsets, \c{offset + size} cannot exceed the size of \a buf.
5940
5941 \note When \a buf is not null, it must have been created with
5942 QRhiBuffer::UniformBuffer.
5943
5944 \note \a buf can be null. It is valid to create a
5945 QRhiShaderResourceBindings with unspecified resources, but such an object
5946 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
5947 suitable for creating pipelines. Such a pipeline must then always be used
5948 together with another, layout compatible QRhiShaderResourceBindings with
5949 resources present passed to QRhiCommandBuffer::setShaderResources().
5950
5951 \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
5952 unexpected errors may occur.
5953 */
5954QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(
5955 int binding, StageFlags stage, QRhiBuffer *buf, quint32 size)
5956{
5957 Q_ASSERT(size > 0);
5958 QRhiShaderResourceBinding b;
5959 b.d.binding = binding;
5960 b.d.stage = stage;
5961 b.d.type = UniformBuffer;
5962 b.d.u.ubuf.buf = buf;
5963 b.d.u.ubuf.offset = 0;
5964 b.d.u.ubuf.maybeSize = size;
5965 b.d.u.ubuf.hasDynamicOffset = true;
5966 return b;
5967}
5968
5969/*!
5970 \return a shader resource binding for the given binding number, pipeline
5971 stages, texture, and sampler specified by \a binding, \a stage, \a tex,
5972 \a sampler.
5973
5974 \note This function is equivalent to calling sampledTextures() with a
5975 \c count of 1.
5976
5977 \note \a tex and \a sampler can be null. It is valid to create a
5978 QRhiShaderResourceBindings with unspecified resources, but such an object
5979 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
5980 suitable for creating pipelines. Such a pipeline must then always be used
5981 together with another, layout compatible QRhiShaderResourceBindings with
5982 resources present passed to QRhiCommandBuffer::setShaderResources().
5983
5984 \note A shader may not be able to consume more than 16 textures/samplers,
5985 depending on the underlying graphics API. This hard limit must be kept in
5986 mind in renderer design. This does not apply to texture arrays which
5987 consume a single binding point (shader register) and can contain 256-2048
5988 textures, depending on the underlying graphics API. Arrays of textures (see
5989 sampledTextures()) are however no different in this regard than using the
5990 same number of individual textures.
5991
5992 \sa sampledTextures()
5993 */
5994QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
5995 int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
5996{
5997 QRhiShaderResourceBinding b;
5998 b.d.binding = binding;
5999 b.d.stage = stage;
6000 b.d.type = SampledTexture;
6001 b.d.u.stex.count = 1;
6002 b.d.u.stex.texSamplers[0] = { tex, sampler };
6003 return b;
6004}
6005
6006/*!
6007 \return a shader resource binding for the given binding number, pipeline
6008 stages, and the array of texture-sampler pairs specified by \a binding, \a
6009 stage, \a count, and \a texSamplers.
6010
6011 \note \a count must be at least 1, and not larger than 16.
6012
6013 \note When \a count is 1, this function is equivalent to sampledTexture().
6014
6015 This function is relevant when arrays of combined image samplers are
6016 involved. For example, in GLSL \c{layout(binding = 5) uniform sampler2D
6017 shadowMaps[8];} declares an array of combined image samplers. The
6018 application is then expected provide a QRhiShaderResourceBinding for
6019 binding point 5, set up by calling this function with \a count set to 8 and
6020 a valid texture and sampler for each element of the array.
6021
6022 \warning All elements of the array must be specified. With the above
6023 example, the only valid, portable approach is calling this function with a
6024 \a count of 8. Additionally, all QRhiTexture and QRhiSampler instances must
6025 be valid, meaning nullptr is not an accepted value. This is due to some of
6026 the underlying APIs, such as, Vulkan, that require a valid image and
6027 sampler object for each element in descriptor arrays. Applications are
6028 advised to provide "dummy" samplers and textures if some array elements are
6029 not relevant (due to not being accessed in the shader).
6030
6031 \note \a texSamplers can be null. It is valid to create a
6032 QRhiShaderResourceBindings with unspecified resources, but such an object
6033 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6034 suitable for creating pipelines. Such a pipeline must then always be used
6035 together with another, layout compatible QRhiShaderResourceBindings with
6036 resources present passed to QRhiCommandBuffer::setShaderResources().
6037
6038 \sa sampledTexture()
6039 */
6040QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTextures(
6041 int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers)
6042{
6043 Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
6044 QRhiShaderResourceBinding b;
6045 b.d.binding = binding;
6046 b.d.stage = stage;
6047 b.d.type = SampledTexture;
6048 b.d.u.stex.count = count;
6049 for (int i = 0; i < count; ++i) {
6050 if (texSamplers)
6051 b.d.u.stex.texSamplers[i] = texSamplers[i];
6052 else
6053 b.d.u.stex.texSamplers[i] = { nullptr, nullptr };
6054 }
6055 return b;
6056}
6057
6058/*!
6059 \return a shader resource binding for the given binding number, pipeline
6060 stages, and texture specified by \a binding, \a stage, \a tex.
6061
6062 \note This function is equivalent to calling textures() with a
6063 \c count of 1.
6064
6065 \note \a tex can be null. It is valid to create a
6066 QRhiShaderResourceBindings with unspecified resources, but such an object
6067 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6068 suitable for creating pipelines. Such a pipeline must then always be used
6069 together with another, layout compatible QRhiShaderResourceBindings with
6070 resources present passed to QRhiCommandBuffer::setShaderResources().
6071
6072 This creates a binding for a separate texture (image) object, whereas
6073 sampledTexture() is suitable for combined image samplers. In
6074 Vulkan-compatible GLSL code separate textures are declared as \c texture2D
6075 as opposed to \c sampler2D: \c{layout(binding = 1) uniform texture2D tex;}
6076
6077 \note A shader may not be able to consume more than 16 textures, depending
6078 on the underlying graphics API. This hard limit must be kept in mind in
6079 renderer design. This does not apply to texture arrays which consume a
6080 single binding point (shader register) and can contain 256-2048 textures,
6081 depending on the underlying graphics API. Arrays of textures (see
6082 sampledTextures()) are however no different in this regard than using the
6083 same number of individual textures.
6084
6085 \sa textures(), sampler()
6086 */
6087QRhiShaderResourceBinding QRhiShaderResourceBinding::texture(int binding, StageFlags stage, QRhiTexture *tex)
6088{
6089 QRhiShaderResourceBinding b;
6090 b.d.binding = binding;
6091 b.d.stage = stage;
6092 b.d.type = Texture;
6093 b.d.u.stex.count = 1;
6094 b.d.u.stex.texSamplers[0] = { tex, nullptr };
6095 return b;
6096}
6097
6098/*!
6099 \return a shader resource binding for the given binding number, pipeline
6100 stages, and the array of (separate) textures specified by \a binding, \a
6101 stage, \a count, and \a tex.
6102
6103 \note \a count must be at least 1, and not larger than 16.
6104
6105 \note When \a count is 1, this function is equivalent to texture().
6106
6107 \warning All elements of the array must be specified.
6108
6109 \note \a tex can be null. It is valid to create a
6110 QRhiShaderResourceBindings with unspecified resources, but such an object
6111 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6112 suitable for creating pipelines. Such a pipeline must then always be used
6113 together with another, layout compatible QRhiShaderResourceBindings with
6114 resources present passed to QRhiCommandBuffer::setShaderResources().
6115
6116 \sa texture(), sampler()
6117 */
6118QRhiShaderResourceBinding QRhiShaderResourceBinding::textures(int binding, StageFlags stage, int count, QRhiTexture **tex)
6119{
6120 Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
6121 QRhiShaderResourceBinding b;
6122 b.d.binding = binding;
6123 b.d.stage = stage;
6124 b.d.type = Texture;
6125 b.d.u.stex.count = count;
6126 for (int i = 0; i < count; ++i) {
6127 if (tex)
6128 b.d.u.stex.texSamplers[i] = { tex[i], nullptr };
6129 else
6130 b.d.u.stex.texSamplers[i] = { nullptr, nullptr };
6131 }
6132 return b;
6133}
6134
6135/*!
6136 \return a shader resource binding for the given binding number, pipeline
6137 stages, and sampler specified by \a binding, \a stage, \a sampler.
6138
6139 \note \a sampler can be null. It is valid to create a
6140 QRhiShaderResourceBindings with unspecified resources, but such an object
6141 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6142 suitable for creating pipelines. Such a pipeline must then always be used
6143 together with another, layout compatible QRhiShaderResourceBindings with
6144 resources present passed to QRhiCommandBuffer::setShaderResources().
6145
6146 Arrays of separate samplers are not supported.
6147
6148 This creates a binding for a separate sampler object, whereas
6149 sampledTexture() is suitable for combined image samplers. In
6150 Vulkan-compatible GLSL code separate samplers are declared as \c sampler
6151 as opposed to \c sampler2D: \c{layout(binding = 2) uniform sampler samp;}
6152
6153 With both a \c texture2D and \c sampler present, they can be used together
6154 to sample the texture: \c{fragColor = texture(sampler2D(tex, samp),
6155 texcoord);}.
6156
6157 \note A shader may not be able to consume more than 16 samplers, depending
6158 on the underlying graphics API. This hard limit must be kept in mind in
6159 renderer design.
6160
6161 \sa texture()
6162 */
6163QRhiShaderResourceBinding QRhiShaderResourceBinding::sampler(int binding, StageFlags stage, QRhiSampler *sampler)
6164{
6165 QRhiShaderResourceBinding b;
6166 b.d.binding = binding;
6167 b.d.stage = stage;
6168 b.d.type = Sampler;
6169 b.d.u.stex.count = 1;
6170 b.d.u.stex.texSamplers[0] = { nullptr, sampler };
6171 return b;
6172}
6173
6174/*!
6175 \return a shader resource binding for a read-only storage image with the
6176 given \a binding number and pipeline \a stage. The image load operations
6177 will have access to all layers of the specified \a level. (so if the texture
6178 is a cubemap, the shader must use imageCube instead of image2D)
6179
6180 \note When \a tex is not null, it must have been created with
6181 QRhiTexture::UsedWithLoadStore.
6182
6183 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6184 with unspecified resources, but such an object cannot be used with
6185 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6186 pipelines. Such a pipeline must then always be used together with another,
6187 layout compatible QRhiShaderResourceBindings with resources present passed
6188 to QRhiCommandBuffer::setShaderResources().
6189
6190 \note Image load/store is only available within the compute and fragment stages.
6191 */
6192QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoad(
6193 int binding, StageFlags stage, QRhiTexture *tex, int level)
6194{
6195 QRhiShaderResourceBinding b;
6196 b.d.binding = binding;
6197 b.d.stage = stage;
6198 b.d.type = ImageLoad;
6199 b.d.u.simage.tex = tex;
6200 b.d.u.simage.level = level;
6201 return b;
6202}
6203
6204/*!
6205 \return a shader resource binding for a write-only storage image with the
6206 given \a binding number and pipeline \a stage. The image store operations
6207 will have access to all layers of the specified \a level. (so if the texture
6208 is a cubemap, the shader must use imageCube instead of image2D)
6209
6210 \note When \a tex is not null, it must have been created with
6211 QRhiTexture::UsedWithLoadStore.
6212
6213 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6214 with unspecified resources, but such an object cannot be used with
6215 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6216 pipelines. Such a pipeline must then always be used together with another,
6217 layout compatible QRhiShaderResourceBindings with resources present passed
6218 to QRhiCommandBuffer::setShaderResources().
6219
6220 \note Image load/store is only available within the compute and fragment stages.
6221 */
6222QRhiShaderResourceBinding QRhiShaderResourceBinding::imageStore(
6223 int binding, StageFlags stage, QRhiTexture *tex, int level)
6224{
6225 QRhiShaderResourceBinding b;
6226 b.d.binding = binding;
6227 b.d.stage = stage;
6228 b.d.type = ImageStore;
6229 b.d.u.simage.tex = tex;
6230 b.d.u.simage.level = level;
6231 return b;
6232}
6233
6234/*!
6235 \return a shader resource binding for a read/write storage image with the
6236 given \a binding number and pipeline \a stage. The image load/store operations
6237 will have access to all layers of the specified \a level. (so if the texture
6238 is a cubemap, the shader must use imageCube instead of image2D)
6239
6240 \note When \a tex is not null, it must have been created with
6241 QRhiTexture::UsedWithLoadStore.
6242
6243 \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6244 with unspecified resources, but such an object cannot be used with
6245 QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6246 pipelines. Such a pipeline must then always be used together with another,
6247 layout compatible QRhiShaderResourceBindings with resources present passed
6248 to QRhiCommandBuffer::setShaderResources().
6249
6250 \note Image load/store is only available within the compute and fragment stages.
6251 */
6252QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoadStore(
6253 int binding, StageFlags stage, QRhiTexture *tex, int level)
6254{
6255 QRhiShaderResourceBinding b;
6256 b.d.binding = binding;
6257 b.d.stage = stage;
6258 b.d.type = ImageLoadStore;
6259 b.d.u.simage.tex = tex;
6260 b.d.u.simage.level = level;
6261 return b;
6262}
6263
6264/*!
6265 \return a shader resource binding for a read-only storage buffer with the
6266 given \a binding number and pipeline \a stage.
6267
6268 \note When \a buf is not null, must have been created with
6269 QRhiBuffer::StorageBuffer.
6270
6271 \note \a buf can be null. It is valid to create a
6272 QRhiShaderResourceBindings with unspecified resources, but such an object
6273 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6274 suitable for creating pipelines. Such a pipeline must then always be used
6275 together with another, layout compatible QRhiShaderResourceBindings with
6276 resources present passed to QRhiCommandBuffer::setShaderResources().
6277
6278 \note Buffer load/store is only guaranteed to be available within a compute
6279 pipeline. While some backends may support using these resources in a
6280 graphics pipeline as well, this is not universally supported, and even when
6281 it is, unexpected problems may arise when it comes to barriers and
6282 synchronization. Therefore, avoid using such resources with shaders other
6283 than compute.
6284 */
6285QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6286 int binding, StageFlags stage, QRhiBuffer *buf)
6287{
6288 QRhiShaderResourceBinding b;
6289 b.d.binding = binding;
6290 b.d.stage = stage;
6291 b.d.type = BufferLoad;
6292 b.d.u.sbuf.buf = buf;
6293 b.d.u.sbuf.offset = 0;
6294 b.d.u.sbuf.maybeSize = 0; // entire buffer
6295 return b;
6296}
6297
6298/*!
6299 \return a shader resource binding for a read-only storage buffer with the
6300 given \a binding number and pipeline \a stage. This overload binds a region
6301 only, as specified by \a offset and \a size.
6302
6303 \note When \a buf is not null, must have been created with
6304 QRhiBuffer::StorageBuffer.
6305
6306 \note \a buf can be null. It is valid to create a
6307 QRhiShaderResourceBindings with unspecified resources, but such an object
6308 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6309 suitable for creating pipelines. Such a pipeline must then always be used
6310 together with another, layout compatible QRhiShaderResourceBindings with
6311 resources present passed to QRhiCommandBuffer::setShaderResources().
6312
6313 \note Buffer load/store is only guaranteed to be available within a compute
6314 pipeline. While some backends may support using these resources in a
6315 graphics pipeline as well, this is not universally supported, and even when
6316 it is, unexpected problems may arise when it comes to barriers and
6317 synchronization. Therefore, avoid using such resources with shaders other
6318 than compute.
6319 */
6320QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6321 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6322{
6323 Q_ASSERT(size > 0);
6324 QRhiShaderResourceBinding b;
6325 b.d.binding = binding;
6326 b.d.stage = stage;
6327 b.d.type = BufferLoad;
6328 b.d.u.sbuf.buf = buf;
6329 b.d.u.sbuf.offset = offset;
6330 b.d.u.sbuf.maybeSize = size;
6331 return b;
6332}
6333
6334/*!
6335 \return a shader resource binding for a write-only storage buffer with the
6336 given \a binding number and pipeline \a stage.
6337
6338 \note When \a buf is not null, must have been created with
6339 QRhiBuffer::StorageBuffer.
6340
6341 \note \a buf can be null. It is valid to create a
6342 QRhiShaderResourceBindings with unspecified resources, but such an object
6343 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6344 suitable for creating pipelines. Such a pipeline must then always be used
6345 together with another, layout compatible QRhiShaderResourceBindings with
6346 resources present passed to QRhiCommandBuffer::setShaderResources().
6347
6348 \note Buffer load/store is only guaranteed to be available within a compute
6349 pipeline. While some backends may support using these resources in a
6350 graphics pipeline as well, this is not universally supported, and even when
6351 it is, unexpected problems may arise when it comes to barriers and
6352 synchronization. Therefore, avoid using such resources with shaders other
6353 than compute.
6354 */
6355QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6356 int binding, StageFlags stage, QRhiBuffer *buf)
6357{
6358 QRhiShaderResourceBinding b;
6359 b.d.binding = binding;
6360 b.d.stage = stage;
6361 b.d.type = BufferStore;
6362 b.d.u.sbuf.buf = buf;
6363 b.d.u.sbuf.offset = 0;
6364 b.d.u.sbuf.maybeSize = 0; // entire buffer
6365 return b;
6366}
6367
6368/*!
6369 \return a shader resource binding for a write-only storage buffer with the
6370 given \a binding number and pipeline \a stage. This overload binds a region
6371 only, as specified by \a offset and \a size.
6372
6373 \note When \a buf is not null, must have been created with
6374 QRhiBuffer::StorageBuffer.
6375
6376 \note \a buf can be null. It is valid to create a
6377 QRhiShaderResourceBindings with unspecified resources, but such an object
6378 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6379 suitable for creating pipelines. Such a pipeline must then always be used
6380 together with another, layout compatible QRhiShaderResourceBindings with
6381 resources present passed to QRhiCommandBuffer::setShaderResources().
6382
6383 \note Buffer load/store is only guaranteed to be available within a compute
6384 pipeline. While some backends may support using these resources in a
6385 graphics pipeline as well, this is not universally supported, and even when
6386 it is, unexpected problems may arise when it comes to barriers and
6387 synchronization. Therefore, avoid using such resources with shaders other
6388 than compute.
6389 */
6390QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6391 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6392{
6393 Q_ASSERT(size > 0);
6394 QRhiShaderResourceBinding b;
6395 b.d.binding = binding;
6396 b.d.stage = stage;
6397 b.d.type = BufferStore;
6398 b.d.u.sbuf.buf = buf;
6399 b.d.u.sbuf.offset = offset;
6400 b.d.u.sbuf.maybeSize = size;
6401 return b;
6402}
6403
6404/*!
6405 \return a shader resource binding for a read-write storage buffer with the
6406 given \a binding number and pipeline \a stage.
6407
6408 \note When \a buf is not null, must have been created with
6409 QRhiBuffer::StorageBuffer.
6410
6411 \note \a buf can be null. It is valid to create a
6412 QRhiShaderResourceBindings with unspecified resources, but such an object
6413 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6414 suitable for creating pipelines. Such a pipeline must then always be used
6415 together with another, layout compatible QRhiShaderResourceBindings with
6416 resources present passed to QRhiCommandBuffer::setShaderResources().
6417
6418 \note Buffer load/store is only guaranteed to be available within a compute
6419 pipeline. While some backends may support using these resources in a
6420 graphics pipeline as well, this is not universally supported, and even when
6421 it is, unexpected problems may arise when it comes to barriers and
6422 synchronization. Therefore, avoid using such resources with shaders other
6423 than compute.
6424 */
6425QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6426 int binding, StageFlags stage, QRhiBuffer *buf)
6427{
6428 QRhiShaderResourceBinding b;
6429 b.d.binding = binding;
6430 b.d.stage = stage;
6431 b.d.type = BufferLoadStore;
6432 b.d.u.sbuf.buf = buf;
6433 b.d.u.sbuf.offset = 0;
6434 b.d.u.sbuf.maybeSize = 0; // entire buffer
6435 return b;
6436}
6437
6438/*!
6439 \return a shader resource binding for a read-write storage buffer with the
6440 given \a binding number and pipeline \a stage. This overload binds a region
6441 only, as specified by \a offset and \a size.
6442
6443 \note When \a buf is not null, must have been created with
6444 QRhiBuffer::StorageBuffer.
6445
6446 \note \a buf can be null. It is valid to create a
6447 QRhiShaderResourceBindings with unspecified resources, but such an object
6448 cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6449 suitable for creating pipelines. Such a pipeline must then always be used
6450 together with another, layout compatible QRhiShaderResourceBindings with
6451 resources present passed to QRhiCommandBuffer::setShaderResources().
6452
6453 \note Buffer load/store is only guaranteed to be available within a compute
6454 pipeline. While some backends may support using these resources in a
6455 graphics pipeline as well, this is not universally supported, and even when
6456 it is, unexpected problems may arise when it comes to barriers and
6457 synchronization. Therefore, avoid using such resources with shaders other
6458 than compute.
6459 */
6460QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6461 int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6462{
6463 Q_ASSERT(size > 0);
6464 QRhiShaderResourceBinding b;
6465 b.d.binding = binding;
6466 b.d.stage = stage;
6467 b.d.type = BufferLoadStore;
6468 b.d.u.sbuf.buf = buf;
6469 b.d.u.sbuf.offset = offset;
6470 b.d.u.sbuf.maybeSize = size;
6471 return b;
6472}
6473
6474/*!
6475 \return \c true if the contents of the two QRhiShaderResourceBinding
6476 objects \a a and \a b are equal. This includes the resources (buffer,
6477 texture) and related parameters (offset, size) as well. To only compare
6478 layouts (binding point, pipeline stage, resource type), use
6479 \l{QRhiShaderResourceBinding::isLayoutCompatible()}{isLayoutCompatible()}
6480 instead.
6481
6482 \relates QRhiShaderResourceBinding
6483 */
6484bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6485{
6486 const QRhiShaderResourceBinding::Data *da = QRhiImplementation::shaderResourceBindingData(a);
6487 const QRhiShaderResourceBinding::Data *db = QRhiImplementation::shaderResourceBindingData(b);
6488
6489 if (da == db)
6490 return true;
6491
6492
6493 if (da->binding != db->binding
6494 || da->stage != db->stage
6495 || da->type != db->type)
6496 {
6497 return false;
6498 }
6499
6500 switch (da->type) {
6501 case QRhiShaderResourceBinding::UniformBuffer:
6502 if (da->u.ubuf.buf != db->u.ubuf.buf
6503 || da->u.ubuf.offset != db->u.ubuf.offset
6504 || da->u.ubuf.maybeSize != db->u.ubuf.maybeSize)
6505 {
6506 return false;
6507 }
6508 break;
6509 case QRhiShaderResourceBinding::SampledTexture:
6510 if (da->u.stex.count != db->u.stex.count)
6511 return false;
6512 for (int i = 0; i < da->u.stex.count; ++i) {
6513 if (da->u.stex.texSamplers[i].tex != db->u.stex.texSamplers[i].tex
6514 || da->u.stex.texSamplers[i].sampler != db->u.stex.texSamplers[i].sampler)
6515 {
6516 return false;
6517 }
6518 }
6519 break;
6520 case QRhiShaderResourceBinding::Texture:
6521 if (da->u.stex.count != db->u.stex.count)
6522 return false;
6523 for (int i = 0; i < da->u.stex.count; ++i) {
6524 if (da->u.stex.texSamplers[i].tex != db->u.stex.texSamplers[i].tex)
6525 return false;
6526 }
6527 break;
6528 case QRhiShaderResourceBinding::Sampler:
6529 if (da->u.stex.texSamplers[0].sampler != db->u.stex.texSamplers[0].sampler)
6530 return false;
6531 break;
6532 case QRhiShaderResourceBinding::ImageLoad:
6533 case QRhiShaderResourceBinding::ImageStore:
6534 case QRhiShaderResourceBinding::ImageLoadStore:
6535 if (da->u.simage.tex != db->u.simage.tex
6536 || da->u.simage.level != db->u.simage.level)
6537 {
6538 return false;
6539 }
6540 break;
6541 case QRhiShaderResourceBinding::BufferLoad:
6542 case QRhiShaderResourceBinding::BufferStore:
6543 case QRhiShaderResourceBinding::BufferLoadStore:
6544 if (da->u.sbuf.buf != db->u.sbuf.buf
6545 || da->u.sbuf.offset != db->u.sbuf.offset
6546 || da->u.sbuf.maybeSize != db->u.sbuf.maybeSize)
6547 {
6548 return false;
6549 }
6550 break;
6551 default:
6552 Q_UNREACHABLE_RETURN(false);
6553 }
6554
6555 return true;
6556}
6557
6558/*!
6559 \return \c false if all the bindings in the two QRhiShaderResourceBinding
6560 objects \a a and \a b are equal; otherwise returns \c true.
6561
6562 \relates QRhiShaderResourceBinding
6563 */
6564bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6565{
6566 return !(a == b);
6567}
6568
6569/*!
6570 \fn size_t qHash(const QRhiShaderResourceBinding &key, size_t seed)
6571 \qhashold{QRhiShaderResourceBinding}
6572 */
6573size_t qHash(const QRhiShaderResourceBinding &b, size_t seed) noexcept
6574{
6575 const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6576 QtPrivate::QHashCombineWithSeed hash(seed);
6577 seed = hash(seed, d->binding);
6578 seed = hash(seed, d->stage);
6579 seed = hash(seed, d->type);
6580 switch (d->type) {
6581 case QRhiShaderResourceBinding::UniformBuffer:
6582 seed = hash(seed, reinterpret_cast<quintptr>(d->u.ubuf.buf));
6583 break;
6584 case QRhiShaderResourceBinding::SampledTexture:
6585 seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].tex));
6586 seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].sampler));
6587 break;
6588 case QRhiShaderResourceBinding::Texture:
6589 seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].tex));
6590 break;
6591 case QRhiShaderResourceBinding::Sampler:
6592 seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].sampler));
6593 break;
6594 case QRhiShaderResourceBinding::ImageLoad:
6595 case QRhiShaderResourceBinding::ImageStore:
6596 case QRhiShaderResourceBinding::ImageLoadStore:
6597 seed = hash(seed, reinterpret_cast<quintptr>(d->u.simage.tex));
6598 break;
6599 case QRhiShaderResourceBinding::BufferLoad:
6600 case QRhiShaderResourceBinding::BufferStore:
6601 case QRhiShaderResourceBinding::BufferLoadStore:
6602 seed = hash(seed, reinterpret_cast<quintptr>(d->u.sbuf.buf));
6603 break;
6604 }
6605 return seed;
6606}
6607
6608#ifndef QT_NO_DEBUG_STREAM
6609QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
6610{
6611 QDebugStateSaver saver(dbg);
6612 const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6613 dbg.nospace() << "QRhiShaderResourceBinding("
6614 << "binding=" << d->binding
6615 << " stage=" << d->stage
6616 << " type=" << d->type;
6617 switch (d->type) {
6618 case QRhiShaderResourceBinding::UniformBuffer:
6619 dbg.nospace() << " UniformBuffer("
6620 << "buffer=" << d->u.ubuf.buf
6621 << " offset=" << d->u.ubuf.offset
6622 << " maybeSize=" << d->u.ubuf.maybeSize
6623 << ')';
6624 break;
6625 case QRhiShaderResourceBinding::SampledTexture:
6626 dbg.nospace() << " SampledTextures("
6627 << "count=" << d->u.stex.count;
6628 for (int i = 0; i < d->u.stex.count; ++i) {
6629 dbg.nospace() << " texture=" << d->u.stex.texSamplers[i].tex
6630 << " sampler=" << d->u.stex.texSamplers[i].sampler;
6631 }
6632 dbg.nospace() << ')';
6633 break;
6634 case QRhiShaderResourceBinding::Texture:
6635 dbg.nospace() << " Textures("
6636 << "count=" << d->u.stex.count;
6637 for (int i = 0; i < d->u.stex.count; ++i)
6638 dbg.nospace() << " texture=" << d->u.stex.texSamplers[i].tex;
6639 dbg.nospace() << ')';
6640 break;
6641 case QRhiShaderResourceBinding::Sampler:
6642 dbg.nospace() << " Sampler("
6643 << " sampler=" << d->u.stex.texSamplers[0].sampler
6644 << ')';
6645 break;
6646 case QRhiShaderResourceBinding::ImageLoad:
6647 dbg.nospace() << " ImageLoad("
6648 << "texture=" << d->u.simage.tex
6649 << " level=" << d->u.simage.level
6650 << ')';
6651 break;
6652 case QRhiShaderResourceBinding::ImageStore:
6653 dbg.nospace() << " ImageStore("
6654 << "texture=" << d->u.simage.tex
6655 << " level=" << d->u.simage.level
6656 << ')';
6657 break;
6658 case QRhiShaderResourceBinding::ImageLoadStore:
6659 dbg.nospace() << " ImageLoadStore("
6660 << "texture=" << d->u.simage.tex
6661 << " level=" << d->u.simage.level
6662 << ')';
6663 break;
6664 case QRhiShaderResourceBinding::BufferLoad:
6665 dbg.nospace() << " BufferLoad("
6666 << "buffer=" << d->u.sbuf.buf
6667 << " offset=" << d->u.sbuf.offset
6668 << " maybeSize=" << d->u.sbuf.maybeSize
6669 << ')';
6670 break;
6671 case QRhiShaderResourceBinding::BufferStore:
6672 dbg.nospace() << " BufferStore("
6673 << "buffer=" << d->u.sbuf.buf
6674 << " offset=" << d->u.sbuf.offset
6675 << " maybeSize=" << d->u.sbuf.maybeSize
6676 << ')';
6677 break;
6678 case QRhiShaderResourceBinding::BufferLoadStore:
6679 dbg.nospace() << " BufferLoadStore("
6680 << "buffer=" << d->u.sbuf.buf
6681 << " offset=" << d->u.sbuf.offset
6682 << " maybeSize=" << d->u.sbuf.maybeSize
6683 << ')';
6684 break;
6685 default:
6686 dbg.nospace() << " UNKNOWN()";
6687 break;
6688 }
6689 dbg.nospace() << ')';
6690 return dbg;
6691}
6692#endif
6693
6694#ifndef QT_NO_DEBUG_STREAM
6695QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
6696{
6697 QDebugStateSaver saver(dbg);
6698 dbg.nospace() << "QRhiShaderResourceBindings("
6699 << srb.m_bindings
6700 << ')';
6701 return dbg;
6702}
6703#endif
6704
6705/*!
6706 \class QRhiGraphicsPipeline
6707 \inmodule QtGuiPrivate
6708 \inheaderfile rhi/qrhi.h
6709 \since 6.6
6710 \brief Graphics pipeline state resource.
6711
6712 Represents a graphics pipeline. What exactly this map to in the underlying
6713 native graphics API, varies. Where there is a concept of pipeline objects,
6714 for example with Vulkan, the QRhi backend will create such an object upon
6715 calling create(). Elsewhere, for example with OpenGL, the
6716 QRhiGraphicsPipeline may merely collect the various state, and create()'s
6717 main task is to set up the corresponding shader program, but deferring
6718 looking at any of the requested state to a later point.
6719
6720 As with all QRhiResource subclasses, the two-phased initialization pattern
6721 applies: setting any values via the setters, for example setDepthTest(), is
6722 only effective after calling create(). Avoid changing any values once the
6723 QRhiGraphicsPipeline has been initialized via create(). To change some
6724 state, set the new value and call create() again. However, that will
6725 effectively release all underlying native resources and create new ones. As
6726 a result, it may be a heavy, expensive operation. Rather, prefer creating
6727 multiple pipelines with the different states, and
6728 \l{QRhiCommandBuffer::setGraphicsPipeline()}{switch between them} when
6729 recording the render pass.
6730
6731 \note Setting the shader stages is mandatory. There must be at least one
6732 stage, and there must be a vertex stage.
6733
6734 \note Setting the shader resource bindings is mandatory. The referenced
6735 QRhiShaderResourceBindings must already have create() called on it by the
6736 time create() is called. Associating with a QRhiShaderResourceBindings that
6737 has no bindings is also valid, as long as no shader in any stage expects any
6738 resources. Using a QRhiShaderResourceBindings object that does not specify
6739 any actual resources (i.e., the buffers, textures, etc. for the binding
6740 points are set to \nullptr) is valid as well, as long as a
6741 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
6742 QRhiShaderResourceBindings, that specifies resources for all the bindings,
6743 is going to be set via
6744 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} when
6745 recording the render pass.
6746
6747 \note Setting the render pass descriptor is mandatory. To obtain a
6748 QRhiRenderPassDescriptor that can be passed to setRenderPassDescriptor(),
6749 use either QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() or
6750 QRhiSwapChain::newCompatibleRenderPassDescriptor().
6751
6752 \note Setting the vertex input layout is mandatory.
6753
6754 \note sampleCount() defaults to 1 and must match the sample count of the
6755 render target's color and depth stencil attachments.
6756
6757 \note The depth test, depth write, and stencil test are disabled by
6758 default. The face culling mode defaults to no culling.
6759
6760 \note stencilReadMask() and stencilWriteMask() apply to both faces. They
6761 both default to 0xFF.
6762
6763 \section2 Example usage
6764
6765 All settings of a graphics pipeline have defaults which might be suitable
6766 to many applications. Therefore a minimal example of creating a graphics
6767 pipeline could be the following. This assumes that the vertex shader takes
6768 a single \c{vec3 position} input at the input location 0. With the
6769 QRhiShaderResourceBindings and QRhiRenderPassDescriptor objects, plus the
6770 QShader collections for the vertex and fragment stages, a pipeline could be
6771 created like this:
6772
6773 \code
6774 QRhiShaderResourceBindings *srb;
6775 QRhiRenderPassDescriptor *rpDesc;
6776 QShader vs, fs;
6777 // ...
6778
6779 QRhiVertexInputLayout inputLayout;
6780 inputLayout.setBindings({ { 3 * sizeof(float) } });
6781 inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float3, 0 } });
6782
6783 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
6784 ps->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
6785 ps->setVertexInputLayout(inputLayout);
6786 ps->setShaderResourceBindings(srb);
6787 ps->setRenderPassDescriptor(rpDesc);
6788 if (!ps->create()) { error(); }
6789 \endcode
6790
6791 The above code creates a pipeline object that uses the defaults for many
6792 settings and states. For example, it will use a \l Triangles topology, no
6793 backface culling, blending is disabled but color write is enabled for all
6794 four channels, depth test/write are disabled, stencil operations are
6795 disabled.
6796
6797 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
6798 for details.
6799
6800 \sa QRhiCommandBuffer, QRhi
6801 */
6802
6803/*!
6804 \enum QRhiGraphicsPipeline::Flag
6805
6806 Flag values for describing the dynamic state of the pipeline, and other
6807 options. The viewport is always dynamic.
6808
6809 \value UsesBlendConstants Indicates that a blend color constant will be set
6810 via QRhiCommandBuffer::setBlendConstants()
6811
6812 \value UsesStencilRef Indicates that a stencil reference value will be set
6813 via QRhiCommandBuffer::setStencilRef()
6814
6815 \value UsesScissor Indicates that a scissor rectangle will be set via
6816 QRhiCommandBuffer::setScissor()
6817
6818 \value CompileShadersWithDebugInfo Requests compiling shaders with debug
6819 information enabled. This is relevant only when runtime shader compilation
6820 from source code is involved, and only when the underlying infrastructure
6821 supports this. With concrete examples, this is not relevant with Vulkan and
6822 SPIR-V, because the GLSL-to-SPIR-V compilation does not happen at run
6823 time. On the other hand, consider Direct3D and HLSL, where there are
6824 multiple options: when the QShader packages ship with pre-compiled bytecode
6825 (\c DXBC), debug information is to be requested through the tool that
6826 generates the \c{.qsb} file, similarly to the case of Vulkan and
6827 SPIR-V. However, when having HLSL source code in the pre- or
6828 runtime-generated QShader packages, the first phase of compilation (HLSL
6829 source to intermediate format) happens at run time too, with this flag taken
6830 into account. Debug information is relevant in particular with tools like
6831 RenderDoc since it allows seeing the original source code when investigating
6832 the pipeline and when performing vertex or fragment shader debugging.
6833
6834 \value UsesShadingRate Indicates that a per-draw (per-pipeline) shading rate
6835 value will be set via QRhiCommandBuffer::setShadingRate(). Not specifying
6836 this flag and still calling setShadingRate() may lead to varying, unexpected
6837 results depending on the underlying graphics API.
6838 */
6839
6840/*!
6841 \enum QRhiGraphicsPipeline::Topology
6842 Specifies the primitive topology
6843
6844 \value Triangles (default)
6845 \value TriangleStrip
6846 \value TriangleFan (only available if QRhi::TriangleFanTopology is supported)
6847 \value Lines
6848 \value LineStrip
6849 \value Points
6850
6851 \value Patches (only available if QRhi::Tessellation is supported, and
6852 requires the tessellation stages to be present in the pipeline)
6853 */
6854
6855/*!
6856 \enum QRhiGraphicsPipeline::CullMode
6857 Specifies the culling mode
6858
6859 \value None No culling (default)
6860 \value Front Cull front faces
6861 \value Back Cull back faces
6862 */
6863
6864/*!
6865 \enum QRhiGraphicsPipeline::FrontFace
6866 Specifies the front face winding order
6867
6868 \value CCW Counter clockwise (default)
6869 \value CW Clockwise
6870 */
6871
6872/*!
6873 \enum QRhiGraphicsPipeline::ColorMaskComponent
6874 Flag values for specifying the color write mask
6875
6876 \value R
6877 \value G
6878 \value B
6879 \value A
6880 */
6881
6882/*!
6883 \enum QRhiGraphicsPipeline::BlendFactor
6884 Specifies the blend factor
6885
6886 \value Zero
6887 \value One
6888 \value SrcColor
6889 \value OneMinusSrcColor
6890 \value DstColor
6891 \value OneMinusDstColor
6892 \value SrcAlpha
6893 \value OneMinusSrcAlpha
6894 \value DstAlpha
6895 \value OneMinusDstAlpha
6896 \value ConstantColor
6897 \value OneMinusConstantColor
6898 \value ConstantAlpha
6899 \value OneMinusConstantAlpha
6900 \value SrcAlphaSaturate
6901 \value Src1Color
6902 \value OneMinusSrc1Color
6903 \value Src1Alpha
6904 \value OneMinusSrc1Alpha
6905 */
6906
6907/*!
6908 \enum QRhiGraphicsPipeline::BlendOp
6909 Specifies the blend operation
6910
6911 \value Add
6912 \value Subtract
6913 \value ReverseSubtract
6914 \value Min
6915 \value Max
6916 */
6917
6918/*!
6919 \enum QRhiGraphicsPipeline::CompareOp
6920 Specifies the depth or stencil comparison function
6921
6922 \value Never
6923 \value Less (default for depth)
6924 \value Equal
6925 \value LessOrEqual
6926 \value Greater
6927 \value NotEqual
6928 \value GreaterOrEqual
6929 \value Always (default for stencil)
6930 */
6931
6932/*!
6933 \enum QRhiGraphicsPipeline::StencilOp
6934 Specifies the stencil operation
6935
6936 \value StencilZero
6937 \value Keep (default)
6938 \value Replace
6939 \value IncrementAndClamp
6940 \value DecrementAndClamp
6941 \value Invert
6942 \value IncrementAndWrap
6943 \value DecrementAndWrap
6944 */
6945
6946/*!
6947 \enum QRhiGraphicsPipeline::PolygonMode
6948 \brief Specifies the polygon rasterization mode
6949
6950 Polygon Mode (Triangle Fill Mode in Metal, Fill Mode in D3D) specifies
6951 the fill mode used when rasterizing polygons. Polygons may be drawn as
6952 solids (Fill), or as a wire mesh (Line).
6953
6954 Support for non-fill polygon modes is optional and is indicated by the
6955 QRhi::NonFillPolygonMode feature. With OpenGL ES and some Vulkan
6956 implementations the feature will likely be reported as unsupported, which
6957 then means values other than Fill cannot be used.
6958
6959 \value Fill The interior of the polygon is filled (default)
6960 \value Line Boundary edges of the polygon are drawn as line segments.
6961 */
6962
6963/*!
6964 \struct QRhiGraphicsPipeline::TargetBlend
6965 \inmodule QtGuiPrivate
6966 \inheaderfile rhi/qrhi.h
6967 \since 6.6
6968 \brief Describes the blend state for one color attachment.
6969
6970 Defaults to color write enabled, blending disabled. The blend values are
6971 set up for pre-multiplied alpha (One, OneMinusSrcAlpha, One,
6972 OneMinusSrcAlpha) by default. This means that to get the alpha blending
6973 mode Qt Quick uses, it is enough to set the \c enable flag to true while
6974 leaving other values at their defaults.
6975
6976 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
6977 for details.
6978 */
6979
6980/*!
6981 \variable QRhiGraphicsPipeline::TargetBlend::colorWrite
6982 */
6983
6984/*!
6985 \variable QRhiGraphicsPipeline::TargetBlend::enable
6986 */
6987
6988/*!
6989 \variable QRhiGraphicsPipeline::TargetBlend::srcColor
6990 */
6991
6992/*!
6993 \variable QRhiGraphicsPipeline::TargetBlend::dstColor
6994 */
6995
6996/*!
6997 \variable QRhiGraphicsPipeline::TargetBlend::opColor
6998 */
6999
7000/*!
7001 \variable QRhiGraphicsPipeline::TargetBlend::srcAlpha
7002 */
7003
7004/*!
7005 \variable QRhiGraphicsPipeline::TargetBlend::dstAlpha
7006 */
7007
7008/*!
7009 \variable QRhiGraphicsPipeline::TargetBlend::opAlpha
7010 */
7011
7012/*!
7013 \struct QRhiGraphicsPipeline::StencilOpState
7014 \inmodule QtGuiPrivate
7015 \inheaderfile rhi/qrhi.h
7016 \since 6.6
7017 \brief Describes the stencil operation state.
7018
7019 The default-constructed StencilOpState has the following set:
7020 \list
7021 \li failOp - \l Keep
7022 \li depthFailOp - \l Keep
7023 \li passOp - \l Keep
7024 \li compareOp \l Always
7025 \endlist
7026
7027 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7028 for details.
7029 */
7030
7031/*!
7032 \variable QRhiGraphicsPipeline::StencilOpState::failOp
7033 */
7034
7035/*!
7036 \variable QRhiGraphicsPipeline::StencilOpState::depthFailOp
7037 */
7038
7039/*!
7040 \variable QRhiGraphicsPipeline::StencilOpState::passOp
7041 */
7042
7043/*!
7044 \variable QRhiGraphicsPipeline::StencilOpState::compareOp
7045 */
7046
7047/*!
7048 \internal
7049 */
7050QRhiGraphicsPipeline::QRhiGraphicsPipeline(QRhiImplementation *rhi)
7051 : QRhiResource(rhi)
7052{
7053}
7054
7055/*!
7056 \return the resource type.
7057 */
7058QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
7059{
7060 return GraphicsPipeline;
7061}
7062
7063/*!
7064 \fn virtual bool QRhiGraphicsPipeline::create() = 0
7065
7066 Creates the corresponding native graphics resources. If there are already
7067 resources present due to an earlier create() with no corresponding
7068 destroy(), then destroy() is called implicitly first.
7069
7070 \return \c true when successful, \c false when a graphics operation failed.
7071 Regardless of the return value, calling destroy() is always safe.
7072
7073 \note This may be, depending on the underlying graphics API, an expensive
7074 operation, especially when shaders get compiled/optimized from source or
7075 from an intermediate bytecode format to the GPU's own instruction set.
7076 Where applicable, the QRhi backend automatically sets up the relevant
7077 non-persistent facilities to accelerate this, for example the Vulkan
7078 backend automatically creates a \c VkPipelineCache to improve data reuse
7079 during the lifetime of the application.
7080
7081 \note Drivers may also employ various persistent (disk-based) caching
7082 strategies for shader and pipeline data, which is hidden to and is outside
7083 of Qt's control. In some cases, depending on the graphics API and the QRhi
7084 backend, there are facilities within QRhi for manually managing such a
7085 cache, allowing the retrieval of a serializable blob that can then be
7086 reloaded in the future runs of the application to ensure faster pipeline
7087 creation times. See QRhi::pipelineCacheData() and
7088 QRhi::setPipelineCacheData() for details. Note also that when working with
7089 a QRhi instance managed by a higher level Qt framework, such as Qt Quick,
7090 it is possible that such disk-based caching is taken care of automatically,
7091 for example QQuickWindow uses a disk-based pipeline cache by default (which
7092 comes in addition to any driver-level caching).
7093 */
7094
7095/*!
7096 \fn QRhiGraphicsPipeline::Flags QRhiGraphicsPipeline::flags() const
7097 \return the currently set flags.
7098 */
7099
7100/*!
7101 \fn void QRhiGraphicsPipeline::setFlags(Flags f)
7102 Sets the flags \a f.
7103 */
7104
7105/*!
7106 \fn QRhiGraphicsPipeline::Topology QRhiGraphicsPipeline::topology() const
7107 \return the currently set primitive topology.
7108 */
7109
7110/*!
7111 \fn void QRhiGraphicsPipeline::setTopology(Topology t)
7112 Sets the primitive topology \a t.
7113 */
7114
7115/*!
7116 \fn QRhiGraphicsPipeline::CullMode QRhiGraphicsPipeline::cullMode() const
7117 \return the currently set face culling mode.
7118 */
7119
7120/*!
7121 \fn void QRhiGraphicsPipeline::setCullMode(CullMode mode)
7122 Sets the specified face culling \a mode.
7123 */
7124
7125/*!
7126 \fn QRhiGraphicsPipeline::FrontFace QRhiGraphicsPipeline::frontFace() const
7127 \return the currently set front face mode.
7128 */
7129
7130/*!
7131 \fn void QRhiGraphicsPipeline::setFrontFace(FrontFace f)
7132 Sets the front face mode \a f.
7133 */
7134
7135/*!
7136 \fn void QRhiGraphicsPipeline::setTargetBlends(std::initializer_list<TargetBlend> list)
7137
7138 Sets the \a list of render target blend settings. This is a list because
7139 when multiple render targets are used (i.e., a QRhiTextureRenderTarget with
7140 more than one QRhiColorAttachment), there needs to be a TargetBlend
7141 structure per render target (color attachment).
7142
7143 By default there is one default-constructed TargetBlend set.
7144
7145 \sa QRhi::MaxColorAttachments
7146 */
7147
7148/*!
7149 \fn template<typename InputIterator> void QRhiGraphicsPipeline::setTargetBlends(InputIterator first, InputIterator last)
7150 Sets the list of render target blend settings from the iterators \a first and \a last.
7151 */
7152
7153/*!
7154 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cbeginTargetBlends() const
7155 \return a const iterator pointing to the first item in the render target blend setting list.
7156 */
7157
7158/*!
7159 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cendTargetBlends() const
7160 \return a const iterator pointing just after the last item in the render target blend setting list.
7161 */
7162
7163/*!
7164 \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::targetBlendAt(qsizetype index) const
7165 \return the render target blend setting at the specified \a index.
7166 */
7167
7168/*!
7169 \fn qsizetype QRhiGraphicsPipeline::targetBlendCount() const
7170 \return the number of render target blend settings.
7171 */
7172
7173/*!
7174 \fn bool QRhiGraphicsPipeline::hasDepthTest() const
7175 \return true if depth testing is enabled.
7176 */
7177
7178/*!
7179 \fn void QRhiGraphicsPipeline::setDepthTest(bool enable)
7180
7181 Enables or disables depth testing based on \a enable. Both depth test and
7182 the writing out of depth data are disabled by default.
7183
7184 \sa setDepthWrite()
7185 */
7186
7187/*!
7188 \fn bool QRhiGraphicsPipeline::hasDepthWrite() const
7189 \return true if depth write is enabled.
7190 */
7191
7192/*!
7193 \fn void QRhiGraphicsPipeline::setDepthWrite(bool enable)
7194
7195 Controls the writing out of depth data into the depth buffer based on
7196 \a enable. By default this is disabled. Depth write is typically enabled
7197 together with the depth test.
7198
7199 \note Enabling depth write without having depth testing enabled may not
7200 lead to the desired result, and should be avoided.
7201
7202 \sa setDepthTest()
7203 */
7204
7205/*!
7206 \fn bool QRhiGraphicsPipeline::hasDepthClamp() const
7207 \return true if depth clamp is enabled.
7208
7209 \since 6.11
7210 */
7211
7212/*!
7213 \fn void QRhiGraphicsPipeline::setDepthClamp(bool enable)
7214
7215 Enables depth clamping when \a enable is true. When depth clamping is
7216 enabled, primitives that would otherwise be clipped by the near or far
7217 clip plane are rasterized and their depth values are clamped to the
7218 depth range. When disabled (the default), such primitives are clipped.
7219
7220 \note This setting is ignored on OpenGL ES.
7221
7222 \since 6.11
7223 */
7224
7225/*!
7226 \fn QRhiGraphicsPipeline::CompareOp QRhiGraphicsPipeline::depthOp() const
7227 \return the depth comparison function.
7228 */
7229
7230/*!
7231 \fn void QRhiGraphicsPipeline::setDepthOp(CompareOp op)
7232 Sets the depth comparison function \a op.
7233 */
7234
7235/*!
7236 \fn bool QRhiGraphicsPipeline::hasStencilTest() const
7237 \return true if stencil testing is enabled.
7238 */
7239
7240/*!
7241 \fn void QRhiGraphicsPipeline::setStencilTest(bool enable)
7242 Enables or disables stencil tests based on \a enable.
7243 By default this is disabled.
7244 */
7245
7246/*!
7247 \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilFront() const
7248 \return the current stencil test state for front faces.
7249 */
7250
7251/*!
7252 \fn void QRhiGraphicsPipeline::setStencilFront(const StencilOpState &state)
7253 Sets the stencil test \a state for front faces.
7254 */
7255
7256/*!
7257 \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilBack() const
7258 \return the current stencil test state for back faces.
7259 */
7260
7261/*!
7262 \fn void QRhiGraphicsPipeline::setStencilBack(const StencilOpState &state)
7263 Sets the stencil test \a state for back faces.
7264 */
7265
7266/*!
7267 \fn quint32 QRhiGraphicsPipeline::stencilReadMask() const
7268 \return the currrent stencil read mask.
7269 */
7270
7271/*!
7272 \fn void QRhiGraphicsPipeline::setStencilReadMask(quint32 mask)
7273 Sets the stencil read \a mask. The default value is 0xFF.
7274 */
7275
7276/*!
7277 \fn quint32 QRhiGraphicsPipeline::stencilWriteMask() const
7278 \return the current stencil write mask.
7279 */
7280
7281/*!
7282 \fn void QRhiGraphicsPipeline::setStencilWriteMask(quint32 mask)
7283 Sets the stencil write \a mask. The default value is 0xFF.
7284 */
7285
7286/*!
7287 \fn int QRhiGraphicsPipeline::sampleCount() const
7288 \return the currently set sample count. 1 means no multisample antialiasing.
7289 */
7290
7291/*!
7292 \fn void QRhiGraphicsPipeline::setSampleCount(int s)
7293
7294 Sets the sample count. Typical values for \a s are 1, 4, or 8. The pipeline
7295 must always be compatible with the render target, i.e. the sample counts
7296 must match.
7297
7298 \sa QRhi::supportedSampleCounts()
7299 */
7300
7301/*!
7302 \fn float QRhiGraphicsPipeline::lineWidth() const
7303 \return the currently set line width. The default is 1.0f.
7304 */
7305
7306/*!
7307 \fn void QRhiGraphicsPipeline::setLineWidth(float width)
7308
7309 Sets the line \a width. If the QRhi::WideLines feature is reported as
7310 unsupported at runtime, values other than 1.0f are ignored.
7311 */
7312
7313/*!
7314 \fn int QRhiGraphicsPipeline::depthBias() const
7315 \return the currently set depth bias.
7316 */
7317
7318/*!
7319 \fn void QRhiGraphicsPipeline::setDepthBias(int bias)
7320 Sets the depth \a bias. The default value is 0.
7321 */
7322
7323/*!
7324 \fn float QRhiGraphicsPipeline::slopeScaledDepthBias() const
7325 \return the currently set slope scaled depth bias.
7326 */
7327
7328/*!
7329 \fn void QRhiGraphicsPipeline::setSlopeScaledDepthBias(float bias)
7330 Sets the slope scaled depth \a bias. The default value is 0.
7331 */
7332
7333/*!
7334 \fn void QRhiGraphicsPipeline::setShaderStages(std::initializer_list<QRhiShaderStage> list)
7335 Sets the \a list of shader stages.
7336 */
7337
7338/*!
7339 \fn template<typename InputIterator> void QRhiGraphicsPipeline::setShaderStages(InputIterator first, InputIterator last)
7340 Sets the list of shader stages from the iterators \a first and \a last.
7341 */
7342
7343/*!
7344 \fn const QRhiShaderStage *QRhiGraphicsPipeline::cbeginShaderStages() const
7345 \return a const iterator pointing to the first item in the shader stage list.
7346 */
7347
7348/*!
7349 \fn const QRhiShaderStage *QRhiGraphicsPipeline::cendShaderStages() const
7350 \return a const iterator pointing just after the last item in the shader stage list.
7351 */
7352
7353/*!
7354 \fn const QRhiShaderStage *QRhiGraphicsPipeline::shaderStageAt(qsizetype index) const
7355 \return the shader stage at the specified \a index.
7356 */
7357
7358/*!
7359 \fn qsizetype QRhiGraphicsPipeline::shaderStageCount() const
7360 \return the number of shader stages in this pipeline.
7361 */
7362
7363/*!
7364 \fn QRhiVertexInputLayout QRhiGraphicsPipeline::vertexInputLayout() const
7365 \return the currently set vertex input layout specification.
7366 */
7367
7368/*!
7369 \fn void QRhiGraphicsPipeline::setVertexInputLayout(const QRhiVertexInputLayout &layout)
7370 Specifies the vertex input \a layout.
7371 */
7372
7373/*!
7374 \fn QRhiShaderResourceBindings *QRhiGraphicsPipeline::shaderResourceBindings() const
7375 \return the currently associated QRhiShaderResourceBindings object.
7376 */
7377
7378/*!
7379 \fn void QRhiGraphicsPipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
7380
7381 Associates with \a srb describing the resource binding layout and the
7382 resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional,
7383 because only the layout matters during pipeline creation. Therefore, the \a
7384 srb passed in here can leave the actual buffer or texture objects
7385 unspecified (\nullptr) as long as there is another,
7386 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
7387 QRhiShaderResourceBindings bound via
7388 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
7389 recording the draw calls.
7390 */
7391
7392/*!
7393 \fn QRhiRenderPassDescriptor *QRhiGraphicsPipeline::renderPassDescriptor() const
7394 \return the currently set QRhiRenderPassDescriptor.
7395 */
7396
7397/*!
7398 \fn void QRhiGraphicsPipeline::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
7399 Associates with the specified QRhiRenderPassDescriptor \a desc.
7400 */
7401
7402/*!
7403 \fn int QRhiGraphicsPipeline::patchControlPointCount() const
7404 \return the currently set patch control point count.
7405 */
7406
7407/*!
7408 \fn void QRhiGraphicsPipeline::setPatchControlPointCount(int count)
7409
7410 Sets the number of patch control points to \a count. The default value is
7411 3. This is used only when the topology is set to \l Patches.
7412 */
7413
7414/*!
7415 \fn QRhiGraphicsPipeline::PolygonMode QRhiGraphicsPipeline::polygonMode() const
7416 \return the polygon mode.
7417 */
7418
7419/*!
7420 \fn void QRhiGraphicsPipeline::setPolygonMode(PolygonMode mode)
7421 Sets the polygon \a mode. The default is Fill.
7422
7423 \sa QRhi::NonFillPolygonMode
7424 */
7425
7426/*!
7427 \fn int QRhiGraphicsPipeline::multiViewCount() const
7428 \return the view count. The default is 0, indicating no multiview rendering.
7429 \since 6.7
7430 */
7431
7432/*!
7433 \fn void QRhiGraphicsPipeline::setMultiViewCount(int count)
7434 Sets the view \a count for multiview rendering. The default is 0,
7435 indicating no multiview rendering.
7436 \a count must be 2 or larger to trigger multiview rendering.
7437
7438 Multiview is only available when the \l{QRhi::MultiView}{MultiView feature}
7439 is reported as supported. The render target must be a 2D texture array, and
7440 the color attachment for the render target must have the same \a count set.
7441
7442 See QRhiColorAttachment::setMultiViewCount() for further details on
7443 multiview rendering.
7444
7445 \since 6.7
7446 \sa QRhi::MultiView, QRhiColorAttachment::setMultiViewCount()
7447 */
7448
7449/*!
7450 \class QRhiSwapChain
7451 \inmodule QtGuiPrivate
7452 \inheaderfile rhi/qrhi.h
7453 \since 6.6
7454 \brief Swapchain resource.
7455
7456 A swapchain enables presenting rendering results to a surface. A swapchain
7457 is typically backed by a set of color buffers. Of these, one is displayed
7458 at a time.
7459
7460 Below is a typical pattern for creating and managing a swapchain and some
7461 associated resources in order to render onto a QWindow:
7462
7463 \code
7464 void init()
7465 {
7466 sc = rhi->newSwapChain();
7467 ds = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
7468 QSize(), // no need to set the size here due to UsedWithSwapChainOnly
7469 1,
7470 QRhiRenderBuffer::UsedWithSwapChainOnly);
7471 sc->setWindow(window);
7472 sc->setDepthStencil(ds);
7473 rp = sc->newCompatibleRenderPassDescriptor();
7474 sc->setRenderPassDescriptor(rp);
7475 resizeSwapChain();
7476 }
7477
7478 void resizeSwapChain()
7479 {
7480 hasSwapChain = sc->createOrResize();
7481 }
7482
7483 void render()
7484 {
7485 if (!hasSwapChain || notExposed)
7486 return;
7487
7488 if (sc->currentPixelSize() != sc->surfacePixelSize() || newlyExposed) {
7489 resizeSwapChain();
7490 if (!hasSwapChain)
7491 return;
7492 newlyExposed = false;
7493 }
7494
7495 rhi->beginFrame(sc);
7496 // ...
7497 rhi->endFrame(sc);
7498 }
7499 \endcode
7500
7501 Avoid relying on QWindow resize events to resize swapchains, especially
7502 considering that surface sizes may not always fully match the QWindow
7503 reported dimensions. The safe, cross-platform approach is to do the check
7504 via surfacePixelSize() whenever starting a new frame.
7505
7506 Releasing the swapchain must happen while the QWindow and the underlying
7507 native window is fully up and running. Building on the previous example:
7508
7509 \code
7510 void releaseSwapChain()
7511 {
7512 if (hasSwapChain) {
7513 sc->destroy();
7514 hasSwapChain = false;
7515 }
7516 }
7517
7518 // assuming Window is our QWindow subclass
7519 bool Window::event(QEvent *e)
7520 {
7521 switch (e->type()) {
7522 case QEvent::UpdateRequest: // for QWindow::requestUpdate()
7523 render();
7524 break;
7525 case QEvent::PlatformSurface:
7526 if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
7527 releaseSwapChain();
7528 break;
7529 default:
7530 break;
7531 }
7532 return QWindow::event(e);
7533 }
7534 \endcode
7535
7536 Initializing the swapchain and starting to render the first frame cannot
7537 start at any time. The safe, cross-platform approach is to rely on expose
7538 events. QExposeEvent is a loosely specified event that is sent whenever a
7539 window gets mapped, obscured, and resized, depending on the platform.
7540
7541 \code
7542 void Window::exposeEvent(QExposeEvent *)
7543 {
7544 // initialize and start rendering when the window becomes usable for graphics purposes
7545 if (isExposed() && !running) {
7546 running = true;
7547 init();
7548 }
7549
7550 // stop pushing frames when not exposed or size becomes 0
7551 if ((!isExposed() || (hasSwapChain && sc->surfacePixelSize().isEmpty())) && running)
7552 notExposed = true;
7553
7554 // continue when exposed again and the surface has a valid size
7555 if (isExposed() && running && notExposed && !sc->surfacePixelSize().isEmpty()) {
7556 notExposed = false;
7557 newlyExposed = true;
7558 }
7559
7560 if (isExposed() && !sc->surfacePixelSize().isEmpty())
7561 render();
7562 }
7563 \endcode
7564
7565 Once the rendering has started, a simple way to request a new frame is
7566 QWindow::requestUpdate(). While on some platforms this is merely a small
7567 timer, on others it has a specific implementation: for instance on macOS or
7568 iOS it may be backed by
7569 \l{https://developer.apple.com/documentation/corevideo/cvdisplaylink?language=objc}{CVDisplayLink}.
7570 The example above is already prepared for update requests by handling
7571 QEvent::UpdateRequest.
7572
7573 While acting as a QRhiRenderTarget, QRhiSwapChain also manages a
7574 QRhiCommandBuffer. Calling QRhi::endFrame() submits the recorded commands
7575 and also enqueues a \c present request. The default behavior is to do this
7576 with a swap interval of 1, meaning synchronizing to the display's vertical
7577 refresh is enabled. Thus the rendering thread calling beginFrame() and
7578 endFrame() will get throttled to vsync. On some backends this can be
7579 disabled by passing QRhiSwapChain:NoVSync in flags().
7580
7581 Multisampling (MSAA) is handled transparently to the applications when
7582 requested via setSampleCount(). Where applicable, QRhiSwapChain will take
7583 care of creating additional color buffers and issuing a multisample resolve
7584 command at the end of a frame. For OpenGL, it is necessary to request the
7585 appropriate sample count also via QSurfaceFormat, by calling
7586 QSurfaceFormat::setDefaultFormat() before initializing the QRhi.
7587
7588 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7589 for details.
7590 */
7591
7592/*!
7593 \enum QRhiSwapChain::Flag
7594 Flag values to describe swapchain properties
7595
7596 \value SurfaceHasPreMulAlpha Indicates that the target surface has
7597 transparency with premultiplied alpha. For example, this is what Qt Quick
7598 uses when the alpha channel is enabled on the target QWindow, because the
7599 scenegraph rendrerer always outputs fragments with alpha multiplied into
7600 the red, green, and blue values. To ensure identical behavior across
7601 platforms, always set QSurfaceFormat::alphaBufferSize() to a non-zero value
7602 on the target QWindow whenever this flag is set on the swapchain.
7603
7604 \value SurfaceHasNonPreMulAlpha Indicates the target surface has
7605 transparency with non-premultiplied alpha. Be aware that this may not be
7606 supported on some systems, if the system compositor always expects content
7607 with premultiplied alpha. In that case the behavior with this flag set is
7608 expected to be equivalent to SurfaceHasPreMulAlpha.
7609
7610 \value sRGB Requests to pick an sRGB format for the swapchain's color
7611 buffers and/or render target views, where applicable. Note that this
7612 implies that sRGB framebuffer update and blending will get enabled for all
7613 content targeting this swapchain, and opting out is not possible. For
7614 OpenGL, set \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the
7615 QSurfaceFormat of the QWindow in addition. Applicable only when the
7616 swapchain format is set to QRhiSwapChain::SDR.
7617
7618 \value UsedAsTransferSource Indicates the swapchain will be used as the
7619 source of a readback in QRhiResourceUpdateBatch::readBackTexture().
7620
7621 \value NoVSync Requests disabling waiting for vertical sync, also avoiding
7622 throttling the rendering thread. The behavior is backend specific and
7623 applicable only where it is possible to control this. Some may ignore the
7624 request altogether. For OpenGL, try instead setting the swap interval to 0
7625 on the QWindow via QSurfaceFormat::setSwapInterval().
7626
7627 \value MinimalBufferCount Requests creating the swapchain with the minimum
7628 number of buffers, which is in practice 2, unless the graphics
7629 implementation has a higher minimum number than that. Only applicable with
7630 backends where such control is available via the graphics API, for example,
7631 Vulkan. By default it is up to the backend to decide what number of buffers
7632 it requests (in practice this is almost always either 2 or 3), and it is
7633 not the applications' concern. However, on Vulkan for instance the backend
7634 will likely prefer the higher number (3), for example to avoid odd
7635 performance issues with some Vulkan implementations on mobile devices. It
7636 could be that on some platforms it can prove to be beneficial to force the
7637 lower buffer count (2), so this flag allows forcing that. Note that all
7638 this has no effect on the number of frames kept in flight, so the CPU
7639 (QRhi) will still prepare frames at most \c{N - 1} frames ahead of the GPU,
7640 even when the swapchain image buffer count larger than \c N. (\c{N} =
7641 QRhi::FramesInFlight and typically 2).
7642 */
7643
7644/*!
7645 \enum QRhiSwapChain::Format
7646 Describes the swapchain format. The default format is SDR.
7647
7648 This enum is used with
7649 \l{QRhiSwapChain::isFormatSupported()}{isFormatSupported()} to check
7650 upfront if creating the swapchain with the given format is supported by the
7651 platform and the window's associated screen, and with
7652 \l{QRhiSwapChain::setFormat()}{setFormat()}
7653 to set the requested format in the swapchain before calling
7654 \l{QRhiSwapChain::createOrResize()}{createOrResize()} for the first time.
7655
7656 \value SDR 8-bit RGBA or BGRA, depending on the backend and platform. With
7657 OpenGL ES in particular, it could happen that the platform provides less
7658 than 8 bits (e.g. due to EGL and the QSurfaceFormat choosing a 565 or 444
7659 format - this is outside the control of QRhi). Standard dynamic range. May
7660 be combined with setting the QRhiSwapChain::sRGB flag.
7661
7662 \value HDRExtendedSrgbLinear 16-bit float RGBA, high dynamic range,
7663 extended linear sRGB (scRGB) color space. This involves Rec. 709 primaries
7664 (same as SDR/sRGB) and linear colors. Conversion to the display's native
7665 color space (such as, HDR10) is performed by the windowing system. On
7666 Windows this is the canonical color space of the system compositor, and is
7667 the recommended format for HDR swapchains in general on desktop platforms.
7668
7669 \value HDR10 10-bit unsigned int RGB or BGR with 2 bit alpha, high dynamic
7670 range, HDR10 (Rec. 2020) color space with an ST2084 PQ transfer function.
7671
7672 \value HDRExtendedDisplayP3Linear 16-bit float RGBA, high dynamic range,
7673 extended linear Display P3 color space. The primary choice for HDR on
7674 platforms such as iOS and VisionOS.
7675 */
7676
7677/*!
7678 \internal
7679 */
7680QRhiSwapChain::QRhiSwapChain(QRhiImplementation *rhi)
7681 : QRhiResource(rhi)
7682{
7683}
7684
7685/*!
7686 \return the resource type.
7687 */
7688QRhiResource::Type QRhiSwapChain::resourceType() const
7689{
7690 return SwapChain;
7691}
7692
7693/*!
7694 \fn QSize QRhiSwapChain::currentPixelSize() const
7695
7696 \return the size with which the swapchain was last successfully built. Use
7697 this to decide if createOrResize() needs to be called again: if
7698 \c{currentPixelSize() != surfacePixelSize()} then the swapchain needs to be
7699 resized.
7700
7701 \note Typical rendering logic will call this function to get the output
7702 size when starting to prepare a new frame, and base dependent calculations
7703 (such as, the viewport) on the size returned from this function.
7704
7705 While in many cases the value is the same as \c{QWindow::size() *
7706 QWindow::devicePixelRatio()}, relying on the QWindow-reported size is not
7707 guaranteed to be correct on all platforms and graphics API implementations.
7708 Using this function is therefore strongly recommended whenever there is a
7709 need to identify the dimensions, in pixels, of the output layer or surface.
7710
7711 This also has the added benefit of avoiding potential data races when QRhi
7712 is used on a dedicated rendering thread, because the need to call QWindow
7713 functions, that may then access data updated on the main thread, is
7714 avoided.
7715
7716 \sa surfacePixelSize()
7717 */
7718
7719/*!
7720 \fn virtual QSize QRhiSwapChain::surfacePixelSize() = 0
7721
7722 \return The size of the window's associated surface or layer.
7723
7724 \warning Do not assume this is the same as \c{QWindow::size() *
7725 QWindow::devicePixelRatio()}. With some graphics APIs and windowing system
7726 interfaces (for example, Vulkan) there is a theoretical possibility for a
7727 surface to assume a size different from the associated window. To support
7728 these cases, \b{rendering logic must always base size-derived calculations
7729 (such as, viewports) on the size reported from QRhiSwapChain, and never on
7730 the size queried from QWindow}.
7731
7732 \note \b{Can also be called before createOrResize(), if at least window() is
7733 already set. This in combination with currentPixelSize() allows to detect
7734 when a swapchain needs to be resized.} However, watch out for the fact that
7735 the size of the underlying native object (surface, layer, or similar) is
7736 "live", so whenever this function is called, it returns the latest value
7737 reported by the underlying implementation, without any atomicity guarantee.
7738 Therefore, using this function to determine pixel sizes for graphics
7739 resources that are used in a frame is strongly discouraged. Rely on
7740 currentPixelSize() instead which returns a size that is atomic and will not
7741 change between createOrResize() invocations.
7742
7743 \note For depth-stencil buffers used in combination with the swapchain's
7744 color buffers, it is strongly recommended to rely on the automatic sizing
7745 and rebuilding behavior provided by the
7746 QRhiRenderBuffer:UsedWithSwapChainOnly flag. Avoid querying the surface
7747 size via this function just to get a size that can be passed to
7748 QRhiRenderBuffer::setPixelSize() as that would suffer from the lack of
7749 atomicity as described above.
7750
7751 \sa currentPixelSize()
7752 */
7753
7754/*!
7755 \fn virtual bool QRhiSwapChain::isFormatSupported(Format f) = 0
7756
7757 \return true if the given swapchain format \a f is supported. SDR is always
7758 supported.
7759
7760 \note Can be called independently of createOrResize(), but window() must
7761 already be set. Calling without the window set may lead to unexpected
7762 results depending on the backend and platform (most likely false for any
7763 HDR format), because HDR format support is usually tied to the output
7764 (screen) to which the swapchain's associated window belongs at any given
7765 time. If the result is true for a HDR format, then creating the swapchain
7766 with that format is expected to succeed as long as the window is not moved
7767 to another screen in the meantime.
7768
7769 The main use of this function is to call it before the first
7770 createOrResize() after the window is already set. This allow the QRhi
7771 backends to perform platform or windowing system specific queries to
7772 determine if the window (and the screen it is on) is capable of true HDR
7773 output with the specified format.
7774
7775 When the format is reported as supported, call setFormat() to set the
7776 requested format and call createOrResize(). Be aware of the consequences
7777 however: successfully requesting a HDR format will involve having to deal
7778 with a different color space, possibly doing white level correction for
7779 non-HDR-aware content, adjusting tonemapping methods, adjusting offscreen
7780 render target settings, etc.
7781
7782 \sa setFormat()
7783 */
7784
7785/*!
7786 \fn virtual QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer() = 0
7787
7788 \return a command buffer on which rendering commands and resource updates
7789 can be recorded within a \l{QRhi::beginFrame()}{beginFrame} -
7790 \l{QRhi::endFrame()}{endFrame} block, assuming beginFrame() was called with
7791 this swapchain.
7792
7793 \note The returned object is valid also after endFrame(), up until the next
7794 beginFrame(), but the returned command buffer should not be used to record
7795 any commands then. Rather, it can be used to query data collected during
7796 the frame (or previous frames), for example by calling
7797 \l{QRhiCommandBuffer::lastCompletedGpuTime()}{lastCompletedGpuTime()}.
7798
7799 \note The value must not be cached and reused between frames. The caller
7800 should not hold on to the returned object once
7801 \l{QRhi::beginFrame()}{beginFrame()} is called again. Instead, the command
7802 buffer object should be queried again by calling this function.
7803*/
7804
7805/*!
7806 \fn virtual QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget() = 0
7807
7808 \return a render target that can used with beginPass() in order to render
7809 the swapchain's current backbuffer. Only valid within a
7810 QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called
7811 with this swapchain.
7812
7813 \note the value must not be cached and reused between frames
7814 */
7815
7816/*!
7817 \enum QRhiSwapChain::StereoTargetBuffer
7818 Selects the backbuffer to use with a stereoscopic swapchain.
7819
7820 \value LeftBuffer
7821 \value RightBuffer
7822 */
7823
7824/*!
7825 \return a render target that can be used with beginPass() in order to
7826 render to the swapchain's left or right backbuffer. This overload should be
7827 used only with stereoscopic rendering, that is, when the associated QWindow
7828 is backed by two color buffers, one for each eye, instead of just one.
7829
7830 When stereoscopic rendering is not supported, the return value will be
7831 the default target. It is supported by all hardware backends except for Metal, in
7832 combination with \l QSurfaceFormat::StereoBuffers, assuming it is supported
7833 by the graphics and display driver stack at run time. Metal and Null backends
7834 are going to return the default render target from this overload.
7835
7836 \note the value must not be cached and reused between frames
7837 */
7838QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
7839{
7840 Q_UNUSED(targetBuffer);
7841 return currentFrameRenderTarget();
7842}
7843
7844/*!
7845 \fn virtual bool QRhiSwapChain::createOrResize() = 0
7846
7847 Creates the swapchain if not already done and resizes the swapchain buffers
7848 to match the current size of the targeted surface. Call this whenever the
7849 size of the target surface is different than before.
7850
7851 \note call destroy() only when the swapchain needs to be released
7852 completely, typically upon
7853 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed. To perform resizing, just
7854 call createOrResize().
7855
7856 \return \c true when successful, \c false when a graphics operation failed.
7857 Regardless of the return value, calling destroy() is always safe.
7858 */
7859
7860/*!
7861 \fn QWindow *QRhiSwapChain::window() const
7862 \return the currently set window.
7863 */
7864
7865/*!
7866 \fn void QRhiSwapChain::setWindow(QWindow *window)
7867 Sets the \a window.
7868 */
7869
7870/*!
7871 \fn QRhiSwapChainProxyData QRhiSwapChain::proxyData() const
7872 \return the currently set proxy data.
7873 */
7874
7875/*!
7876 \fn void QRhiSwapChain::setProxyData(const QRhiSwapChainProxyData &d)
7877 Sets the proxy data \a d.
7878
7879 \sa QRhi::updateSwapChainProxyData()
7880 */
7881
7882/*!
7883 \fn QRhiSwapChain::Flags QRhiSwapChain::flags() const
7884 \return the currently set flags.
7885 */
7886
7887/*!
7888 \fn void QRhiSwapChain::setFlags(Flags f)
7889 Sets the flags \a f.
7890 */
7891
7892/*!
7893 \fn QRhiSwapChain::Format QRhiSwapChain::format() const
7894 \return the currently set format.
7895 */
7896
7897/*!
7898 \fn void QRhiSwapChain::setFormat(Format f)
7899 Sets the format \a f.
7900
7901 Avoid setting formats that are reported as unsupported from
7902 isFormatSupported(). Note that support for a given format may depend on the
7903 screen the swapchain's associated window is opened on. On some platforms,
7904 such as Windows and macOS, for HDR output to work it is necessary to have
7905 HDR output enabled in the display settings.
7906
7907 See isFormatSupported(), \l QRhiSwapChainHdrInfo, and \l Format for more
7908 information on high dynamic range output.
7909 */
7910
7911/*!
7912 \fn QRhiRenderBuffer *QRhiSwapChain::depthStencil() const
7913 \return the currently associated renderbuffer for depth-stencil.
7914 */
7915
7916/*!
7917 \fn void QRhiSwapChain::setDepthStencil(QRhiRenderBuffer *ds)
7918 Sets the renderbuffer \a ds for use as a depth-stencil buffer.
7919 */
7920
7921/*!
7922 \fn int QRhiSwapChain::sampleCount() const
7923 \return the currently set sample count. 1 means no multisample antialiasing.
7924 */
7925
7926/*!
7927 \fn void QRhiSwapChain::setSampleCount(int samples)
7928
7929 Sets the sample count. Common values for \a samples are 1 (no MSAA), 4 (4x
7930 MSAA), or 8 (8x MSAA).
7931
7932 \sa QRhi::supportedSampleCounts()
7933 */
7934
7935/*!
7936 \fn QRhiRenderPassDescriptor *QRhiSwapChain::renderPassDescriptor() const
7937 \return the currently associated QRhiRenderPassDescriptor object.
7938 */
7939
7940/*!
7941 \fn void QRhiSwapChain::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
7942 Associates with the QRhiRenderPassDescriptor \a desc.
7943 */
7944
7945/*!
7946 \fn virtual QRhiRenderPassDescriptor *QRhiSwapChain::newCompatibleRenderPassDescriptor() = 0;
7947
7948 \return a new QRhiRenderPassDescriptor that is compatible with this swapchain.
7949
7950 The returned value is used in two ways: it can be passed to
7951 setRenderPassDescriptor() and
7952 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
7953 describes the attachments (color, depth/stencil) and the load/store
7954 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
7955 be used in combination with a swapchain that has a
7956 \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
7957 QRhiRenderPassDescriptor set.
7958
7959 \sa createOrResize()
7960 */
7961
7962/*!
7963 \fn QRhiShadingRateMap *QRhiSwapChain::shadingRateMap() const
7964 \return the currently set QRhiShadingRateMap. By default this is \nullptr.
7965 \since 6.9
7966 */
7967
7968/*!
7969 \fn void QRhiSwapChain::setShadingRateMap(QRhiShadingRateMap *map)
7970
7971 Associates with the specified QRhiShadingRateMap \a map. This is functional
7972 only when the \l QRhi::VariableRateShadingMap feature is reported as
7973 supported.
7974
7975 When QRhiCommandBuffer::setShadingRate() is also called, the higher of two
7976 the shading rates are used for each tile. There is currently no control
7977 offered over the combiner behavior.
7978
7979 \note Setting a shading rate map implies that a different, new
7980 QRhiRenderPassDescriptor is needed and some of the native swapchain objects
7981 must be rebuilt. Therefore, if the swapchain is already set up, call
7982 newCompatibleRenderPassDescriptor() and setRenderPassDescriptor() right
7983 after setShadingRateMap(). Then, createOrResize() must also be called again.
7984 This has rolling consequences, for example for graphics pipelines: those
7985 also need to be associated with the new QRhiRenderPassDescriptor and then
7986 rebuilt. See \l QRhiRenderPassDescriptor::serializedFormat() for some
7987 suggestions on how to deal with this. Remember to set the
7988 QRhiGraphicsPipeline::UsesShadingRate flag for them as well.
7989
7990 \since 6.9
7991 */
7992
7993/*!
7994 \struct QRhiSwapChainHdrInfo
7995 \inmodule QtGuiPrivate
7996 \inheaderfile rhi/qrhi.h
7997 \since 6.6
7998
7999 \brief Describes the high dynamic range related information of the
8000 swapchain's associated output.
8001
8002 To perform HDR-compatible tonemapping, where the target range is not [0,1],
8003 one often needs to know the maximum luminance of the display the
8004 swapchain's window is associated with. While this is often made
8005 user-configurable (think brightness, gamma and similar settings in games),
8006 it can be highly useful to set defaults based on the values reported by the
8007 display itself, thus providing a decent starting point.
8008
8009 There are some problems however: the information is exposed in different
8010 forms on different platforms, whereas with cross-platform graphics APIs
8011 there is often no associated solution at all, because managing such
8012 information is not in the scope of the API (and may rather be retrievable
8013 via other platform-specific means, if any).
8014
8015 With Metal on macOS/iOS, there is no luminance values exposed in the
8016 platform APIs. Instead, the maximum color component value, that would be
8017 1.0 in a non-HDR setup, is provided. The \c limitsType field indicates what
8018 kind of information is available. It is then up to the clients of QRhi to
8019 access the correct data from the \c limits union and use it as they see
8020 fit.
8021
8022 With an API like Vulkan, where there is no way to get such information, the
8023 values are always the built-in defaults.
8024
8025 Therefore, the struct returned from QRhiSwapChain::hdrInfo() contains
8026 either some hard-coded defaults or real values received from an API such as
8027 DXGI (IDXGIOutput6) or Cocoa (NSScreen). When no platform queries are
8028 available (or needs using platform facilities out of scope for QRhi), the
8029 hard-coded defaults are a maximum luminance of 1000 nits and an SDR white
8030 level of 200.
8031
8032 The struct also exposes the presumed luminance behavior of the platform and
8033 its compositor, to indicate what a color component value of 1.0 is treated
8034 as in a HDR color buffer. In some cases it will be necessary to perform
8035 color correction of non-HDR content composited with HDR content. To enable
8036 this, the SDR white level is queried from the system on some platforms
8037 (Windows) and exposed here.
8038
8039 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8040 for details.
8041
8042 \sa QRhiSwapChain::hdrInfo()
8043 */
8044
8045/*!
8046 \enum QRhiSwapChainHdrInfo::LimitsType
8047
8048 \value LuminanceInNits Indicates that the \l limits union has its
8049 \c luminanceInNits struct set
8050
8051 \value ColorComponentValue Indicates that the \l limits union has its
8052 \c colorComponentValue struct set
8053*/
8054
8055/*!
8056 \enum QRhiSwapChainHdrInfo::LuminanceBehavior
8057
8058 \value SceneReferred Indicates that the color value of 1.0 is interpreted
8059 as 80 nits. This is the behavior of HDR-enabled windows with the Windows
8060 compositor. See
8061 \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range}{this
8062 page} for more information on HDR on Windows.
8063
8064 \value DisplayReferred Indicates that the color value of 1.0 is interpreted
8065 as the value of the SDR white. (which can be e.g. 200 nits, but will vary
8066 depending on screen brightness) This is the behavior of HDR-enabled windows
8067 on Apple platforms. See
8068 \l{https://developer.apple.com/documentation/metal/hdr_content/displaying_hdr_content_in_a_metal_layer}{this
8069 page} for more information on Apple's EDR system.
8070*/
8071
8072/*!
8073 \variable QRhiSwapChainHdrInfo::limitsType
8074
8075 With Metal on macOS/iOS, there is no luminance values exposed in the
8076 platform APIs. Instead, the maximum color component value, that would be
8077 1.0 in a non-HDR setup, is provided. This value indicates what kind of
8078 information is available in \l limits.
8079
8080 \sa QRhiSwapChain::hdrInfo()
8081*/
8082
8083/*!
8084 \variable QRhiSwapChainHdrInfo::limits
8085
8086 Contains the actual values queried from the graphics API or the platform.
8087 The type of data is indicated by \l limitsType. This is therefore a union.
8088 There are currently two options:
8089
8090 Luminance values in nits:
8091
8092 \code
8093 struct {
8094 float minLuminance;
8095 float maxLuminance;
8096 } luminanceInNits;
8097 \endcode
8098
8099 On Windows the minimum and maximum luminance depends on the screen
8100 brightness. While not relevant for desktops, on laptops the screen
8101 brightness may change at any time. Increasing brightness implies decreased
8102 maximum luminance. In addition, the results may also be dependent on the
8103 HDR Content Brightness set in Windows Settings' System/Display/HDR view,
8104 if there is such a setting.
8105
8106 Note however that the changes made to the laptop screen's brightness or in
8107 the system settings while the application is running are not necessarily
8108 reflected in the returned values, meaning calling hdrInfo() again may still
8109 return the same luminance range as before for the rest of the process'
8110 lifetime. The exact behavior is up to DXGI and Qt has no control over it.
8111
8112 \note The Windows compositor works in scene-referred mode for HDR content.
8113 A color component value of 1.0 corresponds to a luminance of 80 nits. When
8114 rendering non-HDR content (e.g. 2D UI elements), the correction of the
8115 white level is often necessary. (e.g., outputting the fragment color (1, 1,
8116 1) will likely lead to showing a shade of white that is too dim on-screen)
8117 See \l sdrWhiteLevel.
8118
8119 For macOS/iOS, the current maximum and potential maximum color
8120 component values are provided:
8121
8122 \code
8123 struct {
8124 float maxColorComponentValue;
8125 float maxPotentialColorComponentValue;
8126 } colorComponentValue;
8127 \endcode
8128
8129 The value may depend on the screen brightness, which on laptops means that
8130 the result may change in the next call to hdrInfo() if the brightness was
8131 changed in the meantime. The maximum screen brightness implies a maximum
8132 color value of 1.0.
8133
8134 \note Apple's EDR is display-referred. 1.0 corresponds to a luminance level
8135 of SDR white (e.g. 200 nits), the value of which varies based on the screen
8136 brightness and possibly other settings. The exact luminance value for that,
8137 or the maximum luminance of the display, are not exposed to the
8138 applications.
8139
8140 \note It has been observed that the color component values are not set to
8141 the correct larger-than-1 value right away on startup on some macOS
8142 systems, but the values tend to change during or after the first frame.
8143
8144 \sa QRhiSwapChain::hdrInfo()
8145*/
8146
8147/*!
8148 \variable QRhiSwapChainHdrInfo::luminanceBehavior
8149
8150 Describes the platform's presumed behavior with regards to color values.
8151
8152 \sa sdrWhiteLevel
8153 */
8154
8155/*!
8156 \variable QRhiSwapChainHdrInfo::sdrWhiteLevel
8157
8158 On Windows this is the dynamic SDR white level in nits. The value is
8159 dependent on the screen brightness (on laptops), and the SDR or HDR Content
8160 Brightness settings in the Windows settings' System/Display/HDR view.
8161
8162 To perform white level correction for non-HDR (SDR) content, such as 2D UI
8163 elemenents, multiply the final color with sdrWhiteLevel / 80.0 whenever
8164 \l luminanceBehavior is SceneReferred. (assuming Windows and a linear
8165 extended sRGB (scRGB) color space)
8166
8167 On other platforms the value is always a pre-defined value, 200. This may
8168 not match the system's actual SDR white level, but the value of this
8169 variable is not relevant in practice when the \l luminanceBehavior is
8170 DisplayReferred, because then the color component value of 1.0 refers to
8171 the SDR white by default.
8172
8173 \sa luminanceBehavior
8174*/
8175
8176/*!
8177 \return the HDR information for the associated display.
8178
8179 Do not assume that this is a cheap operation. Depending on the platform,
8180 this function makes various platform queries which may have a performance
8181 impact.
8182
8183 \note Can be called before createOrResize() as long as the window is
8184 \l{setWindow()}{set}.
8185
8186 \note What happens when moving a window with an initialized swapchain
8187 between displays (HDR to HDR with different characteristics, HDR to SDR,
8188 etc.) is not currently well-defined and depends heavily on the windowing
8189 system and compositor, with potentially varying behavior between platforms.
8190 Currently QRhi only guarantees that hdrInfo() returns valid data, if
8191 available, for the display to which the swapchain's associated window
8192 belonged at the time of createOrResize().
8193
8194 \sa QRhiSwapChainHdrInfo
8195 */
8196QRhiSwapChainHdrInfo QRhiSwapChain::hdrInfo()
8197{
8198 QRhiSwapChainHdrInfo info;
8199 info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
8200 info.limits.luminanceInNits.minLuminance = 0.0f;
8201 info.limits.luminanceInNits.maxLuminance = 1000.0f;
8202 info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
8203 info.sdrWhiteLevel = 200.0f;
8204 return info;
8205}
8206
8207#ifndef QT_NO_DEBUG_STREAM
8208QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
8209{
8210 QDebugStateSaver saver(dbg);
8211 dbg.nospace() << "QRhiSwapChainHdrInfo(";
8212 switch (info.limitsType) {
8214 dbg.nospace() << " minLuminance=" << info.limits.luminanceInNits.minLuminance
8215 << " maxLuminance=" << info.limits.luminanceInNits.maxLuminance;
8216 break;
8218 dbg.nospace() << " maxColorComponentValue=" << info.limits.colorComponentValue.maxColorComponentValue;
8219 dbg.nospace() << " maxPotentialColorComponentValue=" << info.limits.colorComponentValue.maxPotentialColorComponentValue;
8220 break;
8221 }
8222 switch (info.luminanceBehavior) {
8224 dbg.nospace() << " scene-referred, SDR white level=" << info.sdrWhiteLevel;
8225 break;
8227 dbg.nospace() << " display-referred";
8228 break;
8229 }
8230 dbg.nospace() << ')';
8231 return dbg;
8232}
8233#endif
8234
8235/*!
8236 \class QRhiComputePipeline
8237 \inmodule QtGuiPrivate
8238 \inheaderfile rhi/qrhi.h
8239 \since 6.6
8240 \brief Compute pipeline state resource.
8241
8242 \note Setting the shader resource bindings is mandatory. The referenced
8243 QRhiShaderResourceBindings must already have created() called on it by the
8244 time create() is called.
8245
8246 \note Setting the shader is mandatory.
8247
8248 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8249 for details.
8250 */
8251
8252/*!
8253 \enum QRhiComputePipeline::Flag
8254
8255 Flag values for describing pipeline options.
8256
8257 \value CompileShadersWithDebugInfo Requests compiling shaders with debug
8258 information enabled, when applicable. See
8259 QRhiGraphicsPipeline::CompileShadersWithDebugInfo for more information.
8260 */
8261
8262/*!
8263 \return the resource type.
8264 */
8265QRhiResource::Type QRhiComputePipeline::resourceType() const
8266{
8267 return ComputePipeline;
8268}
8269
8270/*!
8271 \internal
8272 */
8273QRhiComputePipeline::QRhiComputePipeline(QRhiImplementation *rhi)
8274 : QRhiResource(rhi)
8275{
8276}
8277
8278/*!
8279 \fn QRhiComputePipeline::Flags QRhiComputePipeline::flags() const
8280 \return the currently set flags.
8281 */
8282
8283/*!
8284 \fn void QRhiComputePipeline::setFlags(Flags f)
8285 Sets the flags \a f.
8286 */
8287
8288/*!
8289 \fn QRhiShaderStage QRhiComputePipeline::shaderStage() const
8290 \return the currently set shader.
8291 */
8292
8293/*!
8294 \fn void QRhiComputePipeline::setShaderStage(const QRhiShaderStage &stage)
8295
8296 Sets the shader to use. \a stage can only refer to the
8297 \l{QRhiShaderStage::Compute}{compute stage}.
8298 */
8299
8300/*!
8301 \fn QRhiShaderResourceBindings *QRhiComputePipeline::shaderResourceBindings() const
8302 \return the currently associated QRhiShaderResourceBindings object.
8303 */
8304
8305/*!
8306 \fn void QRhiComputePipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
8307
8308 Associates with \a srb describing the resource binding layout and the
8309 resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional. As
8310 with graphics pipelines, the \a srb passed in here can leave the actual
8311 buffer or texture objects unspecified (\nullptr) as long as there is
8312 another,
8313 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
8314 QRhiShaderResourceBindings bound via
8315 \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
8316 recording the dispatch call.
8317 */
8318
8319/*!
8320 \class QRhiCommandBuffer
8321 \inmodule QtGuiPrivate
8322 \inheaderfile rhi/qrhi.h
8323 \since 6.6
8324 \brief Command buffer resource.
8325
8326 Not creatable by applications at the moment. The only ways to obtain a
8327 valid QRhiCommandBuffer are to get it from the targeted swapchain via
8328 QRhiSwapChain::currentFrameCommandBuffer(), or, in case of rendering
8329 completely offscreen, initializing one via QRhi::beginOffscreenFrame().
8330
8331 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8332 for details.
8333 */
8334
8335/*!
8336 \enum QRhiCommandBuffer::IndexFormat
8337 Specifies the index data type
8338
8339 \value IndexUInt16 Unsigned 16-bit (quint16)
8340 \value IndexUInt32 Unsigned 32-bit (quint32)
8341 */
8342
8343/*!
8344 \enum QRhiCommandBuffer::BeginPassFlag
8345 Flag values for QRhi::beginPass()
8346
8347 \value ExternalContent Specifies that there will be a call to
8348 QRhiCommandBuffer::beginExternal() in this pass. Some backends, Vulkan in
8349 particular, will fail if this flag is not set and beginExternal() is still
8350 called.
8351
8352 \value DoNotTrackResourcesForCompute Specifies that there is no need to
8353 track resources used in this pass if the only purpose of such tracking is
8354 to generate barriers for compute. Implies that there are no compute passes
8355 in the frame. This is an optimization hint that may be taken into account
8356 by certain backends, OpenGL in particular, allowing them to skip certain
8357 operations. When this flag is set for a render pass in a frame, calling
8358 \l{QRhiCommandBuffer::beginComputePass()}{beginComputePass()} in that frame
8359 may lead to unexpected behavior, depending on the resource dependencies
8360 between the render and compute passes.
8361 */
8362
8363/*!
8364 \typedef QRhiCommandBuffer::DynamicOffset
8365
8366 Synonym for std::pair<int, quint32>. The first entry is the binding, the second
8367 is the offset in the buffer.
8368*/
8369
8370/*!
8371 \typedef QRhiCommandBuffer::VertexInput
8372
8373 Synonym for std::pair<QRhiBuffer *, quint32>. The second entry is an offset in
8374 the buffer specified by the first.
8375*/
8376
8377/*!
8378 \internal
8379 */
8380QRhiCommandBuffer::QRhiCommandBuffer(QRhiImplementation *rhi)
8381 : QRhiResource(rhi)
8382{
8383}
8384
8385/*!
8386 \return the resource type.
8387 */
8388QRhiResource::Type QRhiCommandBuffer::resourceType() const
8389{
8390 return CommandBuffer;
8391}
8392
8393static const char *resourceTypeStr(const QRhiResource *res)
8394{
8395 switch (res->resourceType()) {
8396 case QRhiResource::Buffer:
8397 return "Buffer";
8398 case QRhiResource::Texture:
8399 return "Texture";
8400 case QRhiResource::Sampler:
8401 return "Sampler";
8402 case QRhiResource::RenderBuffer:
8403 return "RenderBuffer";
8404 case QRhiResource::RenderPassDescriptor:
8405 return "RenderPassDescriptor";
8406 case QRhiResource::SwapChainRenderTarget:
8407 return "SwapChainRenderTarget";
8408 case QRhiResource::TextureRenderTarget:
8409 return "TextureRenderTarget";
8410 case QRhiResource::ShaderResourceBindings:
8411 return "ShaderResourceBindings";
8412 case QRhiResource::GraphicsPipeline:
8413 return "GraphicsPipeline";
8414 case QRhiResource::SwapChain:
8415 return "SwapChain";
8416 case QRhiResource::ComputePipeline:
8417 return "ComputePipeline";
8418 case QRhiResource::CommandBuffer:
8419 return "CommandBuffer";
8420 case QRhiResource::ShadingRateMap:
8421 return "ShadingRateMap";
8422 }
8423
8424 Q_UNREACHABLE_RETURN("");
8425}
8426
8427QRhiImplementation::~QRhiImplementation()
8428{
8429 qDeleteAll(resUpdPool);
8430
8431 // Be nice and show something about leaked stuff. Though we may not get
8432 // this far with some backends where the allocator or the api may check
8433 // and freak out for unfreed graphics objects in the derived dtor already.
8434#ifndef QT_NO_DEBUG
8435 // debug builds: just do it always
8436 static bool leakCheck = true;
8437#else
8438 // release builds: opt-in
8439 static bool leakCheck = qEnvironmentVariableIntValue("QT_RHI_LEAK_CHECK");
8440#endif
8441 if (!resources.isEmpty()) {
8442 if (leakCheck) {
8443 qWarning("QRhi %p going down with %d unreleased resources that own native graphics objects. This is not nice.",
8444 q, int(resources.size()));
8445 }
8446 for (auto it = resources.cbegin(), end = resources.cend(); it != end; ++it) {
8447 QRhiResource *res = it.key();
8448 const bool ownsNativeResources = it.value();
8449 if (leakCheck && ownsNativeResources)
8450 qWarning(" %s resource %p (%s)", resourceTypeStr(res), res, res->m_objectName.constData());
8451
8452 // Null out the resource's rhi pointer. This is why it makes sense to do null
8453 // checks in the destroy() implementations of the various resource types. It
8454 // allows to survive in bad applications that somehow manage to destroy a
8455 // resource of a QRhi after the QRhi itself.
8456 res->m_rhi = nullptr;
8457 }
8458 }
8459}
8460
8461bool QRhiImplementation::isCompressedFormat(QRhiTexture::Format format) const
8462{
8463 return (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
8464 || (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
8465 || (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12);
8466}
8467
8468void QRhiImplementation::compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
8469 quint32 *bpl, quint32 *byteSize,
8470 QSize *blockDim) const
8471{
8472 int xdim = 4;
8473 int ydim = 4;
8474 quint32 blockSize = 0;
8475
8476 switch (format) {
8477 case QRhiTexture::BC1:
8478 blockSize = 8;
8479 break;
8480 case QRhiTexture::BC2:
8481 blockSize = 16;
8482 break;
8483 case QRhiTexture::BC3:
8484 blockSize = 16;
8485 break;
8486 case QRhiTexture::BC4:
8487 blockSize = 8;
8488 break;
8489 case QRhiTexture::BC5:
8490 blockSize = 16;
8491 break;
8492 case QRhiTexture::BC6H:
8493 blockSize = 16;
8494 break;
8495 case QRhiTexture::BC7:
8496 blockSize = 16;
8497 break;
8498
8499 case QRhiTexture::ETC2_RGB8:
8500 blockSize = 8;
8501 break;
8502 case QRhiTexture::ETC2_RGB8A1:
8503 blockSize = 8;
8504 break;
8505 case QRhiTexture::ETC2_RGBA8:
8506 blockSize = 16;
8507 break;
8508
8509 case QRhiTexture::ASTC_4x4:
8510 blockSize = 16;
8511 break;
8512 case QRhiTexture::ASTC_5x4:
8513 blockSize = 16;
8514 xdim = 5;
8515 break;
8516 case QRhiTexture::ASTC_5x5:
8517 blockSize = 16;
8518 xdim = ydim = 5;
8519 break;
8520 case QRhiTexture::ASTC_6x5:
8521 blockSize = 16;
8522 xdim = 6;
8523 ydim = 5;
8524 break;
8525 case QRhiTexture::ASTC_6x6:
8526 blockSize = 16;
8527 xdim = ydim = 6;
8528 break;
8529 case QRhiTexture::ASTC_8x5:
8530 blockSize = 16;
8531 xdim = 8;
8532 ydim = 5;
8533 break;
8534 case QRhiTexture::ASTC_8x6:
8535 blockSize = 16;
8536 xdim = 8;
8537 ydim = 6;
8538 break;
8539 case QRhiTexture::ASTC_8x8:
8540 blockSize = 16;
8541 xdim = ydim = 8;
8542 break;
8543 case QRhiTexture::ASTC_10x5:
8544 blockSize = 16;
8545 xdim = 10;
8546 ydim = 5;
8547 break;
8548 case QRhiTexture::ASTC_10x6:
8549 blockSize = 16;
8550 xdim = 10;
8551 ydim = 6;
8552 break;
8553 case QRhiTexture::ASTC_10x8:
8554 blockSize = 16;
8555 xdim = 10;
8556 ydim = 8;
8557 break;
8558 case QRhiTexture::ASTC_10x10:
8559 blockSize = 16;
8560 xdim = ydim = 10;
8561 break;
8562 case QRhiTexture::ASTC_12x10:
8563 blockSize = 16;
8564 xdim = 12;
8565 ydim = 10;
8566 break;
8567 case QRhiTexture::ASTC_12x12:
8568 blockSize = 16;
8569 xdim = ydim = 12;
8570 break;
8571
8572 default:
8573 Q_UNREACHABLE();
8574 break;
8575 }
8576
8577 const quint32 wblocks = uint((size.width() + xdim - 1) / xdim);
8578 const quint32 hblocks = uint((size.height() + ydim - 1) / ydim);
8579
8580 if (bpl)
8581 *bpl = wblocks * blockSize;
8582 if (byteSize)
8583 *byteSize = wblocks * hblocks * blockSize;
8584 if (blockDim)
8585 *blockDim = QSize(xdim, ydim);
8586}
8587
8588void QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSize &size,
8589 quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const
8590{
8591 if (isCompressedFormat(format)) {
8592 compressedFormatInfo(format, size, bpl, byteSize, nullptr);
8593 return;
8594 }
8595
8596 quint32 bpc = 0;
8597 switch (format) {
8598 case QRhiTexture::RGBA8:
8599 bpc = 4;
8600 break;
8601 case QRhiTexture::BGRA8:
8602 bpc = 4;
8603 break;
8604 case QRhiTexture::R8:
8605 bpc = 1;
8606 break;
8607 case QRhiTexture::RG8:
8608 bpc = 2;
8609 break;
8610 case QRhiTexture::R16:
8611 bpc = 2;
8612 break;
8613 case QRhiTexture::RG16:
8614 bpc = 4;
8615 break;
8616 case QRhiTexture::RED_OR_ALPHA8:
8617 bpc = 1;
8618 break;
8619
8620 case QRhiTexture::RGBA16F:
8621 bpc = 8;
8622 break;
8623 case QRhiTexture::RGBA32F:
8624 bpc = 16;
8625 break;
8626 case QRhiTexture::R16F:
8627 bpc = 2;
8628 break;
8629 case QRhiTexture::R32F:
8630 bpc = 4;
8631 break;
8632
8633 case QRhiTexture::RGB10A2:
8634 bpc = 4;
8635 break;
8636
8637 case QRhiTexture::D16:
8638 bpc = 2;
8639 break;
8640 case QRhiTexture::D24:
8641 case QRhiTexture::D24S8:
8642 case QRhiTexture::D32F:
8643 bpc = 4;
8644 break;
8645
8646 case QRhiTexture::D32FS8:
8647 bpc = 8;
8648 break;
8649
8650 case QRhiTexture::R8SI:
8651 case QRhiTexture::R8UI:
8652 bpc = 1;
8653 break;
8654 case QRhiTexture::R32SI:
8655 case QRhiTexture::R32UI:
8656 bpc = 4;
8657 break;
8658 case QRhiTexture::RG32SI:
8659 case QRhiTexture::RG32UI:
8660 bpc = 8;
8661 break;
8662 case QRhiTexture::RGBA32SI:
8663 case QRhiTexture::RGBA32UI:
8664 bpc = 16;
8665 break;
8666
8667 default:
8668 Q_UNREACHABLE();
8669 break;
8670 }
8671
8672 if (bpl)
8673 *bpl = uint(size.width()) * bpc;
8674 if (byteSize)
8675 *byteSize = uint(size.width() * size.height()) * bpc;
8676 if (bytesPerPixel)
8677 *bytesPerPixel = bpc;
8678}
8679
8680bool QRhiImplementation::isStencilSupportingFormat(QRhiTexture::Format format) const
8681{
8682 switch (format) {
8683 case QRhiTexture::D24S8:
8684 case QRhiTexture::D32FS8:
8685 return true;
8686 default:
8687 break;
8688 }
8689 return false;
8690}
8691
8692bool QRhiImplementation::sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps)
8693{
8694 if (ps->cbeginShaderStages() == ps->cendShaderStages()) {
8695 qWarning("Cannot build a graphics pipeline without any stages");
8696 return false;
8697 }
8698
8699 bool hasVertexStage = false;
8700 for (auto it = ps->cbeginShaderStages(), itEnd = ps->cendShaderStages(); it != itEnd; ++it) {
8701 if (!it->shader().isValid()) {
8702 qWarning("Empty shader passed to graphics pipeline");
8703 return false;
8704 }
8705 if (it->type() == QRhiShaderStage::Vertex)
8706 hasVertexStage = true;
8707 }
8708 if (!hasVertexStage) {
8709 qWarning("Cannot build a graphics pipeline without a vertex stage");
8710 return false;
8711 }
8712
8713 if (!ps->renderPassDescriptor()) {
8714 qWarning("Cannot build a graphics pipeline without a QRhiRenderPassDescriptor");
8715 return false;
8716 }
8717
8718 if (!ps->shaderResourceBindings()) {
8719 qWarning("Cannot build a graphics pipeline without QRhiShaderResourceBindings");
8720 return false;
8721 }
8722
8723 return true;
8724}
8725
8726bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb)
8727{
8728#ifndef QT_NO_DEBUG
8729 bool bindingsOk = true;
8730 const int CHECKED_BINDINGS_COUNT = 64;
8731 bool bindingSeen[CHECKED_BINDINGS_COUNT] = {};
8732 for (auto it = srb->cbeginBindings(), end = srb->cendBindings(); it != end; ++it) {
8733 const int binding = shaderResourceBindingData(*it)->binding;
8734 if (binding >= CHECKED_BINDINGS_COUNT)
8735 continue;
8736 if (binding < 0) {
8737 qWarning("Invalid binding number %d", binding);
8738 bindingsOk = false;
8739 continue;
8740 }
8741 switch (shaderResourceBindingData(*it)->type) {
8742 case QRhiShaderResourceBinding::UniformBuffer:
8743 if (!bindingSeen[binding]) {
8744 bindingSeen[binding] = true;
8745 } else {
8746 qWarning("Uniform buffer duplicates an existing binding number %d", binding);
8747 bindingsOk = false;
8748 }
8749 break;
8750 case QRhiShaderResourceBinding::SampledTexture:
8751 if (!bindingSeen[binding]) {
8752 bindingSeen[binding] = true;
8753 } else {
8754 qWarning("Combined image sampler duplicates an existing binding number %d", binding);
8755 bindingsOk = false;
8756 }
8757 break;
8758 case QRhiShaderResourceBinding::Texture:
8759 if (!bindingSeen[binding]) {
8760 bindingSeen[binding] = true;
8761 } else {
8762 qWarning("Texture duplicates an existing binding number %d", binding);
8763 bindingsOk = false;
8764 }
8765 break;
8766 case QRhiShaderResourceBinding::Sampler:
8767 if (!bindingSeen[binding]) {
8768 bindingSeen[binding] = true;
8769 } else {
8770 qWarning("Sampler duplicates an existing binding number %d", binding);
8771 bindingsOk = false;
8772 }
8773 break;
8774 case QRhiShaderResourceBinding::ImageLoad:
8775 case QRhiShaderResourceBinding::ImageStore:
8776 case QRhiShaderResourceBinding::ImageLoadStore:
8777 if (!bindingSeen[binding]) {
8778 bindingSeen[binding] = true;
8779 } else {
8780 qWarning("Image duplicates an existing binding number %d", binding);
8781 bindingsOk = false;
8782 }
8783 break;
8784 case QRhiShaderResourceBinding::BufferLoad:
8785 case QRhiShaderResourceBinding::BufferStore:
8786 case QRhiShaderResourceBinding::BufferLoadStore:
8787 if (!bindingSeen[binding]) {
8788 bindingSeen[binding] = true;
8789 } else {
8790 qWarning("Buffer duplicates an existing binding number %d", binding);
8791 bindingsOk = false;
8792 }
8793 break;
8794 default:
8795 qWarning("Unknown binding type %d", int(shaderResourceBindingData(*it)->type));
8796 bindingsOk = false;
8797 break;
8798 }
8799 }
8800
8801 if (!bindingsOk) {
8802 qWarning() << *srb;
8803 return false;
8804 }
8805#else
8806 Q_UNUSED(srb);
8807#endif
8808 return true;
8809}
8810
8811int QRhiImplementation::effectiveSampleCount(int sampleCount) const
8812{
8813 // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
8814 const int s = qBound(1, sampleCount, 64);
8815 const QList<int> supported = supportedSampleCounts();
8816 int result = 1;
8817
8818 // Stay compatible with Qt 5 in that requesting an unsupported sample count
8819 // is not an error (although we still do a categorized debug print about
8820 // this), and rather a supported value, preferably a close one, not just 1,
8821 // is used instead. This is actually deviating from Qt 5 as that performs a
8822 // clamping only and does not handle cases such as when sample count 2 is
8823 // not supported but 4 is. (OpenGL handles things like that gracefully,
8824 // other APIs may not, so improve this by picking the next largest, or in
8825 // absence of that, the largest value; this with the goal to not reduce
8826 // quality by rather picking a larger-than-requested value than a smaller one)
8827
8828 for (int i = 0, ie = supported.count(); i != ie; ++i) {
8829 // assumes the 'supported' list is sorted
8830 if (supported[i] >= s) {
8831 result = supported[i];
8832 break;
8833 }
8834 }
8835
8836 if (result != s) {
8837 if (result == 1 && !supported.isEmpty())
8838 result = supported.last();
8839 qCDebug(QRHI_LOG_INFO, "Attempted to set unsupported sample count %d, using %d instead",
8840 sampleCount, result);
8841 }
8842
8843 return result;
8844}
8845
8846/*!
8847 \internal
8848 */
8849QRhi::QRhi()
8850{
8851}
8852
8853/*!
8854 Destructor. Destroys the backend and releases resources.
8855 */
8856QRhi::~QRhi()
8857{
8858 if (!d)
8859 return;
8860
8861 d->runCleanup();
8862
8863 qDeleteAll(d->pendingDeleteResources);
8864 d->pendingDeleteResources.clear();
8865
8866 d->destroy();
8867 delete d;
8868}
8869
8870QRhiImplementation *QRhiImplementation::newInstance(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *importDevice)
8871{
8872 QRhiImplementation *d = nullptr;
8873
8874 switch (impl) {
8875 case QRhi::Null:
8876 d = new QRhiNull(static_cast<QRhiNullInitParams *>(params));
8877 break;
8878 case QRhi::Vulkan:
8879#if QT_CONFIG(vulkan)
8880 d = new QRhiVulkan(static_cast<QRhiVulkanInitParams *>(params),
8881 static_cast<QRhiVulkanNativeHandles *>(importDevice));
8882 break;
8883#else
8884 Q_UNUSED(importDevice);
8885 qWarning("This build of Qt has no Vulkan support");
8886 break;
8887#endif
8888 case QRhi::OpenGLES2:
8889#ifndef QT_NO_OPENGL
8890 d = new QRhiGles2(static_cast<QRhiGles2InitParams *>(params),
8891 static_cast<QRhiGles2NativeHandles *>(importDevice));
8892 break;
8893#else
8894 qWarning("This build of Qt has no OpenGL support");
8895 break;
8896#endif
8897 case QRhi::D3D11:
8898#ifdef Q_OS_WIN
8899 d = new QRhiD3D11(static_cast<QRhiD3D11InitParams *>(params),
8900 static_cast<QRhiD3D11NativeHandles *>(importDevice));
8901 break;
8902#else
8903 qWarning("This platform has no Direct3D 11 support");
8904 break;
8905#endif
8906 case QRhi::Metal:
8907#if QT_CONFIG(metal)
8908 d = new QRhiMetal(static_cast<QRhiMetalInitParams *>(params),
8909 static_cast<QRhiMetalNativeHandles *>(importDevice));
8910 break;
8911#else
8912 qWarning("This platform has no Metal support");
8913 break;
8914#endif
8915 case QRhi::D3D12:
8916#ifdef Q_OS_WIN
8917#ifdef QRHI_D3D12_AVAILABLE
8918 d = new QRhiD3D12(static_cast<QRhiD3D12InitParams *>(params),
8919 static_cast<QRhiD3D12NativeHandles *>(importDevice));
8920 break;
8921#else
8922 qWarning("Qt was built without Direct3D 12 support. "
8923 "This is likely due to having ancient SDK headers (such as d3d12.h) in the Qt build environment. "
8924 "Rebuild Qt with an SDK supporting D3D12 features introduced in Windows 10 version 1703, "
8925 "or use an MSVC build as those typically are built with more up-to-date SDKs.");
8926 break;
8927#endif
8928#else
8929 qWarning("This platform has no Direct3D 12 support");
8930 break;
8931#endif
8932 }
8933
8934 return d;
8935}
8936
8937void QRhiImplementation::prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags, QRhiAdapter *adapter)
8938{
8939 q = rhi;
8940
8941 debugMarkers = flags.testFlag(QRhi::EnableDebugMarkers);
8942
8943 implType = impl;
8944 implThread = QThread::currentThread();
8945
8946 requestedRhiAdapter = adapter;
8947}
8948
8949QRhi::AdapterList QRhiImplementation::enumerateAdaptersBeforeCreate(QRhiNativeHandles *) const
8950{
8951 return {};
8952}
8953
8954/*!
8955 \overload
8956
8957 Equivalent to create(\a impl, \a params, \a flags, \a importDevice, \c nullptr).
8958 */
8959QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice)
8960{
8961 return create(impl, params, flags, importDevice, nullptr);
8962}
8963
8964/*!
8965 \return a new QRhi instance with a backend for the graphics API specified
8966 by \a impl with the specified \a flags. \return \c nullptr if the
8967 function fails.
8968
8969 \a params must point to an instance of one of the backend-specific
8970 subclasses of QRhiInitParams, such as, QRhiVulkanInitParams,
8971 QRhiMetalInitParams, QRhiD3D11InitParams, QRhiD3D12InitParams,
8972 QRhiGles2InitParams. See these classes for examples on creating a QRhi.
8973
8974 QRhi by design does not implement any fallback logic: if the specified API
8975 cannot be initialized, create() will fail, with warnings printed on the
8976 debug output by the backends. The clients of QRhi, for example Qt Quick,
8977 may however provide additional logic that allow falling back to an API
8978 different than what was requested, depending on the platform. If the
8979 intention is just to test if initialization would succeed when calling
8980 create() at later point, it is preferable to use probe() instead of
8981 create(), because with some backends probing can be implemented in a more
8982 lightweight manner as opposed to create(), which performs full
8983 initialization of the infrastructure and is wasteful if that QRhi instance
8984 is then thrown immediately away.
8985
8986 \a importDevice allows using an already existing graphics device, without
8987 QRhi creating its own. When not null, this parameter must point to an
8988 instance of one of the subclasses of QRhiNativeHandles:
8989 QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles,
8990 QRhiMetalNativeHandles, QRhiGles2NativeHandles. The exact details and
8991 semantics depend on the backand and the underlying graphics API.
8992
8993 Specifying a QRhiAdapter in \a adapter offers a transparent, cross-API
8994 alternative to passing in a \c VkPhysicalDevice via QRhiVulkanNativeHandles,
8995 or an adapter LUID via QRhiD3D12NativeHandles. The ownership of \a adapter
8996 is not taken. See enumerateAdapters() for more information on this approach.
8997
8998 \note \a importDevice and \a adapter cannot be both specified.
8999
9000 \sa probe()
9001 */
9002QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice, QRhiAdapter *adapter)
9003{
9004 if (adapter && importDevice)
9005 qWarning("adapter and importDevice should not both be non-null in QRhi::create()");
9006
9007 std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, importDevice));
9008 if (!rd)
9009 return nullptr;
9010
9011 std::unique_ptr<QRhi> r(new QRhi);
9012 r->d = rd.release();
9013 r->d->prepareForCreate(r.get(), impl, flags, adapter);
9014 if (!r->d->create(flags))
9015 return nullptr;
9016
9017 return r.release();
9018}
9019
9020/*!
9021 \return true if create() can be expected to succeed when called the given
9022 \a impl and \a params.
9023
9024 For some backends this is equivalent to calling create(), checking its
9025 return value, and then destroying the resulting QRhi.
9026
9027 For others, in particular with Metal, there may be a specific probing
9028 implementation, which allows testing in a more lightweight manner without
9029 polluting the debug output with warnings upon failures.
9030
9031 \sa create()
9032 */
9033bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)
9034{
9035 bool ok = false;
9036
9037 // The only place currently where this makes sense is Metal, where the API
9038 // is simple enough so that a special probing function - doing nothing but
9039 // a MTLCreateSystemDefaultDevice - is reasonable. Elsewhere, just call
9040 // create() and then drop the result.
9041
9042 if (impl == Metal) {
9043#if QT_CONFIG(metal)
9044 ok = QRhiMetal::probe(static_cast<QRhiMetalInitParams *>(params));
9045#endif
9046 } else {
9047 QRhi *rhi = create(impl, params);
9048 ok = rhi != nullptr;
9049 delete rhi;
9050 }
9051 return ok;
9052}
9053
9054/*!
9055 \typedef QRhi::AdapterList
9056 \relates QRhi
9057 \since 6.10
9058
9059 Synonym for QVector<QRhiAdapter *>.
9060*/
9061
9062/*!
9063 \return the list of adapters (physical devices) present, or an empty list
9064 when such control is not available with a given graphics API.
9065
9066 Backends where such level of control is not available, the returned list is
9067 always empty. Thus an empty list does not indicate there are no graphics
9068 devices in the system, but that fine-grained control over selecting which
9069 one to use is not available.
9070
9071 Backends for Direct 3D 11, Direct 3D 12, and Vulkan can be expected to fully
9072 support enumerating adapters. Others may not. The backend is specified by \a
9073 impl. A QRhiAdapter returned from this function must only be used in a
9074 create() call with the same \a impl. Some underlying APIs may present
9075 further limitations, with Vulkan in particular the QRhiAdapter is specified
9076 to the QVulkanInstance (\c VkInstance).
9077
9078 The caller is expected to destroy the QRhiAdapter objects in the list. Apart
9079 from querying \l{QRhiAdapter::}{info()}, the only purpose of these objects is
9080 to be passed on to create(), or the corresponding functions in higher layers
9081 such as Qt Quick.
9082
9083 The following snippet, written specifically for Vulkan, shows how to
9084 enumerate the available physical devices and request to create a QRhi for
9085 the chosen one. This in practice is equivalent to passing in a \c
9086 VkPhysicalDevice via a QRhiVulkanNativeHandles to create(), but it involves
9087 less API-specific code on the application side:
9088
9089 \code
9090 QRhiVulkanInitParams initParams;
9091 initParams.inst = &vulkanInstance;
9092 QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::Vulkan, &initParams);
9093 QRhiAdapter *chosenAdapter = nullptr;
9094 for (QRhiAdapter *adapter : adapters) {
9095 if (looksGood(adapter->info())) {
9096 chosenAdapter = adapter;
9097 break;
9098 }
9099 }
9100 QRhi *rhi = QRhi::create(QRhi::Vulkan, &initParams, {}, nullptr, chosenAdapter);
9101 qDeleteAll(adapters);
9102 \endcode
9103
9104 Passing in \a params is required due to some of the underlying graphics
9105 APIs' design. With Vulkan in particular, the QVulkanInstance must be
9106 provided, since enumerating is not possible without it. Other fields in the
9107 backend-specific \a params will not actually be used by this function.
9108
9109 \a nativeHandles is optional. When specified, it must be a valid
9110 QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, or QRhiVulkanNativeHandles,
9111 similarly to create(). However, unlike create(), only the physical device
9112 (in case of Vulkan) or the adapter LUID (in case of D3D) fields are used,
9113 all other fields are ignored. This can be used the restrict the results to a
9114 given adapter. The returned list will contain 1 or 0 elements in this case.
9115
9116 Note how in the previous code snippet the looksGood() function
9117 implementation cannot perform any platform-specific filtering based on the
9118 true adapter / physical device identity, such as the adapter LUID on Windows
9119 or the VkPhysicalDevice with Vulkan. This is because QRhiDriverInfo does not
9120 contain platform-specific data. Instead, use \a nativeHandles to get the
9121 results filtered already inside enumerateAdapters().
9122
9123 The following two snippets, using Direct 3D 12 as an example, are equivalent
9124 in practice:
9125
9126 \code
9127 // enumerateAdapters-based approach from Qt 6.10 on
9128 QRhiD3D12InitParams initParams;
9129 QRhiD3D12NativeHandles nativeHandles;
9130 nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
9131 nativeHandles.adapterLuidHigh = luid.HighPart;
9132 QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::D3D12, &initParams, &nativeHandles);
9133 if (adapters.isEmpty()) { qWarning("Requested adapter was not found"); }
9134 QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, nullptr, adapters[0]);
9135 qDeleteAll(adapters);
9136 \endcode
9137
9138 \code
9139 // traditional approach, more lightweight
9140 QRhiD3D12InitParams initParams;
9141 QRhiD3D12NativeHandles nativeHandles;
9142 nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
9143 nativeHandles.adapterLuidHigh = luid.HighPart;
9144 QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, &nativeHandles, nullptr);
9145 \endcode
9146
9147 \since 6.10
9148 \sa create()
9149 */
9150QRhi::AdapterList QRhi::enumerateAdapters(Implementation impl, QRhiInitParams *params, QRhiNativeHandles *nativeHandles)
9151{
9152 std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, nullptr));
9153 if (!rd)
9154 return {};
9155
9156 return rd->enumerateAdaptersBeforeCreate(nativeHandles);
9157}
9158
9159/*!
9160 \struct QRhiSwapChainProxyData
9161 \inmodule QtGuiPrivate
9162 \inheaderfile rhi/qrhi.h
9163 \since 6.6
9164
9165 \brief Opaque data describing native objects needed to set up a swapchain.
9166
9167 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9168 for details.
9169
9170 \sa QRhi::updateSwapChainProxyData()
9171 */
9172
9173/*!
9174 Generates and returns a QRhiSwapChainProxyData struct containing opaque
9175 data specific to the backend and graphics API specified by \a impl. \a
9176 window is the QWindow a swapchain is targeting.
9177
9178 The returned struct can be passed to QRhiSwapChain::setProxyData(). This
9179 makes sense in threaded rendering systems: this static function is expected
9180 to be called on the \b{main (gui) thread}, unlike all QRhi operations, then
9181 transferred to the thread working with the QRhi and QRhiSwapChain and passed
9182 on to the swapchain. This allows doing native platform queries that are
9183 only safe to be called on the main thread, for example to query the
9184 CAMetalLayer from a NSView, and then passing on the data to the
9185 QRhiSwapChain living on the rendering thread. With the Metal example, doing
9186 the view.layer access on a dedicated rendering thread causes a warning in
9187 the Xcode Thread Checker. With the data proxy mechanism, this is avoided.
9188
9189 When threads are not involved, generating and passing on the
9190 QRhiSwapChainProxyData is not required: backends are guaranteed to be able
9191 to query whatever is needed on their own, and if everything lives on the
9192 main (gui) thread, that should be sufficient.
9193
9194 \note \a impl should match what the QRhi is created with. For example,
9195 calling with QRhi::Metal on a non-Apple platform will not generate any
9196 useful data.
9197 */
9198QRhiSwapChainProxyData QRhi::updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)
9199{
9200#if QT_CONFIG(metal)
9201 if (impl == Metal)
9202 return QRhiMetal::updateSwapChainProxyData(window);
9203#else
9204 Q_UNUSED(impl);
9205 Q_UNUSED(window);
9206#endif
9207 return {};
9208}
9209
9210/*!
9211 \return the backend type for this QRhi.
9212 */
9213QRhi::Implementation QRhi::backend() const
9214{
9215 return d->implType;
9216}
9217
9218/*!
9219 \return a friendly name for the backend \a impl, usually the name of the 3D
9220 API in use.
9221 */
9222const char *QRhi::backendName(Implementation impl)
9223{
9224 switch (impl) {
9225 case QRhi::Null:
9226 return "Null";
9227 case QRhi::Vulkan:
9228 return "Vulkan";
9229 case QRhi::OpenGLES2:
9230 return "OpenGL";
9231 case QRhi::D3D11:
9232 return "D3D11";
9233 case QRhi::Metal:
9234 return "Metal";
9235 case QRhi::D3D12:
9236 return "D3D12";
9237 }
9238
9239 Q_UNREACHABLE_RETURN("Unknown");
9240}
9241
9242/*!
9243 \return the backend type as string for this QRhi.
9244 */
9245const char *QRhi::backendName() const
9246{
9247 return backendName(d->implType);
9248}
9249
9250/*!
9251 \enum QRhiDriverInfo::DeviceType
9252 Specifies the graphics device's type, when the information is available.
9253
9254 In practice this is only applicable with Vulkan and Metal. With Direct 3D
9255 11 and 12, using an adapter with the software flag set leads to the value
9256 \c CpuDevice. Otherwise, and with OpenGL, the value is always UnknownDevice.
9257
9258 \value UnknownDevice
9259 \value IntegratedDevice
9260 \value DiscreteDevice
9261 \value ExternalDevice
9262 \value VirtualDevice
9263 \value CpuDevice
9264*/
9265
9266/*!
9267 \struct QRhiDriverInfo
9268 \inmodule QtGuiPrivate
9269 \inheaderfile rhi/qrhi.h
9270 \since 6.6
9271
9272 \brief Describes the physical device, adapter, or graphics API
9273 implementation that is used by an initialized QRhi.
9274
9275 Graphics APIs offer different levels and kinds of information. The only
9276 value that is available across all APIs is the deviceName, which is a
9277 freetext description of the physical device, adapter, or is a combination
9278 of the strings reported for \c{GL_VENDOR} + \c{GL_RENDERER} +
9279 \c{GL_VERSION}. The deviceId is always 0 for OpenGL. vendorId is always 0
9280 for OpenGL and Metal. deviceType is always UnknownDevice for OpenGL and
9281 Direct 3D.
9282
9283 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9284 for details.
9285 */
9286
9287/*!
9288 \variable QRhiDriverInfo::deviceName
9289
9290 \sa QRhi::driverInfo()
9291*/
9292
9293/*!
9294 \variable QRhiDriverInfo::deviceId
9295
9296 \sa QRhi::driverInfo()
9297*/
9298
9299/*!
9300 \variable QRhiDriverInfo::vendorId
9301
9302 \sa QRhi::driverInfo()
9303*/
9304
9305/*!
9306 \variable QRhiDriverInfo::deviceType
9307
9308 \sa QRhi::driverInfo(), QRhiDriverInfo::DeviceType
9309*/
9310
9311#ifndef QT_NO_DEBUG_STREAM
9312static inline const char *deviceTypeStr(QRhiDriverInfo::DeviceType type)
9313{
9314 switch (type) {
9315 case QRhiDriverInfo::UnknownDevice:
9316 return "Unknown";
9317 case QRhiDriverInfo::IntegratedDevice:
9318 return "Integrated";
9319 case QRhiDriverInfo::DiscreteDevice:
9320 return "Discrete";
9321 case QRhiDriverInfo::ExternalDevice:
9322 return "External";
9323 case QRhiDriverInfo::VirtualDevice:
9324 return "Virtual";
9325 case QRhiDriverInfo::CpuDevice:
9326 return "Cpu";
9327 }
9328
9329 Q_UNREACHABLE_RETURN(nullptr);
9330}
9331QDebug operator<<(QDebug dbg, const QRhiDriverInfo &info)
9332{
9333 QDebugStateSaver saver(dbg);
9334 dbg.nospace() << "QRhiDriverInfo(deviceName=" << info.deviceName
9335 << " deviceId=0x" << Qt::hex << info.deviceId
9336 << " vendorId=0x" << info.vendorId
9337 << " deviceType=" << deviceTypeStr(info.deviceType)
9338 << ')';
9339 return dbg;
9340}
9341#endif
9342
9343/*!
9344 \return metadata for the graphics device used by this successfully
9345 initialized QRhi instance.
9346 */
9347QRhiDriverInfo QRhi::driverInfo() const
9348{
9349 return d->driverInfo();
9350}
9351
9352/*!
9353 \class QRhiAdapter
9354 \inmodule QtGuiPrivate
9355 \inheaderfile rhi/qrhi.h
9356 \since 6.10
9357
9358 \brief Represents a physical graphics device.
9359
9360 Some QRhi backends target graphics APIs that expose the concept of \c
9361 adapters or \c{physical devices}. Call the static \l
9362 {QRhi::}{enumerateAdapters()} function to retrieve a list of the adapters
9363 present in the system. Pass one of the returned QRhiAdapter objects to \l
9364 {QRhi::}{create()} in order to request using the adapter or physical device
9365 the QRhiAdapter corresponds to. Other than exposing the QRhiDriverInfo,
9366 QRhiAdapter is to be treated as an opaque handle.
9367
9368 \note With Vulkan, the QRhiAdapter is valid only as long as the
9369 QVulkanInstance that was used for \l{QRhi::}{enumerateAdapters()} is valid.
9370 This also means that a QRhiAdapter is tied to the Vulkan instance
9371 (QVulkanInstance, \c VkInstance) and cannot be used in the context of
9372 another Vulkan instance.
9373
9374 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9375 for details.
9376 */
9377
9378/*!
9379 \fn virtual QRhiDriverInfo QRhiAdapter::info() const = 0
9380
9381 \return the corresponding QRhiDriverInfo.
9382 */
9383
9384/*!
9385 \internal
9386 */
9387QRhiAdapter::~QRhiAdapter()
9388{
9389}
9390
9391/*!
9392 \return the thread on which the QRhi was \l{QRhi::create()}{initialized}.
9393 */
9394QThread *QRhi::thread() const
9395{
9396 return d->implThread;
9397}
9398
9399/*!
9400 Registers a \a callback that is invoked when the QRhi is destroyed.
9401
9402 The callback will run with the graphics resource still available, so this
9403 provides an opportunity for the application to cleanly release QRhiResource
9404 instances belonging to the QRhi. This is particularly useful for managing
9405 the lifetime of resources stored in \c cache type of objects, where the
9406 cache holds QRhiResources or objects containing QRhiResources.
9407
9408 \sa ~QRhi()
9409 */
9410void QRhi::addCleanupCallback(const CleanupCallback &callback)
9411{
9412 d->addCleanupCallback(callback);
9413}
9414
9415/*!
9416 \overload
9417
9418 Registers \a callback to be invoked when the QRhi is destroyed. This
9419 overload takes an opaque pointer, \a key, that is used to ensure that a
9420 given callback is registered (and so called) only once.
9421
9422 \sa removeCleanupCallback()
9423 */
9424void QRhi::addCleanupCallback(const void *key, const CleanupCallback &callback)
9425{
9426 d->addCleanupCallback(key, callback);
9427}
9428
9429/*!
9430 Deregisters the callback with \a key. If no cleanup callback was registered
9431 with \a key, the function does nothing. Callbacks registered without a key
9432 cannot be removed.
9433
9434 \sa addCleanupCallback()
9435 */
9436void QRhi::removeCleanupCallback(const void *key)
9437{
9438 d->removeCleanupCallback(key);
9439}
9440
9441void QRhiImplementation::runCleanup()
9442{
9443 for (const QRhi::CleanupCallback &f : std::as_const(cleanupCallbacks))
9444 f(q);
9445
9446 cleanupCallbacks.clear();
9447
9448 for (auto it = keyedCleanupCallbacks.cbegin(), end = keyedCleanupCallbacks.cend(); it != end; ++it)
9449 it.value()(q);
9450
9451 keyedCleanupCallbacks.clear();
9452}
9453
9454/*!
9455 \class QRhiResourceUpdateBatch
9456 \inmodule QtGuiPrivate
9457 \inheaderfile rhi/qrhi.h
9458 \since 6.6
9459 \brief Records upload and copy type of operations.
9460
9461 With QRhi it is no longer possible to perform copy type of operations at
9462 arbitrary times. Instead, all such operations are recorded into batches
9463 that are then passed, most commonly, to QRhiCommandBuffer::beginPass().
9464 What then happens under the hood is hidden from the application: the
9465 underlying implementations can defer and implement these operations in
9466 various different ways.
9467
9468 A resource update batch owns no graphics resources and does not perform any
9469 actual operations on its own. It should rather be viewed as a command
9470 buffer for update, upload, and copy type of commands.
9471
9472 To get an available, empty batch from the pool, call
9473 QRhi::nextResourceUpdateBatch().
9474
9475 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9476 for details.
9477 */
9478
9479/*!
9480 \internal
9481 */
9482QRhiResourceUpdateBatch::QRhiResourceUpdateBatch(QRhiImplementation *rhi)
9483 : d(new QRhiResourceUpdateBatchPrivate)
9484{
9485 d->q = this;
9486 d->rhi = rhi;
9487}
9488
9489QRhiResourceUpdateBatch::~QRhiResourceUpdateBatch()
9490{
9491 delete d;
9492}
9493
9494/*!
9495 \return the batch to the pool. This should only be used when the batch is
9496 not passed to one of QRhiCommandBuffer::beginPass(),
9497 QRhiCommandBuffer::endPass(), or QRhiCommandBuffer::resourceUpdate()
9498 because these implicitly call destroy().
9499
9500 \note QRhiResourceUpdateBatch instances must never by \c deleted by
9501 applications.
9502 */
9503void QRhiResourceUpdateBatch::release()
9504{
9505 d->free();
9506}
9507
9508/*!
9509 Copies all queued operations from the \a other batch into this one.
9510
9511 \note \a other may no longer contain valid data after the merge operation,
9512 and must not be submitted, but it will still need to be released by calling
9513 release().
9514
9515 This allows for a convenient pattern where resource updates that are
9516 already known during the initialization step are collected into a batch
9517 that is then merged into another when starting to first render pass later
9518 on:
9519
9520 \code
9521 void init()
9522 {
9523 initialUpdates = rhi->nextResourceUpdateBatch();
9524 initialUpdates->uploadStaticBuffer(vbuf, vertexData);
9525 initialUpdates->uploadStaticBuffer(ibuf, indexData);
9526 // ...
9527 }
9528
9529 void render()
9530 {
9531 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
9532 if (initialUpdates) {
9533 resUpdates->merge(initialUpdates);
9534 initialUpdates->release();
9535 initialUpdates = nullptr;
9536 }
9537 // resUpdates->updateDynamicBuffer(...);
9538 cb->beginPass(rt, clearCol, clearDs, resUpdates);
9539 }
9540 \endcode
9541 */
9542void QRhiResourceUpdateBatch::merge(QRhiResourceUpdateBatch *other)
9543{
9544 d->merge(other->d);
9545}
9546
9547/*!
9548 \return true until the number of buffer and texture operations enqueued
9549 onto this batch is below a reasonable limit.
9550
9551 The return value is false when the number of buffer and/or texture
9552 operations added to this batch have reached, or are about to reach, a
9553 certain limit. The batch is fully functional afterwards as well, but may
9554 need to allocate additional memory. Therefore, a renderer that collects
9555 lots of buffer and texture updates in a single batch when preparing a frame
9556 may want to consider \l{QRhiCommandBuffer::resourceUpdate()}{submitting the
9557 batch} and \l{QRhi::nextResourceUpdateBatch()}{starting a new one} when
9558 this function returns false.
9559 */
9560bool QRhiResourceUpdateBatch::hasOptimalCapacity() const
9561{
9562 return d->hasOptimalCapacity();
9563}
9564
9565/*!
9566 Enqueues updating a region of a QRhiBuffer \a buf created with the type
9567 QRhiBuffer::Dynamic.
9568
9569 The region is specified \a offset and \a size. The actual bytes to write
9570 are specified by \a data which must have at least \a size bytes available.
9571
9572 \a data is copied and can safely be destroyed or changed once this function
9573 returns.
9574
9575 \note If host writes are involved, which is the case with
9576 updateDynamicBuffer() typically as such buffers are backed by host visible
9577 memory with most backends, they may accumulate within a frame. Thus pass 1
9578 reading a region changed by a batch passed to pass 2 may see the changes
9579 specified in pass 2's update batch.
9580
9581 \note QRhi transparently manages double buffering in order to prevent
9582 stalling the graphics pipeline. The fact that a QRhiBuffer may have
9583 multiple native buffer objects underneath can be safely ignored when using
9584 the QRhi and QRhiResourceUpdateBatch.
9585 */
9586void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
9587{
9588 if (size > 0) {
9589 const int idx = d->activeBufferOpCount++;
9590 const int opListSize = d->bufferOps.size();
9591 if (idx < opListSize)
9592 QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, size, data);
9593 else
9594 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, size, data));
9595 }
9596}
9597
9598/*!
9599 \overload
9600 \since 6.10
9601
9602 Enqueues updating a region of a QRhiBuffer \a buf created with the type
9603 QRhiBuffer::Dynamic.
9604
9605 \a data is moved into the batch instead of copied with this overload.
9606 */
9607void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
9608{
9609 if (!data.isEmpty()) {
9610 const int idx = d->activeBufferOpCount++;
9611 const int opListSize = d->bufferOps.size();
9612 if (idx < opListSize)
9613 QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, std::move(data));
9614 else
9615 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, std::move(data)));
9616 }
9617}
9618
9619/*!
9620 Enqueues updating a region of a QRhiBuffer \a buf created with the type
9621 QRhiBuffer::Immutable or QRhiBuffer::Static.
9622
9623 The region is specified \a offset and \a size. The actual bytes to write
9624 are specified by \a data which must have at least \a size bytes available.
9625
9626 \a data is copied and can safely be destroyed or changed once this function
9627 returns.
9628 */
9629void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
9630{
9631 if (size > 0) {
9632 const int idx = d->activeBufferOpCount++;
9633 if (idx < d->bufferOps.size())
9634 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, size, data);
9635 else
9636 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, size, data));
9637 }
9638}
9639
9640/*!
9641 \overload
9642 \since 6.10
9643
9644 Enqueues updating a region of a QRhiBuffer \a buf created with the type
9645 QRhiBuffer::Immutable or QRhiBuffer::Static.
9646
9647 \a data is moved into the batch instead of copied with this overload.
9648 */
9649void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
9650{
9651 if (!data.isEmpty()) {
9652 const int idx = d->activeBufferOpCount++;
9653 if (idx < d->bufferOps.size())
9654 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, std::move(data));
9655 else
9656 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, std::move(data)));
9657 }
9658}
9659
9660/*!
9661 \overload
9662
9663 Enqueues updating the entire QRhiBuffer \a buf created with the type
9664 QRhiBuffer::Immutable or QRhiBuffer::Static.
9665 */
9666void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *data)
9667{
9668 if (buf->size() > 0) {
9669 const int idx = d->activeBufferOpCount++;
9670 if (idx < d->bufferOps.size())
9671 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, 0, data);
9672 else
9673 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, 0, data));
9674 }
9675}
9676
9677/*!
9678 \overload
9679 \since 6.10
9680
9681 Enqueues updating the entire QRhiBuffer \a buf created with the type
9682 QRhiBuffer::Immutable or QRhiBuffer::Static.
9683
9684 \a data is moved into the batch instead of copied with this overload.
9685
9686 \a data size must equal the size of \a buf.
9687 */
9688void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, QByteArray data)
9689{
9690 if (buf->size() > 0 && quint32(data.size()) == buf->size()) {
9691 const int idx = d->activeBufferOpCount++;
9692 if (idx < d->bufferOps.size())
9693 QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, std::move(data));
9694 else
9695 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, std::move(data)));
9696 }
9697}
9698
9699/*!
9700 Enqueues reading back a region of the QRhiBuffer \a buf. The size of the
9701 region is specified by \a size in bytes, \a offset is the offset in bytes
9702 to start reading from.
9703
9704 A readback is asynchronous. \a result contains a callback that is invoked
9705 when the operation has completed. The data is provided in
9706 QRhiReadbackResult::data. Upon successful completion that QByteArray
9707 will have a size equal to \a size. On failure the QByteArray will be empty.
9708
9709 \note Reading buffers with a usage different than QRhiBuffer::UniformBuffer
9710 is supported only when the QRhi::ReadBackNonUniformBuffer feature is
9711 reported as supported.
9712
9713 \note The asynchronous readback is guaranteed to have completed when one of
9714 the following conditions is met: \l{QRhi::finish()}{finish()} has been
9715 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
9716 including the frame that issued the readback operation, and the
9717 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
9718 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
9719 QRhi::MaxAsyncReadbackFrames.
9720
9721 \sa readBackTexture(), QRhi::isFeatureSupported(), QRhi::resourceLimit()
9722 */
9723void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
9724{
9725 const int idx = d->activeBufferOpCount++;
9726 if (idx < d->bufferOps.size())
9727 d->bufferOps[idx] = QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result);
9728 else
9729 d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result));
9730}
9731
9732/*!
9733 Enqueues uploading the image data for one or more mip levels in one or more
9734 layers of the texture \a tex.
9735
9736 The details of the copy (source QImage or compressed texture data, regions,
9737 target layers and levels) are described in \a desc.
9738 */
9739void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
9740{
9741 if (desc.cbeginEntries() != desc.cendEntries()) {
9742 const int idx = d->activeTextureOpCount++;
9743 if (idx < d->textureOps.size())
9744 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc);
9745 else
9746 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc));
9747 }
9748}
9749
9750/*!
9751 Enqueues uploading the image data for mip level 0 of layer 0 of the texture
9752 \a tex.
9753
9754 \a tex must have an uncompressed format. Its format must also be compatible
9755 with the QImage::format() of \a image. The source data is given in \a
9756 image.
9757 */
9758void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &image)
9759{
9760 uploadTexture(tex,
9761 QRhiTextureUploadEntry(0, 0, QRhiTextureSubresourceUploadDescription(image)));
9762}
9763
9764/*!
9765 Enqueues a texture-to-texture copy operation from \a src into \a dst as
9766 described by \a desc.
9767
9768 \note The source texture \a src must be created with
9769 QRhiTexture::UsedAsTransferSource.
9770
9771 \note The format of the textures must match. With most graphics
9772 APIs the data is copied as-is without any format conversions. If
9773 \a dst and \a src are created with different formats, unspecified
9774 issues may arise.
9775 */
9776void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
9777{
9778 const int idx = d->activeTextureOpCount++;
9779 if (idx < d->textureOps.size())
9780 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc);
9781 else
9782 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc));
9783}
9784
9785/*!
9786 Enqueues a texture-to-host copy operation as described by \a rb.
9787
9788 Normally \a rb will specify a QRhiTexture as the source. However, when the
9789 swapchain in the current frame was created with
9790 QRhiSwapChain::UsedAsTransferSource, it can also be the source of the
9791 readback. For this, leave the texture set to null in \a rb.
9792
9793 Unlike other operations, the results here need to be processed by the
9794 application. Therefore, \a result provides not just the data but also a
9795 callback as operations on the batch are asynchronous by nature:
9796
9797 \code
9798 rhi->beginFrame(swapchain);
9799 cb->beginPass(swapchain->currentFrameRenderTarget(), colorClear, dsClear);
9800 // ...
9801 QRhiReadbackResult *rbResult = new QRhiReadbackResult;
9802 rbResult->completed = [rbResult] {
9803 {
9804 const QImage::Format fmt = QImage::Format_RGBA8888_Premultiplied; // fits QRhiTexture::RGBA8
9805 const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
9806 QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
9807 image.save("result.png");
9808 }
9809 delete rbResult;
9810 };
9811 QRhiResourceUpdateBatch *u = nextResourceUpdateBatch();
9812 QRhiReadbackDescription rb; // no texture -> uses the current backbuffer of sc
9813 u->readBackTexture(rb, rbResult);
9814 cb->endPass(u);
9815 rhi->endFrame(swapchain);
9816 \endcode
9817
9818 \note The texture must be created with QRhiTexture::UsedAsTransferSource.
9819
9820 \note Multisample textures cannot be read back.
9821
9822 \note The readback returns raw byte data, in order to allow the applications
9823 to interpret it in any way they see fit. Be aware of the blending settings
9824 of rendering code: if the blending is set up to rely on premultiplied alpha,
9825 the results of the readback must also be interpreted as Premultiplied.
9826
9827 \note When interpreting the resulting raw data, be aware that the readback
9828 happens with a byte ordered format. A \l{QRhiTexture::RGBA8}{RGBA8} texture
9829 maps therefore to byte ordered QImage formats, such as,
9830 QImage::Format_RGBA8888.
9831
9832 \note The asynchronous readback is guaranteed to have completed when one of
9833 the following conditions is met: \l{QRhi::finish()}{finish()} has been
9834 called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
9835 including the frame that issued the readback operation, and the
9836 \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
9837 N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
9838 QRhi::MaxAsyncReadbackFrames.
9839
9840 A single readback operation copies one mip level of one layer (cubemap face
9841 or 3D slice or texture array element) at a time. The level and layer are
9842 specified by the respective fields in \a rb.
9843
9844 \sa readBackBuffer(), QRhi::resourceLimit()
9845 */
9846void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
9847{
9848 const int idx = d->activeTextureOpCount++;
9849 if (idx < d->textureOps.size())
9850 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result);
9851 else
9852 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result));
9853}
9854
9855/*!
9856 Enqueues a mipmap generation operation for the specified texture \a tex.
9857
9858 Both 2D and cube textures are supported.
9859
9860 \note The texture must be created with QRhiTexture::MipMapped and
9861 QRhiTexture::UsedWithGenerateMips.
9862
9863 \warning QRhi cannot guarantee that mipmaps can be generated for all
9864 supported texture formats. For example, QRhiTexture::RGBA32F is not a \c
9865 filterable format in OpenGL ES 3.0 and Metal on iOS, and therefore the
9866 mipmap generation request may fail. RGBA8 and RGBA16F are typically
9867 filterable, so it is recommended to use these formats when mipmap generation
9868 is desired.
9869 */
9870void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex)
9871{
9872 const int idx = d->activeTextureOpCount++;
9873 if (idx < d->textureOps.size())
9874 d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex);
9875 else
9876 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex));
9877}
9878
9879/*!
9880 \return an available, empty batch to which copy type of operations can be
9881 recorded.
9882
9883 \note the return value is not owned by the caller and must never be
9884 destroyed. Instead, the batch is returned the pool for reuse by passing
9885 it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or
9886 QRhiCommandBuffer::resourceUpdate(), or by calling
9887 QRhiResourceUpdateBatch::release() on it.
9888
9889 \note Can be called outside beginFrame() - endFrame() as well since a batch
9890 instance just collects data on its own, it does not perform any operations.
9891
9892 Due to not being tied to a frame being recorded, the following sequence is
9893 valid for example:
9894
9895 \code
9896 rhi->beginFrame(swapchain);
9897 QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
9898 u->uploadStaticBuffer(buf, data);
9899 // ... do not commit the batch
9900 rhi->endFrame();
9901 // u stays valid (assuming buf stays valid as well)
9902 rhi->beginFrame(swapchain);
9903 swapchain->currentFrameCommandBuffer()->resourceUpdate(u);
9904 // ... draw with buf
9905 rhi->endFrame();
9906 \endcode
9907
9908 \warning The maximum number of batches per QRhi is 64. When this limit is
9909 reached, the function will return null until a batch is returned to the
9910 pool.
9911 */
9912QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
9913{
9914 // By default we prefer spreading out the utilization of the worst case 64
9915 // (but typically 4) batches as much as possible, meaning we won't pick the
9916 // first one even if it's free, but prefer picking one after the last picked
9917 // one. Relevant due to implicit sharing (the backend may hold on to the
9918 // QRhiBufferData until frame no. current+FramesInFlight-1, but
9919 // implementations may vary), combined with the desire to reuse container
9920 // and QRhiBufferData allocations in bufferOps instead of flooding every
9921 // frame with allocs. See free(). In typical Qt Quick scenes this leads to
9922 // eventually seeding all 4 (or more) resource batches with buffer operation
9923 // data allocations which may (*) then be reused in subsequent frames. This
9924 // comes at the expense of using more memory, but has proven good results
9925 // when (CPU) profiling typical Quick/Quick3D apps.
9926 //
9927 // (*) Due to implicit sharing(ish), the exact behavior is unpredictable. If
9928 // a backend holds on to the QRhiBufferData for, e.g., a dynamic buffer
9929 // update, and then there is a new assign() for that same QRhiBufferData
9930 // while the refcount is still 2, it will "detach" (without contents) and
9931 // there is no reuse of the alloc. This is mitigated by the 'choose the one
9932 // afer the last picked one' logic when handing out batches.
9933
9934 auto nextFreeBatch = [this]() -> QRhiResourceUpdateBatch * {
9935 auto isFree = [this](int i) -> QRhiResourceUpdateBatch * {
9936 const quint64 mask = 1ULL << quint64(i);
9937 if (!(d->resUpdPoolMap & mask)) {
9938 d->resUpdPoolMap |= mask;
9939 QRhiResourceUpdateBatch *u = d->resUpdPool[i];
9940 QRhiResourceUpdateBatchPrivate::get(u)->poolIndex = i;
9941 d->lastResUpdIdx = i;
9942 return u;
9943 }
9944 return nullptr;
9945 };
9946 const int poolSize = d->resUpdPool.size();
9947 for (int i = d->lastResUpdIdx + 1; i < poolSize; ++i) {
9948 if (QRhiResourceUpdateBatch *u = isFree(i))
9949 return u;
9950 }
9951 for (int i = 0; i <= d->lastResUpdIdx; ++i) {
9952 if (QRhiResourceUpdateBatch *u = isFree(i))
9953 return u;
9954 }
9955 return nullptr;
9956 };
9957
9958 QRhiResourceUpdateBatch *u = nextFreeBatch();
9959 if (!u) {
9960 const int oldSize = d->resUpdPool.size();
9961 // 4, 8, 12, ..., up to 64
9962 const int newSize = oldSize + qMin(4, qMax(0, 64 - oldSize));
9963 d->resUpdPool.resize(newSize);
9964 for (int i = oldSize; i < newSize; ++i)
9965 d->resUpdPool[i] = new QRhiResourceUpdateBatch(d);
9966 u = nextFreeBatch();
9967 if (!u)
9968 qWarning("Resource update batch pool exhausted (max is 64)");
9969 }
9970
9971 return u;
9972}
9973
9975{
9976 Q_ASSERT(poolIndex >= 0 && rhi->resUpdPool[poolIndex] == q);
9977
9978 quint32 bufferDataTotal = 0;
9979 quint32 bufferLargeAllocTotal = 0;
9980 for (const BufferOp &op : std::as_const(bufferOps)) {
9981 bufferDataTotal += op.data.size();
9982 bufferLargeAllocTotal += op.data.largeAlloc(); // alloc when > 1 KB
9983 }
9984
9985 if (QRHI_LOG_RUB().isDebugEnabled()) {
9986 qDebug() << "[rub] release to pool upd.batch #" << poolIndex
9987 << "/ bufferOps active" << activeBufferOpCount
9988 << "of" << bufferOps.count()
9989 << "data" << bufferDataTotal
9990 << "largeAlloc" << bufferLargeAllocTotal
9991 << "textureOps active" << activeTextureOpCount
9992 << "of" << textureOps.count();
9993 }
9994
9997
9998 const quint64 mask = 1ULL << quint64(poolIndex);
9999 rhi->resUpdPoolMap &= ~mask;
10000 poolIndex = -1;
10001
10002 // textureOps is cleared, to not keep the potentially large image pixel
10003 // data alive, but it is expected that the container keeps the list alloc
10004 // at least. Only trimOpList() goes for the more aggressive route with squeeze.
10005 textureOps.clear();
10006
10007 // bufferOps is not touched in many cases, to allow reusing allocations
10008 // (incl. in the elements' QRhiBufferData) as much as possible when this
10009 // batch is used again in the future, which is important for performance, in
10010 // particular with Qt Quick where it is easy for scenes to produce lots of,
10011 // typically small buffer changes on every frame.
10012 //
10013 // However, ensure that even in the unlikely case of having the max number
10014 // of batches (64) created in resUpdPool, no more than 64 MB in total is
10015 // used up by buffer data just to help future reuse. For simplicity, if
10016 // there is more than 1 MB data -> clear. Applications with frequent, huge
10017 // buffer updates probably have other bottlenecks anyway.
10018 if (bufferLargeAllocTotal > 1024 * 1024)
10019 bufferOps.clear();
10020}
10021
10023{
10024 int combinedSize = activeBufferOpCount + other->activeBufferOpCount;
10025 if (bufferOps.size() < combinedSize)
10026 bufferOps.resize(combinedSize);
10027 for (int i = activeBufferOpCount; i < combinedSize; ++i)
10028 bufferOps[i] = std::move(other->bufferOps[i - activeBufferOpCount]);
10030
10031 combinedSize = activeTextureOpCount + other->activeTextureOpCount;
10032 if (textureOps.size() < combinedSize)
10033 textureOps.resize(combinedSize);
10034 for (int i = activeTextureOpCount; i < combinedSize; ++i)
10035 textureOps[i] = std::move(other->textureOps[i - activeTextureOpCount]);
10037}
10038
10044
10046{
10047 // Unlike free(), this is expected to aggressively deallocate all memory
10048 // used by both the buffer and texture operation lists. (i.e. using
10049 // squeeze() to only keep the stack prealloc of the QVLAs)
10050 //
10051 // This (e.g. just the destruction of bufferOps elements) may have a
10052 // non-negligible performance impact e.g. with Qt Quick with scenes where
10053 // there are lots of buffer operations per frame.
10054
10056 bufferOps.clear();
10057 bufferOps.squeeze();
10058
10060 textureOps.clear();
10061 textureOps.squeeze();
10062}
10063
10064/*!
10065 Sometimes committing resource updates is necessary or just more convenient
10066 without starting a render pass. Calling this function with \a
10067 resourceUpdates is an alternative to passing \a resourceUpdates to a
10068 beginPass() call (or endPass(), which would be typical in case of readbacks).
10069
10070 \note Cannot be called inside a pass.
10071 */
10072void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
10073{
10074 if (resourceUpdates)
10075 m_rhi->resourceUpdate(this, resourceUpdates);
10076}
10077
10078/*!
10079 Records starting a new render pass targeting the render target \a rt.
10080
10081 \a resourceUpdates, when not null, specifies a resource update batch that
10082 is to be committed and then released.
10083
10084 The color and depth/stencil buffers of the render target are normally
10085 cleared. The clear values are specified in \a colorClearValue and \a
10086 depthStencilClearValue. The exception is when the render target was created
10087 with QRhiTextureRenderTarget::PreserveColorContents and/or
10088 QRhiTextureRenderTarget::PreserveDepthStencilContents. The clear values are
10089 ignored then.
10090
10091 \note Enabling preserved color or depth contents leads to decreased
10092 performance depending on the underlying hardware. Mobile GPUs with tiled
10093 architecture benefit from not having to reload the previous contents into
10094 the tile buffer. Similarly, a QRhiTextureRenderTarget with a QRhiTexture as
10095 the depth buffer is less efficient than a QRhiRenderBuffer since using a
10096 depth texture triggers requiring writing the data out to it, while with
10097 renderbuffers this is not needed (as the API does not allow sampling or
10098 reading from a renderbuffer).
10099
10100 \note Do not assume that any state or resource bindings persist between
10101 passes.
10102
10103 \note The QRhiCommandBuffer's \c set and \c draw functions can only be
10104 called inside a pass. Also, with the exception of setGraphicsPipeline(),
10105 they expect to have a pipeline set already on the command buffer.
10106 Unspecified issues may arise otherwise, depending on the backend.
10107
10108 If \a rt is a QRhiTextureRenderTarget, beginPass() performs a check to see
10109 if the texture and renderbuffer objects referenced from the render target
10110 are up-to-date. This is similar to what setShaderResources() does for
10111 QRhiShaderResourceBindings. If any of the attachments had been rebuilt
10112 since QRhiTextureRenderTarget::create(), an implicit call to create() is
10113 made on \a rt. Therefore, if \a rt has a QRhiTexture color attachment \c
10114 texture, and one needs to make the texture a different size, the following
10115 is then valid:
10116 \code
10117 QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ { texture } });
10118 rt->create();
10119 // ...
10120 texture->setPixelSize(new_size);
10121 texture->create();
10122 cb->beginPass(rt, colorClear, dsClear); // this is ok, no explicit rt->create() is required before
10123 \endcode
10124
10125 \a flags allow controlling certain advanced functionality. One commonly used
10126 flag is \c ExternalContents. This should be specified whenever
10127 beginExternal() will be called within the pass started by this function.
10128
10129 \sa endPass(), BeginPassFlags
10130 */
10131void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
10132 const QColor &colorClearValue,
10133 const QRhiDepthStencilClearValue &depthStencilClearValue,
10134 QRhiResourceUpdateBatch *resourceUpdates,
10135 BeginPassFlags flags)
10136{
10137 m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates, flags);
10138}
10139
10140/*!
10141 Records ending the current render pass.
10142
10143 \a resourceUpdates, when not null, specifies a resource update batch that
10144 is to be committed and then released.
10145
10146 \sa beginPass()
10147 */
10148void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates)
10149{
10150 m_rhi->endPass(this, resourceUpdates);
10151}
10152
10153/*!
10154 Records setting a new graphics pipeline \a ps.
10155
10156 \note This function must be called before recording other \c set or \c draw
10157 commands on the command buffer.
10158
10159 \note QRhi will optimize out unnecessary invocations within a pass, so
10160 therefore overoptimizing to avoid calls to this function is not necessary
10161 on the applications' side.
10162
10163 \note This function can only be called inside a render pass, meaning
10164 between a beginPass() and endPass() call.
10165
10166 \note The new graphics pipeline \a ps must be a valid pointer.
10167 */
10168void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)
10169{
10170 Q_ASSERT(ps != nullptr);
10171 m_rhi->setGraphicsPipeline(this, ps);
10172}
10173
10174/*!
10175 Records binding a set of shader resources, such as, uniform buffers or
10176 textures, that are made visible to one or more shader stages.
10177
10178 \a srb can be null in which case the current graphics or compute pipeline's
10179 associated QRhiShaderResourceBindings is used. When \a srb is non-null, it
10180 must be
10181 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible},
10182 meaning the layout (number of bindings, the type and binding number of each
10183 binding) must fully match the QRhiShaderResourceBindings that was
10184 associated with the pipeline at the time of calling the pipeline's create().
10185
10186 There are cases when a seemingly unnecessary setShaderResources() call is
10187 mandatory: when rebuilding a resource referenced from \a srb, for example
10188 changing the size of a QRhiBuffer followed by a QRhiBuffer::create(), this
10189 is the place where associated native objects (such as descriptor sets in
10190 case of Vulkan) are updated to refer to the current native resources that
10191 back the QRhiBuffer, QRhiTexture, QRhiSampler objects referenced from \a
10192 srb. In this case setShaderResources() must be called even if \a srb is
10193 the same as in the last call.
10194
10195 When \a srb is not null, the QRhiShaderResourceBindings object the pipeline
10196 was built with in create() is guaranteed to be not accessed in any form. In
10197 fact, it does not need to be valid even at this point: destroying the
10198 pipeline's associated srb after create() and instead explicitly specifying
10199 another, \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout
10200 compatible} one in every setShaderResources() call is valid.
10201
10202 \a dynamicOffsets allows specifying buffer offsets for uniform buffers that
10203 were associated with \a srb via
10204 QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(). This is
10205 different from providing the offset in the \a srb itself: dynamic offsets
10206 do not require building a new QRhiShaderResourceBindings for every
10207 different offset, can avoid writing the underlying descriptors (with
10208 backends where applicable), and so they may be more efficient. Each element
10209 of \a dynamicOffsets is a \c binding - \c offset pair.
10210 \a dynamicOffsetCount specifies the number of elements in \a dynamicOffsets.
10211
10212 \note All offsets in \a dynamicOffsets must be byte aligned to the value
10213 returned from QRhi::ubufAlignment().
10214
10215 \note Some backends may limit the number of supported dynamic offsets.
10216 Avoid using a \a dynamicOffsetCount larger than 8.
10217
10218 \note QRhi will optimize out unnecessary invocations within a pass (taking
10219 the conditions described above into account), so therefore overoptimizing
10220 to avoid calls to this function is not necessary on the applications' side.
10221
10222 \note This function can only be called inside a render or compute pass,
10223 meaning between a beginPass() and endPass(), or beginComputePass() and
10224 endComputePass().
10225 */
10226void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb,
10227 int dynamicOffsetCount,
10228 const DynamicOffset *dynamicOffsets)
10229{
10230 m_rhi->setShaderResources(this, srb, dynamicOffsetCount, dynamicOffsets);
10231}
10232
10233/*!
10234 Records vertex input bindings.
10235
10236 The index buffer used by subsequent drawIndexed() commands is specified by
10237 \a indexBuf, \a indexOffset, and \a indexFormat. \a indexBuf can be set to
10238 null when indexed drawing is not needed.
10239
10240 Vertex buffer bindings are batched. \a startBinding specifies the first
10241 binding number. The recorded command then binds each buffer from \a
10242 bindings to the binding point \c{startBinding + i} where \c i is the index
10243 in \a bindings. Each element in \a bindings specifies a QRhiBuffer and an
10244 offset.
10245
10246 \note Some backends may limit the number of vertex buffer bindings. Avoid
10247 using a \a bindingCount larger than 8.
10248
10249 Superfluous vertex input and index changes in the same pass are ignored
10250 automatically with most backends and therefore applications do not need to
10251 overoptimize to avoid calls to this function.
10252
10253 \note This function can only be called inside a render pass, meaning
10254 between a beginPass() and endPass() call.
10255
10256 As a simple example, take a vertex shader with two inputs:
10257
10258 \badcode
10259 layout(location = 0) in vec4 position;
10260 layout(location = 1) in vec3 color;
10261 \endcode
10262
10263 and assume we have the data available in interleaved format, using only 2
10264 floats for position (so 5 floats per vertex: x, y, r, g, b). A QRhiGraphicsPipeline for
10265 this shader can then be created using the input layout:
10266
10267 \code
10268 QRhiVertexInputLayout inputLayout;
10269 inputLayout.setBindings({
10270 { 5 * sizeof(float) }
10271 });
10272 inputLayout.setAttributes({
10273 { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
10274 { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
10275 });
10276 \endcode
10277
10278 Here there is one buffer binding (binding number 0), with two inputs
10279 referencing it. When recording the pass, once the pipeline is set, the
10280 vertex bindings can be specified simply like the following, assuming vbuf
10281 is the QRhiBuffer with all the interleaved position+color data:
10282
10283 \code
10284 const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
10285 cb->setVertexInput(0, 1, &vbufBinding);
10286 \endcode
10287 */
10288void QRhiCommandBuffer::setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
10289 QRhiBuffer *indexBuf, quint32 indexOffset,
10290 IndexFormat indexFormat)
10291{
10292 m_rhi->setVertexInput(this, startBinding, bindingCount, bindings, indexBuf, indexOffset, indexFormat);
10293}
10294
10295/*!
10296 Records setting the active viewport rectangle specified in \a viewport.
10297
10298 With backends where the underlying graphics API has scissoring always
10299 enabled, this function also sets the scissor to match the viewport whenever
10300 the active QRhiGraphicsPipeline does not have
10301 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set.
10302
10303 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
10304 bottom-left.
10305
10306 \note This function can only be called inside a render pass, meaning
10307 between a beginPass() and endPass() call.
10308 */
10309void QRhiCommandBuffer::setViewport(const QRhiViewport &viewport)
10310{
10311 m_rhi->setViewport(this, viewport);
10312}
10313
10314/*!
10315 Records setting the active scissor rectangle specified in \a scissor.
10316
10317 This can only be called when the bound pipeline has
10318 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set. When the flag is
10319 set on the active pipeline, this function must be called because scissor
10320 testing will get enabled and so a scissor rectangle must be provided.
10321
10322 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
10323 bottom-left.
10324
10325 \note This function can only be called inside a render pass, meaning
10326 between a beginPass() and endPass() call.
10327 */
10328void QRhiCommandBuffer::setScissor(const QRhiScissor &scissor)
10329{
10330 m_rhi->setScissor(this, scissor);
10331}
10332
10333/*!
10334 Records setting the active blend constants to \a c.
10335
10336 This can only be called when the bound pipeline has
10337 QRhiGraphicsPipeline::UsesBlendConstants set.
10338
10339 \note This function can only be called inside a render pass, meaning
10340 between a beginPass() and endPass() call.
10341 */
10342void QRhiCommandBuffer::setBlendConstants(const QColor &c)
10343{
10344 m_rhi->setBlendConstants(this, c);
10345}
10346
10347/*!
10348 Records setting the active stencil reference value to \a refValue.
10349
10350 This can only be called when the bound pipeline has
10351 QRhiGraphicsPipeline::UsesStencilRef set.
10352
10353 \note This function can only be called inside a render pass, meaning between
10354 a beginPass() and endPass() call.
10355 */
10356void QRhiCommandBuffer::setStencilRef(quint32 refValue)
10357{
10358 m_rhi->setStencilRef(this, refValue);
10359}
10360
10361/*!
10362 Sets the shading rate for the following draw calls to \a coarsePixelSize.
10363
10364 The default is 1x1.
10365
10366 Functional only when the \l QRhi::VariableRateShading feature is reported as
10367 supported and the QRhiGraphicsPipeline(s) bound on the command buffer were
10368 declaring \l QRhiGraphicsPipeline::UsesShadingRate when creating them.
10369
10370 Call \l QRhi::supportedShadingRates() to check what shading rates are
10371 supported for a given sample count.
10372
10373 When both a QRhiShadingRateMap and this function is in use, the higher of
10374 two the shading rates are used for each tile. There is currently no control
10375 offered over the combiner behavior.
10376
10377 \since 6.9
10378 */
10379void QRhiCommandBuffer::setShadingRate(const QSize &coarsePixelSize)
10380{
10381 m_rhi->setShadingRate(this, coarsePixelSize);
10382}
10383
10384/*!
10385 Records a non-indexed draw.
10386
10387 The number of vertices is specified in \a vertexCount. For instanced
10388 drawing set \a instanceCount to a value other than 1. \a firstVertex is the
10389 index of the first vertex to draw. When drawing multiple instances, the
10390 first instance ID is specified by \a firstInstance.
10391
10392 \note \a firstInstance may not be supported, and is ignored when the
10393 QRhi::BaseInstance feature is reported as not supported. The first instance
10394 ID is always 0 in that case. QRhi::BaseInstance is never supported with
10395 OpenGL at the moment, mainly due to OpenGL ES limitations, and therefore
10396 portable applications should not be designed to rely on this argument.
10397
10398 \note Shaders that need to access the index of the current vertex or
10399 instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
10400 Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
10401 gl_InstanceID.
10402
10403 \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
10404 include the base value with some of the underlying 3D APIs. This is
10405 indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
10406 on a base instance value cannot be avoided, applications are advised to pass
10407 in the value as a uniform conditionally based on what that feature reports,
10408 and add it to \c gl_InstanceIndex in the shader.
10409
10410 \note This function can only be called inside a render pass, meaning
10411 between a beginPass() and endPass() call.
10412 */
10413void QRhiCommandBuffer::draw(quint32 vertexCount,
10414 quint32 instanceCount,
10415 quint32 firstVertex,
10416 quint32 firstInstance)
10417{
10418 m_rhi->draw(this, vertexCount, instanceCount, firstVertex, firstInstance);
10419}
10420
10421/*!
10422 Records an indexed draw.
10423
10424 The number of vertices is specified in \a indexCount. \a firstIndex is the
10425 base index. The effective offset in the index buffer is given by
10426 \c{indexOffset + firstIndex * n} where \c n is 2 or 4 depending on the
10427 index element type. \c indexOffset is specified in setVertexInput().
10428
10429 \note The effective offset in the index buffer must be 4 byte aligned with
10430 some backends (for example, Metal). With these backends the
10431 \l{QRhi::NonFourAlignedEffectiveIndexBufferOffset}{NonFourAlignedEffectiveIndexBufferOffset}
10432 feature will be reported as not-supported.
10433
10434 \a vertexOffset (also called \c{base vertex}) is a signed value that is
10435 added to the element index before indexing into the vertex buffer. Support
10436 for this is not always available, and the value is ignored when the feature
10437 QRhi::BaseVertex is reported as unsupported.
10438
10439 For instanced drawing set \a instanceCount to a value other than 1. When
10440 drawing multiple instances, the first instance ID is specified by \a
10441 firstInstance.
10442
10443 \note \a firstInstance may not be supported, and is ignored when the
10444 QRhi::BaseInstance feature is reported as not supported. The first instance
10445 ID is always 0 in that case. QRhi::BaseInstance is never supported with
10446 OpenGL at the moment, mainly due to OpenGL ES limitations, and therefore
10447 portable applications should not be designed to rely on this argument.
10448
10449 \note Shaders that need to access the index of the current vertex or
10450 instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
10451 Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
10452 gl_InstanceID.
10453
10454 \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
10455 include the base value with some of the underlying 3D APIs. This is
10456 indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
10457 on a base instance value cannot be avoided, applications are advised to pass
10458 in the value as a uniform conditionally based on what that feature reports,
10459 and add it to \c gl_InstanceIndex in the shader.
10460
10461 \note This function can only be called inside a render pass, meaning
10462 between a beginPass() and endPass() call.
10463 */
10464void QRhiCommandBuffer::drawIndexed(quint32 indexCount,
10465 quint32 instanceCount,
10466 quint32 firstIndex,
10467 qint32 vertexOffset,
10468 quint32 firstInstance)
10469{
10470 m_rhi->drawIndexed(this, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
10471}
10472
10473/*!
10474 Records a named debug group on the command buffer with the specified \a
10475 name. This is shown in graphics debugging tools such as
10476 \l{https://renderdoc.org/}{RenderDoc} and
10477 \l{https://developer.apple.com/xcode/}{XCode}. The end of the grouping is
10478 indicated by debugMarkEnd().
10479
10480 \note Ignored when QRhi::DebugMarkers are not supported or
10481 QRhi::EnableDebugMarkers is not set.
10482
10483 \note Can be called anywhere within the frame, both inside and outside of passes.
10484 */
10485void QRhiCommandBuffer::debugMarkBegin(const QByteArray &name)
10486{
10487 m_rhi->debugMarkBegin(this, name);
10488}
10489
10490/*!
10491 Records the end of a debug group.
10492
10493 \note Ignored when QRhi::DebugMarkers are not supported or
10494 QRhi::EnableDebugMarkers is not set.
10495
10496 \note Can be called anywhere within the frame, both inside and outside of passes.
10497 */
10498void QRhiCommandBuffer::debugMarkEnd()
10499{
10500 m_rhi->debugMarkEnd(this);
10501}
10502
10503/*!
10504 Inserts a debug message \a msg into the command stream.
10505
10506 \note Ignored when QRhi::DebugMarkers are not supported or
10507 QRhi::EnableDebugMarkers is not set.
10508
10509 \note With some backends debugMarkMsg() is only supported inside a pass and
10510 is ignored when called outside a pass. With others it is recorded anywhere
10511 within the frame.
10512 */
10513void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)
10514{
10515 m_rhi->debugMarkMsg(this, msg);
10516}
10517
10518/*!
10519 Records starting a new compute pass.
10520
10521 \a resourceUpdates, when not null, specifies a resource update batch that
10522 is to be committed and then released.
10523
10524 \note Do not assume that any state or resource bindings persist between
10525 passes.
10526
10527 \note A compute pass can record setComputePipeline(), setShaderResources(),
10528 and dispatch() calls, not graphics ones. General functionality, such as,
10529 debug markers and beginExternal() is available both in render and compute
10530 passes.
10531
10532 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
10533 is reported as supported.
10534
10535 \a flags is not currently used.
10536 */
10537void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates, BeginPassFlags flags)
10538{
10539 m_rhi->beginComputePass(this, resourceUpdates, flags);
10540}
10541
10542/*!
10543 Records ending the current compute pass.
10544
10545 \a resourceUpdates, when not null, specifies a resource update batch that
10546 is to be committed and then released.
10547 */
10548void QRhiCommandBuffer::endComputePass(QRhiResourceUpdateBatch *resourceUpdates)
10549{
10550 m_rhi->endComputePass(this, resourceUpdates);
10551}
10552
10553/*!
10554 Records setting a new compute pipeline \a ps.
10555
10556 \note This function must be called before recording setShaderResources() or
10557 dispatch() commands on the command buffer.
10558
10559 \note QRhi will optimize out unnecessary invocations within a pass, so
10560 therefore overoptimizing to avoid calls to this function is not necessary
10561 on the applications' side.
10562
10563 \note This function can only be called inside a compute pass, meaning
10564 between a beginComputePass() and endComputePass() call.
10565 */
10566void QRhiCommandBuffer::setComputePipeline(QRhiComputePipeline *ps)
10567{
10568 m_rhi->setComputePipeline(this, ps);
10569}
10570
10571/*!
10572 Records dispatching compute work items, with \a x, \a y, and \a z
10573 specifying the number of local workgroups in the corresponding dimension.
10574
10575 \note This function can only be called inside a compute pass, meaning
10576 between a beginComputePass() and endComputePass() call.
10577
10578 \note \a x, \a y, and \a z must fit the limits from the underlying graphics
10579 API implementation at run time. The maximum values are typically 65535.
10580
10581 \note Watch out for possible limits on the local workgroup size as well.
10582 This is specified in the shader, for example: \c{layout(local_size_x = 16,
10583 local_size_y = 16) in;}. For example, with OpenGL the minimum value mandated
10584 by the specification for the number of invocations in a single local work
10585 group (the product of \c local_size_x, \c local_size_y, and \c local_size_z)
10586 is 1024, while with OpenGL ES (3.1) the value may be as low as 128. This
10587 means that the example given above may be rejected by some OpenGL ES
10588 implementations as the number of invocations is 256.
10589 */
10590void QRhiCommandBuffer::dispatch(int x, int y, int z)
10591{
10592 m_rhi->dispatch(this, x, y, z);
10593}
10594
10595/*!
10596 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
10597 QRhiVulkanCommandBufferNativeHandles. The returned value is \nullptr when
10598 exposing the underlying native resources is not supported by, or not
10599 applicable to, the backend.
10600
10601 \sa QRhiVulkanCommandBufferNativeHandles,
10602 QRhiMetalCommandBufferNativeHandles, beginExternal(), endExternal()
10603 */
10604const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
10605{
10606 return m_rhi->nativeHandles(this);
10607}
10608
10609/*!
10610 To be called when the application before the application is about to
10611 enqueue commands to the current pass' command buffer by calling graphics
10612 API functions directly.
10613
10614 \note This is only available when the intent was declared upfront in
10615 beginPass() or beginComputePass(). Therefore this function must only be
10616 called when the pass recording was started with specifying
10617 QRhiCommandBuffer::ExternalContent.
10618
10619 With Vulkan, Metal, or Direct3D 12 one can query the native command buffer
10620 or encoder objects via nativeHandles() and enqueue commands to them. With
10621 OpenGL or Direct3D 11 the (device) context can be retrieved from
10622 QRhi::nativeHandles(). However, this must never be done without ensuring
10623 the QRhiCommandBuffer's state stays up-to-date. Hence the requirement for
10624 wrapping any externally added command recording between beginExternal() and
10625 endExternal(). Conceptually this is the same as QPainter's
10626 \l{QPainter::beginNativePainting()}{beginNativePainting()} and
10627 \l{QPainter::endNativePainting()}{endNativePainting()} functions.
10628
10629 For OpenGL in particular, this function has an additional task: it makes
10630 sure the context is made current on the current thread.
10631
10632 \note Once beginExternal() is called, no other render pass specific
10633 functions (\c set* or \c draw*) must be called on the
10634 QRhiCommandBuffer until endExternal().
10635
10636 \warning Some backends may return a native command buffer object from
10637 QRhiCommandBuffer::nativeHandles() that is different from the primary one
10638 when inside a beginExternal() - endExternal() block. Therefore it is
10639 important to (re)query the native command buffer object after calling
10640 beginExternal(). In practical terms this means that with Vulkan for example
10641 the externally recorded Vulkan commands are placed onto a secondary command
10642 buffer (with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT).
10643 nativeHandles() returns this secondary command buffer when called between
10644 begin/endExternal.
10645
10646 \sa endExternal(), nativeHandles()
10647 */
10648void QRhiCommandBuffer::beginExternal()
10649{
10650 m_rhi->beginExternal(this);
10651}
10652
10653/*!
10654 To be called once the externally added commands are recorded to the command
10655 buffer or context.
10656
10657 \note All QRhiCommandBuffer state must be assumed as invalid after calling
10658 this function. Pipelines, vertex and index buffers, and other state must be
10659 set again if more draw calls are recorded after the external commands.
10660
10661 \sa beginExternal(), nativeHandles()
10662 */
10663void QRhiCommandBuffer::endExternal()
10664{
10665 m_rhi->endExternal(this);
10666}
10667
10668/*!
10669 \return the last available timestamp, in seconds, when
10670 \l QRhi::EnableTimestamps was enabled when creating the QRhi. The value
10671 indicates the elapsed time on the GPU during the last completed frame.
10672
10673 \note Do not expect results other than 0 when the QRhi::Timestamps feature
10674 is not reported as supported, or when QRhi::EnableTimestamps was not passed
10675 to QRhi::create(). There are exceptions to this, because with some graphics
10676 APIs (Metal) timings are available without having to perform extra
10677 operations (timestamp queries), but portable applications should always
10678 consciously opt-in to timestamp collection when they know it is needed, and
10679 call this function accordingly.
10680
10681 Care must be exercised with the interpretation of the value, as its
10682 precision and granularity is often not controlled by Qt, and depends on the
10683 underlying graphics API and its implementation. In particular, comparing
10684 the values between different graphics APIs and hardware is discouraged and
10685 may be meaningless.
10686
10687 When the frame was recorded with \l{QRhi::beginFrame()}{beginFrame()} and
10688 \l{QRhi::endFrame()}{endFrame()}, i.e., with a swapchain, the timing values
10689 will likely become available asynchronously. The returned value may
10690 therefore be 0 (e.g., for the first 1-2 frames) or the last known value
10691 referring to some previous frame. The value my also
10692 become 0 again under certain conditions, such as when resizing the window.
10693 It can be expected that the most up-to-date available value is retrieved in
10694 beginFrame() and becomes queriable via this function once beginFrame()
10695 returns.
10696
10697 \note Do not assume that the value refers to the previous
10698 (\c{currently_recorded - 1}) frame. It may refer to \c{currently_recorded -
10699 2} or \c{currently_recorded - 3} as well. The exact behavior may depend on
10700 the graphics API and its implementation.
10701
10702 On the other hand, with offscreen frames the returned value is up-to-date
10703 once \l{QRhi::endOffscreenFrame()}{endOffscreenFrame()} returns, because
10704 offscreen frames reduce GPU pipelining and wait the the commands to be
10705 complete.
10706
10707 \note This means that, unlike with swapchain frames, with offscreen frames
10708 the returned value is guaranteed to refer to the frame that has just been
10709 submitted and completed. (assuming this function is called after
10710 endOffscreenFrame() but before the next beginOffscreenFrame())
10711
10712 Watch out for the consequences of GPU frequency scaling and GPU clock
10713 changes, depending on the platform. For example, on Windows the returned
10714 timing may vary in a quite wide range between frames with modern graphics
10715 cards, even when submitting frames with a similar, or the same workload.
10716 This is out of scope for Qt to control and solve, generally speaking.
10717 However, the D3D12 backend automatically calls
10718 \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-setstablepowerstate}{ID3D12Device::SetStablePowerState()}
10719 whenever the environment variable \c QT_D3D_STABLE_POWER_STATE is set to a
10720 non-zero value. This can greatly stabilize the result. It can also have a
10721 non-insignificant effect on the CPU-side timings measured via QElapsedTimer
10722 for example, especially when offscreen frames are involved.
10723
10724 \note Do not and never ship applications to production with
10725 \c QT_D3D_STABLE_POWER_STATE set. See the Windows API documentation for details.
10726
10727 \sa QRhi::Timestamps, QRhi::EnableTimestamps
10728 */
10729double QRhiCommandBuffer::lastCompletedGpuTime()
10730{
10731 return m_rhi->lastCompletedGpuTime(this);
10732}
10733
10734/*!
10735 \return the value (typically an offset) \a v aligned to the uniform buffer
10736 alignment given by by ubufAlignment().
10737 */
10738int QRhi::ubufAligned(int v) const
10739{
10740 const int byteAlign = ubufAlignment();
10741 return (v + byteAlign - 1) & ~(byteAlign - 1);
10742}
10743
10744/*!
10745 \return the number of mip levels for a given \a size.
10746 */
10747int QRhi::mipLevelsForSize(const QSize &size)
10748{
10749 return qFloor(std::log2(qMax(size.width(), size.height()))) + 1;
10750}
10751
10752/*!
10753 \return the texture image size for a given \a mipLevel, calculated based on
10754 the level 0 size given in \a baseLevelSize.
10755 */
10756QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)
10757{
10758 const int w = qMax(1, baseLevelSize.width() >> mipLevel);
10759 const int h = qMax(1, baseLevelSize.height() >> mipLevel);
10760 return QSize(w, h);
10761}
10762
10763/*!
10764 \return \c true if the underlying graphics API has the Y axis pointing up
10765 in framebuffers and images.
10766
10767 In practice this is \c true for OpenGL only.
10768 */
10769bool QRhi::isYUpInFramebuffer() const
10770{
10771 return d->isYUpInFramebuffer();
10772}
10773
10774/*!
10775 \return \c true if the underlying graphics API has the Y axis pointing up
10776 in its normalized device coordinate system.
10777
10778 In practice this is \c false for Vulkan only.
10779
10780 \note clipSpaceCorrMatrix() includes the corresponding adjustment (to make
10781 Y point up) in its returned matrix.
10782 */
10783bool QRhi::isYUpInNDC() const
10784{
10785 return d->isYUpInNDC();
10786}
10787
10788/*!
10789 \return \c true if the underlying graphics API uses depth range [0, 1] in
10790 clip space.
10791
10792 In practice this is \c false for OpenGL only, because OpenGL uses a
10793 post-projection depth range of [-1, 1]. (not to be confused with the
10794 NDC-to-window mapping controlled by glDepthRange(), which uses a range of
10795 [0, 1], unless overridden by the QRhiViewport) In some OpenGL versions
10796 glClipControl() could be used to change this, but the OpenGL backend of
10797 QRhi does not use that function as it is not available in OpenGL ES or
10798 OpenGL versions lower than 4.5.
10799
10800 \note clipSpaceCorrMatrix() includes the corresponding adjustment in its
10801 returned matrix. Therefore, many users of QRhi do not need to take any
10802 further measures apart from pre-multiplying their projection matrices with
10803 clipSpaceCorrMatrix(). However, some graphics techniques, such as, some
10804 types of shadow mapping, involve working with and outputting depth values
10805 in the shaders. These will need to query and take the value of this
10806 function into account as appropriate.
10807 */
10808bool QRhi::isClipDepthZeroToOne() const
10809{
10810 return d->isClipDepthZeroToOne();
10811}
10812
10813/*!
10814 \return a matrix that can be used to allow applications keep using
10815 OpenGL-targeted vertex data and perspective projection matrices (such as,
10816 the ones generated by QMatrix4x4::perspective()), regardless of the active
10817 QRhi backend.
10818
10819 In a typical renderer, once \c{this_matrix * mvp} is used instead of just
10820 \c mvp, vertex data with Y up and viewports with depth range 0 - 1 can be
10821 used without considering what backend (and so graphics API) is going to be
10822 used at run time. This way branching based on isYUpInNDC() and
10823 isClipDepthZeroToOne() can be avoided (although such logic may still become
10824 required when implementing certain advanced graphics techniques).
10825
10826 See
10827 \l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this
10828 page} for a discussion of the topic from Vulkan perspective.
10829 */
10830QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
10831{
10832 return d->clipSpaceCorrMatrix();
10833}
10834
10835/*!
10836 \return \c true if the specified texture \a format modified by \a flags is
10837 supported.
10838
10839 The query is supported both for uncompressed and compressed formats.
10840 */
10841bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
10842{
10843 return d->isTextureFormatSupported(format, flags);
10844}
10845
10846/*!
10847 \return \c true if the specified \a feature is supported
10848 */
10849bool QRhi::isFeatureSupported(QRhi::Feature feature) const
10850{
10851 return d->isFeatureSupported(feature);
10852}
10853
10854/*!
10855 \return the value for the specified resource \a limit.
10856
10857 The values are expected to be queried by the backends upon initialization,
10858 meaning calling this function is a light operation.
10859 */
10860int QRhi::resourceLimit(ResourceLimit limit) const
10861{
10862 return d->resourceLimit(limit);
10863}
10864
10865/*!
10866 \return a pointer to the backend-specific collection of native objects
10867 for the device, context, and similar concepts used by the backend.
10868
10869 Cast to QRhiVulkanNativeHandles, QRhiD3D11NativeHandles,
10870 QRhiD3D12NativeHandles, QRhiGles2NativeHandles, or QRhiMetalNativeHandles
10871 as appropriate.
10872
10873 \note No ownership is transferred, neither for the returned pointer nor for
10874 any native objects.
10875 */
10876const QRhiNativeHandles *QRhi::nativeHandles()
10877{
10878 return d->nativeHandles();
10879}
10880
10881/*!
10882 With OpenGL this makes the OpenGL context current on the current thread.
10883 The function has no effect with other backends.
10884
10885 Calling this function is relevant typically in Qt framework code, when one
10886 has to ensure external OpenGL code provided by the application can still
10887 run like it did before with direct usage of OpenGL, as long as the QRhi is
10888 using the OpenGL backend.
10889
10890 \return false when failed, similarly to QOpenGLContext::makeCurrent(). When
10891 the operation failed, isDeviceLost() can be called to determine if there
10892 was a loss of context situation. Such a check is equivalent to checking via
10893 QOpenGLContext::isValid().
10894
10895 \sa QOpenGLContext::makeCurrent(), QOpenGLContext::isValid()
10896 */
10897bool QRhi::makeThreadLocalNativeContextCurrent()
10898{
10899 return d->makeThreadLocalNativeContextCurrent();
10900}
10901
10902/*!
10903 With backends and graphics APIs where applicable, this function allows to
10904 provide additional arguments to the \b next submission of commands to the
10905 graphics command queue.
10906
10907 In particular, with Vulkan this allows passing in a list of Vulkan semaphore
10908 objects for \c vkQueueSubmit() to signal and wait on. \a params must then be
10909 a \l QRhiVulkanQueueSubmitParams. This becomes essential in certain advanced
10910 use cases, such as when performing native Vulkan calls that involve having
10911 to wait on and signal VkSemaphores that the application's custom Vulkan
10912 rendering or compute code manages. In addition, this also allows specifying
10913 additional semaphores to wait on in the next \c vkQueuePresentKHR().
10914
10915 \note This function affects the next queue submission only, which will
10916 happen in endFrame(), endOffscreenFrame(), or finish(). The enqueuing of
10917 present happens in endFrame().
10918
10919 With many other backends the implementation of this function is a no-op.
10920
10921 \since 6.9
10922 */
10923void QRhi::setQueueSubmitParams(QRhiNativeHandles *params)
10924{
10925 d->setQueueSubmitParams(params);
10926}
10927
10928/*!
10929 Attempts to release resources in the backend's caches. This can include both
10930 CPU and GPU resources. Only memory and resources that can be recreated
10931 automatically are in scope. As an example, if the backend's
10932 QRhiGraphicsPipeline implementation maintains a cache of shader compilation
10933 results, calling this function leads to emptying that cache, thus
10934 potentially freeing up memory and graphics resources.
10935
10936 Calling this function makes sense in resource constrained environments,
10937 where at a certain point there is a need to ensure minimal resource usage,
10938 at the expense of performance.
10939 */
10940void QRhi::releaseCachedResources()
10941{
10942 d->releaseCachedResources();
10943
10944 for (QRhiResourceUpdateBatch *u : d->resUpdPool) {
10945 if (u->d->poolIndex < 0)
10946 u->d->trimOpLists();
10947 }
10948}
10949
10950/*!
10951 \return true if the graphics device was lost.
10952
10953 The loss of the device is typically detected in beginFrame(), endFrame() or
10954 QRhiSwapChain::createOrResize(), depending on the backend and the underlying
10955 native APIs. The most common is endFrame() because that is where presenting
10956 happens. With some backends QRhiSwapChain::createOrResize() can also fail
10957 due to a device loss. Therefore this function is provided as a generic way
10958 to check if a device loss was detected by a previous operation.
10959
10960 When the device is lost, no further operations should be done via the QRhi.
10961 Rather, all QRhi resources should be released, followed by destroying the
10962 QRhi. A new QRhi can then be attempted to be created. If successful, all
10963 graphics resources must be reinitialized. If not, try again later,
10964 repeatedly.
10965
10966 While simple applications may decide to not care about device loss,
10967 on the commonly used desktop platforms a device loss can happen
10968 due to a variety of reasons, including physically disconnecting the
10969 graphics adapter, disabling the device or driver, uninstalling or upgrading
10970 the graphics driver, or due to errors that lead to a graphics device reset.
10971 Some of these can happen under perfectly normal circumstances as well, for
10972 example the upgrade of the graphics driver to a newer version is a common
10973 task that can happen at any time while a Qt application is running. Users
10974 may very well expect applications to be able to survive this, even when the
10975 application is actively using an API like OpenGL or Direct3D.
10976
10977 Qt's own frameworks built on top of QRhi, such as, Qt Quick, can be
10978 expected to handle and take appropriate measures when a device loss occurs.
10979 If the data for graphics resources, such as textures and buffers, are still
10980 available on the CPU side, such an event may not be noticeable on the
10981 application level at all since graphics resources can seamlessly be
10982 reinitialized then. However, applications and libraries working directly
10983 with QRhi are expected to be prepared to check and handle device loss
10984 situations themselves.
10985
10986 \note With OpenGL, applications may need to opt-in to context reset
10987 notifications by setting QSurfaceFormat::ResetNotification on the
10988 QOpenGLContext. This is typically done by enabling the flag in
10989 QRhiGles2InitParams::format. Keep in mind however that some systems may
10990 generate context resets situations even when this flag is not set.
10991 */
10992bool QRhi::isDeviceLost() const
10993{
10994 return d->isDeviceLost();
10995}
10996
10997/*!
10998 \return a binary data blob with data collected from the
10999 QRhiGraphicsPipeline and QRhiComputePipeline successfully created during
11000 the lifetime of this QRhi.
11001
11002 By saving and then, in subsequent runs of the same application, reloading
11003 the cache data, pipeline and shader creation times can potentially be
11004 reduced. What exactly the cache and its serialized version includes is not
11005 specified, is always specific to the backend used, and in some cases also
11006 dependent on the particular implementation of the graphics API.
11007
11008 When the PipelineCacheDataLoadSave is reported as unsupported, the returned
11009 QByteArray is empty.
11010
11011 When the EnablePipelineCacheDataSave flag was not specified when calling
11012 create(), the returned QByteArray may be empty, even when the
11013 PipelineCacheDataLoadSave feature is supported.
11014
11015 When the returned data is non-empty, it is always specific to the Qt
11016 version and QRhi backend. In addition, in some cases there is a strong
11017 dependency to the graphics device and the exact driver version used. QRhi
11018 takes care of adding the appropriate header and safeguards that ensure that
11019 the data can always be passed safely to setPipelineCacheData(), therefore
11020 attempting to load data from a run on another version of a driver will be
11021 handled safely and gracefully.
11022
11023 \note Calling releaseCachedResources() may, depending on the backend, clear
11024 the pipeline data collected. A subsequent call to this function may then
11025 not return any data.
11026
11027 See EnablePipelineCacheDataSave for further details about this feature.
11028
11029 \note Minimize the number of calls to this function. Retrieving the blob is
11030 not always a cheap operation, and therefore this function should only be
11031 called at a low frequency, ideally only once e.g. when closing the
11032 application.
11033
11034 \sa setPipelineCacheData(), create(), isFeatureSupported()
11035 */
11036QByteArray QRhi::pipelineCacheData()
11037{
11038 return d->pipelineCacheData();
11039}
11040
11041/*!
11042 Loads \a data into the pipeline cache, when applicable.
11043
11044 When the PipelineCacheDataLoadSave is reported as unsupported, the function
11045 is safe to call, but has no effect.
11046
11047 The blob returned by pipelineCacheData() is always specific to the Qt
11048 version, the QRhi backend, and, in some cases, also to the graphics device,
11049 and a given version of the graphics driver. QRhi takes care of adding the
11050 appropriate header and safeguards that ensure that the data can always be
11051 passed safely to this function. If there is a mismatch, e.g. because the
11052 driver has been upgraded to a newer version, or because the data was
11053 generated from a different QRhi backend, a warning is printed and \a data
11054 is safely ignored.
11055
11056 With Vulkan, this maps directly to VkPipelineCache. Calling this function
11057 creates a new Vulkan pipeline cache object, with its initial data sourced
11058 from \a data. The pipeline cache object is then used by all subsequently
11059 created QRhiGraphicsPipeline and QRhiComputePipeline objects, thus
11060 accelerating, potentially, the pipeline creation.
11061
11062 With other APIs there is no real pipeline cache, but they may provide a
11063 cache with bytecode from shader compilations (D3D) or program binaries
11064 (OpenGL). In applications that perform a lot of shader compilation from
11065 source at run time this can provide a significant boost in subsequent runs
11066 if the "pipeline cache" is pre-seeded from an earlier run using this
11067 function.
11068
11069 \note QRhi cannot give any guarantees that \a data has an effect on the
11070 pipeline and shader creation performance. With APIs like Vulkan, it is up
11071 to the driver to decide if \a data is used for some purpose, or if it is
11072 ignored.
11073
11074 See EnablePipelineCacheDataSave for further details about this feature.
11075
11076 \note This mechanism offered by QRhi is independent of the drivers' own
11077 internal caching mechanism, if any. This means that, depending on the
11078 graphics API and its implementation, the exact effects of retrieving and
11079 then reloading \a data are not predictable. Improved performance may not be
11080 visible at all in case other caching mechanisms outside of Qt's control are
11081 already active.
11082
11083 \note Minimize the number of calls to this function. Loading the blob is
11084 not always a cheap operation, and therefore this function should only be
11085 called at a low frequency, ideally only once e.g. when starting the
11086 application.
11087
11088 \warning Serialized pipeline cache data is assumed to be trusted content. Qt
11089 performs robust parsing of the header and metadata included in \a data,
11090 application developers are however advised to never pass in data from
11091 untrusted sources.
11092
11093 \sa pipelineCacheData(), isFeatureSupported()
11094 */
11095void QRhi::setPipelineCacheData(const QByteArray &data)
11096{
11097 d->setPipelineCacheData(data);
11098}
11099
11100/*!
11101 \struct QRhiStats
11102 \inmodule QtGuiPrivate
11103 \inheaderfile rhi/qrhi.h
11104 \since 6.6
11105
11106 \brief Statistics provided from the underlying memory allocator.
11107
11108 \note This is a RHI API with limited compatibility guarantees, see \l QRhi
11109 for details.
11110 */
11111
11112/*!
11113 \variable QRhiStats::totalPipelineCreationTime
11114
11115 The total time in milliseconds spent in graphics and compute pipeline
11116 creation, which usually involves shader compilation or cache lookups, and
11117 potentially expensive processing.
11118
11119 \note The value should not be compared between different backends since the
11120 concept of "pipelines" and what exactly happens under the hood during, for
11121 instance, a call to QRhiGraphicsPipeline::create(), differ greatly between
11122 graphics APIs and their implementations.
11123
11124 \sa QRhi::statistics()
11125*/
11126
11127/*!
11128 \variable QRhiStats::blockCount
11129
11130 Statistic reported from the Vulkan or D3D12 memory allocator.
11131
11132 \sa QRhi::statistics()
11133*/
11134
11135/*!
11136 \variable QRhiStats::allocCount
11137
11138 Statistic reported from the Vulkan or D3D12 memory allocator.
11139
11140 \sa QRhi::statistics()
11141*/
11142
11143/*!
11144 \variable QRhiStats::usedBytes
11145
11146 Statistic reported from the Vulkan or D3D12 memory allocator.
11147
11148 \sa QRhi::statistics()
11149*/
11150
11151/*!
11152 \variable QRhiStats::unusedBytes
11153
11154 Statistic reported from the Vulkan or D3D12 memory allocator.
11155
11156 \sa QRhi::statistics()
11157*/
11158
11159/*!
11160 \variable QRhiStats::totalUsageBytes
11161
11162 Valid only with D3D12 currently. Matches IDXGIAdapter3::QueryVideoMemoryInfo().
11163
11164 \sa QRhi::statistics()
11165*/
11166
11167#ifndef QT_NO_DEBUG_STREAM
11168QDebug operator<<(QDebug dbg, const QRhiStats &info)
11169{
11170 QDebugStateSaver saver(dbg);
11171 dbg.nospace() << "QRhiStats("
11172 << "totalPipelineCreationTime=" << info.totalPipelineCreationTime
11173 << " blockCount=" << info.blockCount
11174 << " allocCount=" << info.allocCount
11175 << " usedBytes=" << info.usedBytes
11176 << " unusedBytes=" << info.unusedBytes
11177 << " totalUsageBytes=" << info.totalUsageBytes
11178 << ')';
11179 return dbg;
11180}
11181#endif
11182
11183/*!
11184 Gathers and returns statistics about the timings and allocations of
11185 graphics resources.
11186
11187 Data about memory allocations is only available with some backends, where
11188 such operations are under Qt's control. With graphics APIs where there is
11189 no lower level control over resource memory allocations, this will never be
11190 supported and all relevant fields in the results are 0.
11191
11192 With Vulkan in particular, the values are valid always, and are queried
11193 from the underlying memory allocator library. This gives an insight into
11194 the memory requirements of the active buffers and textures.
11195
11196 The same is true for Direct 3D 12. In addition to the memory allocator
11197 library's statistics, here the result also includes a \c totalUsageBytes
11198 field which reports the total size including additional resources that are
11199 not under the memory allocator library's control (swapchain buffers,
11200 descriptor heaps, etc.), as reported by DXGI.
11201
11202 The values correspond to all types of memory used, combined. (i.e. video +
11203 system in case of a discreet GPU)
11204
11205 Additional data, such as the total time in milliseconds spent in graphics
11206 and compute pipeline creation (which usually involves shader compilation or
11207 cache lookups, and potentially expensive processing) is available with most
11208 backends.
11209
11210 \note The elapsed times for operations such as pipeline creation may be
11211 affected by various factors. The results should not be compared between
11212 different backends since the concept of "pipelines" and what exactly
11213 happens under the hood during, for instance, a call to
11214 QRhiGraphicsPipeline::create(), differ greatly between graphics APIs and
11215 their implementations.
11216
11217 \note Additionally, many drivers will likely employ various caching
11218 strategies for shaders, programs, pipelines. (independently of Qt's own
11219 similar facilities, such as setPipelineCacheData() or the OpenGL-specific
11220 program binary disk cache). Because such internal behavior is transparent
11221 to the API client, Qt and QRhi have no knowledge or control over the exact
11222 caching strategy, persistency, invalidation of the cached data, etc. When
11223 reading timings, such as the time spent on pipeline creation, the potential
11224 presence and unspecified behavior of driver-level caching mechanisms should
11225 be kept in mind.
11226 */
11227QRhiStats QRhi::statistics() const
11228{
11229 return d->statistics();
11230}
11231
11232/*!
11233 \return a new graphics pipeline resource.
11234
11235 \sa QRhiResource::destroy()
11236 */
11237QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
11238{
11239 return d->createGraphicsPipeline();
11240}
11241
11242/*!
11243 \return a new compute pipeline resource.
11244
11245 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
11246 is reported as supported.
11247
11248 \sa QRhiResource::destroy()
11249 */
11250QRhiComputePipeline *QRhi::newComputePipeline()
11251{
11252 return d->createComputePipeline();
11253}
11254
11255/*!
11256 \return a new shader resource binding collection resource.
11257
11258 \sa QRhiResource::destroy()
11259 */
11260QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
11261{
11262 return d->createShaderResourceBindings();
11263}
11264
11265/*!
11266 \return a new buffer with the specified \a type, \a usage, and \a size.
11267
11268 \note Some \a usage and \a type combinations may not be supported by all
11269 backends. See \l{QRhiBuffer::UsageFlag}{UsageFlags} and
11270 \l{QRhi::NonDynamicUniformBuffers}{the feature flags}.
11271
11272 \note Backends may choose to allocate buffers bigger than \a size. This is
11273 done transparently to applications, so there are no special restrictions on
11274 the value of \a size. QRhiBuffer::size() will always report back the value
11275 that was requested in \a size.
11276
11277 \sa QRhiResource::destroy()
11278 */
11279QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type,
11280 QRhiBuffer::UsageFlags usage,
11281 quint32 size)
11282{
11283 return d->createBuffer(type, usage, size);
11284}
11285
11286/*!
11287 \return a new renderbuffer with the specified \a type, \a pixelSize, \a
11288 sampleCount, and \a flags.
11289
11290 When \a backingFormatHint is set to a texture format other than
11291 QRhiTexture::UnknownFormat, it may be used by the backend to decide what
11292 format to use for the storage backing the renderbuffer.
11293
11294 \note \a backingFormatHint becomes relevant typically when multisampling
11295 and floating point texture formats are involved: rendering into a
11296 multisample QRhiRenderBuffer and then resolving into a non-RGBA8
11297 QRhiTexture implies (with some graphics APIs) that the storage backing the
11298 QRhiRenderBuffer uses the matching non-RGBA8 format. That means that
11299 passing a format like QRhiTexture::RGBA32F is important, because backends
11300 will typically opt for QRhiTexture::RGBA8 by default, which would then
11301 break later on due to attempting to set up RGBA8->RGBA32F multisample
11302 resolve in the color attachment(s) of the QRhiTextureRenderTarget.
11303
11304 \sa QRhiResource::destroy()
11305 */
11306QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type,
11307 const QSize &pixelSize,
11308 int sampleCount,
11309 QRhiRenderBuffer::Flags flags,
11310 QRhiTexture::Format backingFormatHint)
11311{
11312 return d->createRenderBuffer(type, pixelSize, sampleCount, flags, backingFormatHint);
11313}
11314
11315/*!
11316 \return a new 1D or 2D texture with the specified \a format, \a pixelSize, \a
11317 sampleCount, and \a flags.
11318
11319 A 1D texture array must have QRhiTexture::OneDimensional set in \a flags. This
11320 function will implicitly set this flag if the \a pixelSize height is 0.
11321
11322 \note \a format specifies the requested internal and external format,
11323 meaning the data to be uploaded to the texture will need to be in a
11324 compatible format, while the native texture may (but is not guaranteed to,
11325 in case of OpenGL at least) use this format internally.
11326
11327 \note 1D textures are only functional when the OneDimensionalTextures feature is
11328 reported as supported at run time. Further, mipmaps on 1D textures are only
11329 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
11330
11331 \sa QRhiResource::destroy()
11332 */
11333QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
11334 const QSize &pixelSize,
11335 int sampleCount,
11336 QRhiTexture::Flags flags)
11337{
11338 if (pixelSize.height() == 0)
11339 flags |= QRhiTexture::OneDimensional;
11340
11341 return d->createTexture(format, pixelSize, 1, 0, sampleCount, flags);
11342}
11343
11344/*!
11345 \return a new 1D, 2D or 3D texture with the specified \a format, \a width, \a
11346 height, \a depth, \a sampleCount, and \a flags.
11347
11348 This overload is suitable for 3D textures because it allows specifying \a
11349 depth. A 3D texture must have QRhiTexture::ThreeDimensional set in \a
11350 flags, but using this overload that can be omitted because the flag is set
11351 implicitly whenever \a depth is greater than 0. For 1D, 2D and cube textures \a
11352 depth should be set to 0.
11353
11354 A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This overload
11355 will implicitly set this flag if both \a height and \a depth are 0.
11356
11357 \note 3D textures are only functional when the ThreeDimensionalTextures
11358 feature is reported as supported at run time.
11359
11360 \note 1D textures are only functional when the OneDimensionalTextures feature is
11361 reported as supported at run time. Further, mipmaps on 1D textures are only
11362 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
11363
11364 \overload
11365 */
11366QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
11367 int width, int height, int depth,
11368 int sampleCount,
11369 QRhiTexture::Flags flags)
11370{
11371 if (depth > 0)
11372 flags |= QRhiTexture::ThreeDimensional;
11373
11374 if (height == 0 && depth == 0)
11375 flags |= QRhiTexture::OneDimensional;
11376
11377 return d->createTexture(format, QSize(width, height), depth, 0, sampleCount, flags);
11378}
11379
11380/*!
11381 \return a new 1D or 2D texture array with the specified \a format, \a arraySize,
11382 \a pixelSize, \a sampleCount, and \a flags.
11383
11384 This function implicitly sets QRhiTexture::TextureArray in \a flags.
11385
11386 A 1D texture array must have QRhiTexture::OneDimensional set in \a flags. This
11387 function will implicitly set this flag if the \a pixelSize height is 0.
11388
11389 \note Do not confuse texture arrays with arrays of textures. A QRhiTexture
11390 created by this function is usable with 1D or 2D array samplers in the shader, for
11391 example: \c{layout(binding = 1) uniform sampler2DArray texArr;}. Arrays of
11392 textures refers to a list of textures that are exposed to the shader via
11393 QRhiShaderResourceBinding::sampledTextures() and a count > 1, and declared
11394 in the shader for example like this: \c{layout(binding = 1) uniform
11395 sampler2D textures[4];}
11396
11397 \note This is only functional when the TextureArrays feature is reported as
11398 supported at run time.
11399
11400 \note 1D textures are only functional when the OneDimensionalTextures feature is
11401 reported as supported at run time. Further, mipmaps on 1D textures are only
11402 functional when the OneDimensionalTextureMipmaps feature is reported at run time.
11403
11404
11405 \sa newTexture()
11406 */
11407QRhiTexture *QRhi::newTextureArray(QRhiTexture::Format format,
11408 int arraySize,
11409 const QSize &pixelSize,
11410 int sampleCount,
11411 QRhiTexture::Flags flags)
11412{
11413 flags |= QRhiTexture::TextureArray;
11414
11415 if (pixelSize.height() == 0)
11416 flags |= QRhiTexture::OneDimensional;
11417
11418 return d->createTexture(format, pixelSize, 1, arraySize, sampleCount, flags);
11419}
11420
11421/*!
11422 \return a new sampler with the specified magnification filter \a magFilter,
11423 minification filter \a minFilter, mipmapping mode \a mipmapMode, and the
11424 addressing (wrap) modes \a addressU, \a addressV, and \a addressW.
11425
11426 \note Setting \a mipmapMode to a value other than \c None implies that
11427 images for all relevant mip levels will be provided either via
11428 \l{QRhiResourceUpdateBatch::uploadTexture()}{texture uploads} or by calling
11429 \l{QRhiResourceUpdateBatch::generateMips()}{generateMips()} on the texture
11430 that is used with this sampler. Attempting to use the sampler with a
11431 texture that has no data for all relevant mip levels will lead to rendering
11432 errors, with the exact behavior dependent on the underlying graphics API.
11433
11434 \sa QRhiResource::destroy()
11435 */
11436QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter,
11437 QRhiSampler::Filter minFilter,
11438 QRhiSampler::Filter mipmapMode,
11439 QRhiSampler::AddressMode addressU,
11440 QRhiSampler::AddressMode addressV,
11441 QRhiSampler::AddressMode addressW)
11442{
11443 return d->createSampler(magFilter, minFilter, mipmapMode, addressU, addressV, addressW);
11444}
11445
11446/*!
11447 \return a new shading rate map object.
11448
11449 \since 6.9
11450 */
11451QRhiShadingRateMap *QRhi::newShadingRateMap()
11452{
11453 return d->createShadingRateMap();
11454}
11455
11456/*!
11457 \return a new texture render target with color and depth/stencil
11458 attachments given in \a desc, and with the specified \a flags.
11459
11460 \sa QRhiResource::destroy()
11461 */
11462
11463QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
11464 QRhiTextureRenderTarget::Flags flags)
11465{
11466 return d->createTextureRenderTarget(desc, flags);
11467}
11468
11469/*!
11470 \return a new swapchain.
11471
11472 \sa QRhiResource::destroy(), QRhiSwapChain::createOrResize()
11473 */
11474QRhiSwapChain *QRhi::newSwapChain()
11475{
11476 return d->createSwapChain();
11477}
11478
11479/*!
11480 Starts a new frame targeting the next available buffer of \a swapChain.
11481
11482 A frame consists of resource updates and one or more render and compute
11483 passes.
11484
11485 \a flags can indicate certain special cases.
11486
11487 The high level pattern of rendering into a QWindow using a swapchain:
11488
11489 \list
11490
11491 \li Create a swapchain.
11492
11493 \li Call QRhiSwapChain::createOrResize() whenever the surface size is
11494 different than before.
11495
11496 \li Call QRhiSwapChain::destroy() on
11497 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed.
11498
11499 \li Then on every frame:
11500 \badcode
11501 beginFrame(sc);
11502 updates = nextResourceUpdateBatch();
11503 updates->...
11504 QRhiCommandBuffer *cb = sc->currentFrameCommandBuffer();
11505 cb->beginPass(sc->currentFrameRenderTarget(), colorClear, dsClear, updates);
11506 ...
11507 cb->endPass();
11508 ... // more passes as necessary
11509 endFrame(sc);
11510 \endcode
11511
11512 \endlist
11513
11514 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
11515 value on failure. Some of these should be treated as soft, "try again
11516 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
11517 the swapchain is to be resized or updated by calling
11518 QRhiSwapChain::createOrResize(). The application should then attempt to
11519 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
11520 lost but this may also be recoverable by releasing all resources, including
11521 the QRhi itself, and then recreating all resources. See isDeviceLost() for
11522 further discussion.
11523
11524 \sa endFrame(), beginOffscreenFrame(), isDeviceLost()
11525 */
11526QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
11527{
11528 if (d->inFrame)
11529 qWarning("Attempted to call beginFrame() within a still active frame; ignored");
11530
11531 qCDebug(QRHI_LOG_RUB) << "[rub] new frame";
11532
11533 QRhi::FrameOpResult r = !d->inFrame ? d->beginFrame(swapChain, flags) : FrameOpSuccess;
11534 if (r == FrameOpSuccess)
11535 d->inFrame = true;
11536
11537 return r;
11538}
11539
11540/*!
11541 Ends, commits, and presents a frame that was started in the last
11542 beginFrame() on \a swapChain.
11543
11544 Double (or triple) buffering is managed internally by the QRhiSwapChain and
11545 QRhi.
11546
11547 \a flags can optionally be used to change the behavior in certain ways.
11548 Passing QRhi::SkipPresent skips queuing the Present command or calling
11549 swapBuffers.
11550
11551 \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
11552 value on failure. Some of these should be treated as soft, "try again
11553 later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
11554 the swapchain is to be resized or updated by calling
11555 QRhiSwapChain::createOrResize(). The application should then attempt to
11556 generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
11557 lost but this may also be recoverable by releasing all resources, including
11558 the QRhi itself, and then recreating all resources. See isDeviceLost() for
11559 further discussion.
11560
11561 \sa beginFrame(), isDeviceLost()
11562 */
11563QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags)
11564{
11565 if (!d->inFrame)
11566 qWarning("Attempted to call endFrame() without an active frame; ignored");
11567
11568 QRhi::FrameOpResult r = d->inFrame ? d->endFrame(swapChain, flags) : FrameOpSuccess;
11569 d->inFrame = false;
11570 // deleteLater is a high level QRhi concept the backends know
11571 // nothing about - handle it here.
11572 qDeleteAll(d->pendingDeleteResources);
11573 d->pendingDeleteResources.clear();
11574
11575 return r;
11576}
11577
11578/*!
11579 \return true when there is an active frame, meaning there was a
11580 beginFrame() (or beginOffscreenFrame()) with no corresponding endFrame()
11581 (or endOffscreenFrame()) yet.
11582
11583 \sa currentFrameSlot(), beginFrame(), endFrame()
11584 */
11585bool QRhi::isRecordingFrame() const
11586{
11587 return d->inFrame;
11588}
11589
11590/*!
11591 \return the current frame slot index while recording a frame. Unspecified
11592 when called outside an active frame (that is, when isRecordingFrame() is \c
11593 false).
11594
11595 With backends like Vulkan or Metal, it is the responsibility of the QRhi
11596 backend to block whenever starting a new frame and finding the CPU is
11597 already \c{FramesInFlight - 1} frames ahead of the GPU (because the command
11598 buffer submitted in frame no. \c{current} - \c{FramesInFlight} has not yet
11599 completed).
11600
11601 Resources that tend to change between frames (such as, the native buffer
11602 object backing a QRhiBuffer with type QRhiBuffer::Dynamic) exist in
11603 multiple versions, so that each frame, that can be submitted while a
11604 previous one is still being processed, works with its own copy, thus
11605 avoiding the need to stall the pipeline when preparing the frame. (The
11606 contents of a resource that may still be in use in the GPU should not be
11607 touched, but simply always waiting for the previous frame to finish would
11608 reduce GPU utilization and ultimately, performance and efficiency.)
11609
11610 Conceptually this is somewhat similar to copy-on-write schemes used by some
11611 C++ containers and other types. It may also be similar to what an OpenGL or
11612 Direct 3D 11 implementation performs internally for certain type of objects.
11613
11614 In practice, such double (or triple) buffering resources is realized in
11615 the Vulkan, Metal, and similar QRhi backends by having a fixed number of
11616 native resource (such as, VkBuffer) \c slots behind a QRhiResource. That
11617 can then be indexed by a frame slot index running 0, 1, ..,
11618 FramesInFlight-1, and then wrapping around.
11619
11620 All this is managed transparently to the users of QRhi. However,
11621 applications that integrate rendering done directly with the graphics API
11622 may want to perform a similar double or triple buffering of their own
11623 graphics resources. That is then most easily achieved by knowing the values
11624 of the maximum number of in-flight frames (retrievable via resourceLimit())
11625 and the current frame (slot) index (returned by this function).
11626
11627 \sa isRecordingFrame(), beginFrame(), endFrame()
11628 */
11629int QRhi::currentFrameSlot() const
11630{
11631 return d->currentFrameSlot;
11632}
11633
11634/*!
11635 Starts a new offscreen frame. Provides a command buffer suitable for
11636 recording rendering commands in \a cb. \a flags is used to indicate
11637 certain special cases, just like with beginFrame().
11638
11639 \note The QRhiCommandBuffer stored to *cb is not owned by the caller.
11640
11641 Rendering without a swapchain is possible as well. The typical use case is
11642 to use it in completely offscreen applications, e.g. to generate image
11643 sequences by rendering and reading back without ever showing a window.
11644
11645 Usage in on-screen applications (so beginFrame, endFrame,
11646 beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) is possible too
11647 but it does reduce parallelism so it should be done only infrequently.
11648
11649 Offscreen frames do not let the CPU potentially generate another frame
11650 while the GPU is still processing the previous one. This has the side
11651 effect that if readbacks are scheduled, the results are guaranteed to be
11652 available once endOffscreenFrame() returns. That is not the case with
11653 frames targeting a swapchain: there the GPU is potentially better utilized,
11654 but working with readback operations needs more care from the application
11655 because endFrame(), unlike endOffscreenFrame(), does not guarantee that the
11656 results from the readback are available at that point.
11657
11658 The skeleton of rendering a frame without a swapchain and then reading the
11659 frame contents back could look like the following:
11660
11661 \code
11662 QRhiReadbackResult rbResult;
11663 QRhiCommandBuffer *cb;
11664 rhi->beginOffscreenFrame(&cb);
11665 cb->beginPass(rt, colorClear, dsClear);
11666 // ...
11667 u = nextResourceUpdateBatch();
11668 u->readBackTexture(rb, &rbResult);
11669 cb->endPass(u);
11670 rhi->endOffscreenFrame();
11671 // image data available in rbResult
11672 \endcode
11673
11674 \sa endOffscreenFrame(), beginFrame()
11675 */
11676QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags)
11677{
11678 if (d->inFrame)
11679 qWarning("Attempted to call beginOffscreenFrame() within a still active frame; ignored");
11680
11681 qCDebug(QRHI_LOG_RUB) << "[rub] new offscreen frame";
11682
11683 QRhi::FrameOpResult r = !d->inFrame ? d->beginOffscreenFrame(cb, flags) : FrameOpSuccess;
11684 if (r == FrameOpSuccess)
11685 d->inFrame = true;
11686
11687 return r;
11688}
11689
11690/*!
11691 Ends, submits, and waits for the offscreen frame.
11692
11693 \a flags is not currently used.
11694
11695 \sa beginOffscreenFrame()
11696 */
11697QRhi::FrameOpResult QRhi::endOffscreenFrame(EndFrameFlags flags)
11698{
11699 if (!d->inFrame)
11700 qWarning("Attempted to call endOffscreenFrame() without an active frame; ignored");
11701
11702 QRhi::FrameOpResult r = d->inFrame ? d->endOffscreenFrame(flags) : FrameOpSuccess;
11703 d->inFrame = false;
11704 qDeleteAll(d->pendingDeleteResources);
11705 d->pendingDeleteResources.clear();
11706
11707 return r;
11708}
11709
11710/*!
11711 Waits for any work on the graphics queue (where applicable) to complete,
11712 then executes all deferred operations, like completing readbacks and
11713 resource releases. Can be called inside and outside of a frame, but not
11714 inside a pass. Inside a frame it implies submitting any work on the
11715 command buffer.
11716
11717 \note Avoid this function. One case where it may be needed is when the
11718 results of an enqueued readback in a swapchain-based frame are needed at a
11719 fixed given point and so waiting for the results is desired.
11720 */
11721QRhi::FrameOpResult QRhi::finish()
11722{
11723 return d->finish();
11724}
11725
11726/*!
11727 \return the list of supported sample counts.
11728
11729 A typical example would be (1, 2, 4, 8).
11730
11731 With some backend this list of supported values is fixed in advance, while
11732 with some others the (physical) device properties indicate what is
11733 supported at run time.
11734
11735 \sa QRhiRenderBuffer::setSampleCount(), QRhiTexture::setSampleCount(),
11736 QRhiGraphicsPipeline::setSampleCount(), QRhiSwapChain::setSampleCount()
11737 */
11738QList<int> QRhi::supportedSampleCounts() const
11739{
11740 return d->supportedSampleCounts();
11741}
11742
11743/*!
11744 \return the minimum uniform buffer offset alignment in bytes. This is
11745 typically 256.
11746
11747 Attempting to bind a uniform buffer region with an offset not aligned to
11748 this value will lead to failures depending on the backend and the
11749 underlying graphics API.
11750
11751 \sa ubufAligned()
11752 */
11753int QRhi::ubufAlignment() const
11754{
11755 return d->ubufAlignment();
11756}
11757
11758/*!
11759 \return The list of supported variable shading rates for the specified \a sampleCount.
11760
11761 1x1 is always supported.
11762
11763 \since 6.9
11764 */
11765QList<QSize> QRhi::supportedShadingRates(int sampleCount) const
11766{
11767 return d->supportedShadingRates(sampleCount);
11768}
11769
11770Q_CONSTINIT static QBasicAtomicInteger<QRhiGlobalObjectIdGenerator::Type> counter = Q_BASIC_ATOMIC_INITIALIZER(0);
11771
11772QRhiGlobalObjectIdGenerator::Type QRhiGlobalObjectIdGenerator::newId()
11773{
11774 return counter.fetchAndAddRelaxed(1) + 1;
11775}
11776
11778{
11779 return m_buffers.isEmpty() && m_textures.isEmpty();
11780}
11781
11783{
11784 m_buffers.clear();
11785 m_textures.clear();
11786}
11787
11793
11794void QRhiPassResourceTracker::registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
11795 const UsageState &state)
11796{
11797 auto it = m_buffers.find(buf);
11798 if (it != m_buffers.end()) {
11799 Buffer &b = it->second;
11800 if (Q_UNLIKELY(b.access != *access)) {
11801 const QByteArray name = buf->name();
11802 qWarning("Buffer %p (%s) used with different accesses within the same pass, this is not allowed.",
11803 buf, name.constData());
11804 return;
11805 }
11806 if (b.stage != *stage) {
11807 b.stage = earlierStage(b.stage, *stage);
11808 *stage = b.stage;
11809 }
11810 return;
11811 }
11812
11813 Buffer b;
11814 b.slot = slot;
11815 b.access = *access;
11816 b.stage = *stage;
11817 b.stateAtPassBegin = state; // first use -> initial state
11818 m_buffers.insert(buf, b);
11819}
11820
11826
11833
11835 const UsageState &state)
11836{
11837 auto it = m_textures.find(tex);
11838 if (it != m_textures.end()) {
11839 Texture &t = it->second;
11840 if (t.access != *access) {
11841 // Different subresources of a texture may be used for both load
11842 // and store in the same pass. (think reading from one mip level
11843 // and writing to another one in a compute shader) This we can
11844 // handle by treating the entire resource as read-write.
11845 if (Q_LIKELY(isImageLoadStore(t.access) && isImageLoadStore(*access))) {
11847 *access = t.access;
11848 } else {
11849 const QByteArray name = tex->name();
11850 qWarning("Texture %p (%s) used with different accesses within the same pass, this is not allowed.",
11851 tex, name.constData());
11852 }
11853 }
11854 if (t.stage != *stage) {
11855 t.stage = earlierStage(t.stage, *stage);
11856 *stage = t.stage;
11857 }
11858 return;
11859 }
11860
11861 Texture t;
11862 t.access = *access;
11863 t.stage = *stage;
11864 t.stateAtPassBegin = state; // first use -> initial state
11865 m_textures.insert(tex, t);
11866}
11867
11868QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
11869{
11870 // pick the earlier stage (as this is going to be dstAccessMask)
11871 if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
11873 if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
11875 if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
11877 if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
11879 if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
11881 if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
11883
11884 Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::BufVertexStage);
11885}
11886
11887QRhiPassResourceTracker::TextureStage QRhiPassResourceTracker::toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
11888{
11889 // pick the earlier stage (as this is going to be dstAccessMask)
11890 if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
11892 if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
11894 if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
11896 if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
11898 if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
11900 if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
11902
11903 Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::TexVertexStage);
11904}
11905
11906QSize QRhiImplementation::clampedSubResourceUploadSize(QSize size, QPoint dstPos, int level, QSize textureSizeAtLevelZero, bool warn)
11907{
11908 const QSize subResSize = q->sizeForMipLevel(level, textureSizeAtLevelZero);
11909 const bool outOfBoundsHoriz = dstPos.x() + size.width() > subResSize.width();
11910 const bool outOfBoundsVert = dstPos.y() + size.height() > subResSize.height();
11911 if (Q_UNLIKELY(outOfBoundsHoriz || outOfBoundsVert)) {
11912 if (warn) {
11913 qWarning("Invalid texture upload issued; size %dx%d dst.position %d,%d dst.subresource size %dx%d; size will be clamped",
11914 size.width(), size.height(), dstPos.x(), dstPos.y(), subResSize.width(), subResSize.height());
11915 }
11916 if (outOfBoundsHoriz)
11917 size.setWidth(subResSize.width() - dstPos.x());
11918 if (outOfBoundsVert)
11919 size.setHeight(subResSize.height() - dstPos.y());
11920 }
11921 return size;
11922}
11923
11924QT_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:807
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:818
bool isEmpty() const
Definition qrhi.cpp:11777
void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage, const UsageState &state)
Definition qrhi.cpp:11794
void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage, const UsageState &state)
Definition qrhi.cpp:11834
QRhiImplementation * rhi
Definition qrhi_p.h:583
static const int BUFFER_OPS_STATIC_ALLOC
Definition qrhi_p.h:575
void merge(QRhiResourceUpdateBatchPrivate *other)
Definition qrhi.cpp:10022
QRhiResourceUpdateBatch * q
Definition qrhi_p.h:582
static const int TEXTURE_OPS_STATIC_ALLOC
Definition qrhi_p.h:579
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
static const char * resourceTypeStr(const QRhiResource *res)
Definition qrhi.cpp:8393
static QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a, QRhiPassResourceTracker::BufferStage b)
Definition qrhi.cpp:11788
QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
Definition qrhi.cpp:8208
static bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess access)
Definition qrhi.cpp:11827
static const char * deviceTypeStr(QRhiDriverInfo::DeviceType type)
\variable QRhiDriverInfo::deviceName
Definition qrhi.cpp:9312
static QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a, QRhiPassResourceTracker::TextureStage b)
Definition qrhi.cpp:11821
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:1555
LimitsType limitsType
Definition qrhi.h:1566
float maxPotentialColorComponentValue
Definition qrhi.h:1574
LuminanceBehavior luminanceBehavior
Definition qrhi.h:1577
float maxColorComponentValue
Definition qrhi.h:1573