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

source code of qtbase/src/gui/rhi/qrhi.cpp