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

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