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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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