Coverage Report

Created: 2026-08-25 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/rhi/qrhi.cpp
Line
Count
Source
1
// Copyright (C) 2023 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
#include "qrhi_p.h"
6
#include <qmath.h>
7
#include <QLoggingCategory>
8
#include "private/qloggingregistry_p.h"
9
10
#include "qrhinull_p.h"
11
#ifndef QT_NO_OPENGL
12
#include "qrhigles2_p.h"
13
#endif
14
#if QT_CONFIG(vulkan)
15
#include "qrhivulkan_p.h"
16
#endif
17
#ifdef Q_OS_WIN
18
#include "qrhid3d11_p.h"
19
#include "qrhid3d12_p.h"
20
#endif
21
#if QT_CONFIG(metal)
22
#include "qrhimetal_p.h"
23
#endif
24
25
#include <limits>
26
#include <memory>
27
28
QT_BEGIN_NAMESPACE
29
30
// Play nice with QSG_INFO since that is still the most commonly used
31
// way to get graphics info printed from Qt Quick apps, and the Quick
32
// scenegraph is our primary user.
33
Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(QRHI_LOG_INFO, "QSG_INFO", "qt.rhi.general")
34
35
Q_LOGGING_CATEGORY(QRHI_LOG_RUB, "qt.rhi.rub")
36
37
/*!
38
    \class QRhi
39
    \ingroup painting-3D
40
    \inmodule QtGuiPrivate
41
    \inheaderfile rhi/qrhi.h
42
    \since 6.6
43
44
    \brief Accelerated 2D/3D graphics API abstraction.
45
46
    The Qt Rendering Hardware Interface is an abstraction for hardware accelerated
47
    graphics APIs, such as, \l{https://www.khronos.org/opengl/}{OpenGL},
48
    \l{https://www.khronos.org/opengles/}{OpenGL ES},
49
    \l{https://docs.microsoft.com/en-us/windows/desktop/direct3d}{Direct3D},
50
    \l{https://developer.apple.com/metal/}{Metal}, and
51
    \l{https://www.khronos.org/vulkan/}{Vulkan}.
52
53
    \warning The QRhi family of classes in the Qt Gui module, including QShader
54
    and QShaderDescription, offer limited compatibility guarantees. There are
55
    no source or binary compatibility guarantees for these classes, meaning the
56
    API is only guaranteed to work with the Qt version the application was
57
    developed against. Source incompatible changes are however aimed to be kept
58
    at a minimum and will only be made in minor releases (6.7, 6.8, and so on).
59
    To use these classes in an application, link to
60
    \c{Qt::GuiPrivate} (if using CMake), and include the headers with the \c
61
    rhi prefix, for example \c{#include <rhi/qrhi.h>}.
62
63
    Each QRhi instance is backed by a backend for a specific graphics API. The
64
    selection of the backend is a run time choice and is up to the application
65
    or library that creates the QRhi instance. Some backends are available on
66
    multiple platforms (OpenGL, Vulkan, Null), while APIs specific to a given
67
    platform are only available when running on the platform in question (Metal
68
    on macOS/iOS, Direct3D on Windows).
69
70
    The available backends currently are:
71
72
    \list
73
74
    \li OpenGL 2.1 / OpenGL ES 2.0 or newer. Some extensions and newer core
75
    specification features are utilized when present, for example to enable
76
    multisample framebuffers or compute shaders. Operating in core profile
77
    contexts is supported as well. If necessary, applications can query the
78
    \l{QRhi::Feature}{feature flags} at runtime to check for features that are
79
    not supported in the OpenGL context backing the QRhi. The OpenGL backend
80
    builds on QOpenGLContext, QOpenGLFunctions, and the related cross-platform
81
    infrastructure of the Qt GUI module.
82
83
    \li Direct3D 11.2 and newer (with DXGI 1.3 and newer), using Shader Model
84
    5.0 or newer. When the D3D runtime has no support for 11.2 features or
85
    Shader Model 5.0, initialization using an accelerated graphics device will
86
    fail, but using the
87
    \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/directx-warp}{software
88
    adapter} is still an option.
89
90
    \li Direct3D 12 on Windows 10 version 1703 and newer, with Shader Model 5.0
91
    or newer. Qt requires ID3D12Device2 to be present, hence the requirement
92
    for at least version 1703 of Windows 10. The D3D12 device is by default
93
    created with specifying a minimum feature level of
94
    \c{D3D_FEATURE_LEVEL_11_0}.
95
96
    \li Metal 1.2 or newer.
97
98
    \li Vulkan 1.0 or newer, optionally utilizing some Vulkan 1.1 level
99
    features.
100
101
    \li Null, a "dummy" backend that issues no graphics calls at all.
102
103
    \endlist
104
105
    In order to allow shader code to be written once in Qt applications and
106
    libraries, all shaders are expected to be written in a single language
107
    which is then compiled into SPIR-V. Versions for various shading language
108
    are then generated from that, together with reflection information (inputs,
109
    outputs, shader resources). This is then packed into easily and efficiently
110
    serializable QShader instances. The compilers and tools to generate such
111
    shaders are not part of QRhi and the Qt GUI module, but the core classes
112
    for using such shaders, QShader and QShaderDescription, are. The APIs and
113
    tools for performing compilation and translation are part of the Qt Shader
114
    Tools module.
115
116
    See the \l{RHI Window Example} for an introductory example of creating a
117
    portable, cross-platform application that performs accelerated 3D rendering
118
    onto a QWindow using QRhi.
119
120
    \section1 An Impression of the API
121
122
    To provide a quick look at the API with a short yet complete example that
123
    does not involve window-related setup, the following is a complete,
124
    runnable cross-platform application that renders 20 frames off-screen, and
125
    then saves the generated images to files after reading back the texture
126
    contents from the GPU. For an example that renders on-screen, which then
127
    involves setting up a QWindow and a swapchain, refer to the
128
    \l{RHI Window Example}.
129
130
    For brevity, the initialization of the QRhi is done based on the platform:
131
    the sample code here chooses Direct 3D 12 on Windows, Metal on macOS and
132
    iOS, and Vulkan otherwise. OpenGL and Direct 3D 11 are never used by this
133
    application, but support for those could be introduced with a few
134
    additional lines.
135
136
    \snippet rhioffscreen/main.cpp 0
137
138
    The result of the application is 20 \c PNG images (frame0.png -
139
    frame19.png). These contain a rotating triangle with varying opacity over a
140
    green background.
141
142
    The vertex and fragment shaders are expected to be processed and packaged
143
    into \c{.qsb} files. The Vulkan-compatible GLSL source code is the
144
    following:
145
146
    \e color.vert
147
    \snippet rhioffscreen/color.vert 0
148
149
    \e color.frag
150
    \snippet rhioffscreen/color.frag 0
151
152
    To manually compile and transpile these shaders to a number of targets
153
    (SPIR-V, HLSL, MSL, GLSL) and generate the \c{.qsb} files the application
154
    loads at run time, run \c{qsb --qt6 color.vert -o color.vert.qsb} and
155
    \c{qsb --qt6 color.frag -o color.frag.qsb}. Alternatively, the Qt Shader
156
    Tools module offers build system integration for CMake, the
157
    \c qt_add_shaders() CMake function, that can achieve the same at build time.
158
159
    \section1 Security Considerations
160
161
    All data consumed by QRhi and related classes such as QShader are considered
162
    trusted content.
163
164
    \warning Application developers are advised to carefully consider the
165
    potential implications before allowing the feeding of user-provided content
166
    that is not part of the application and is not under the developers'
167
    control. (this includes all vertex/index data, shaders, pipeline and draw
168
    call parameters, etc.)
169
170
    \section1 Design Fundamentals
171
172
    A QRhi cannot be instantiated directly. Instead, use the create()
173
    function. Delete the QRhi instance normally to release the graphics device.
174
175
    \section2 Resources
176
177
    Instances of classes deriving from QRhiResource, such as, QRhiBuffer,
178
    QRhiTexture, etc., encapsulate zero, one, or more native graphics
179
    resources. Instances of such classes are always created via the \c new
180
    functions of the QRhi, such as, newBuffer(), newTexture(),
181
    newTextureRenderTarget(), newSwapChain().
182
183
    \code
184
        QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
185
        if (!vbuf->create()) { error(); }
186
        // ...
187
        delete vbuf;
188
    \endcode
189
190
    \list
191
192
    \li The returned value from functions like newBuffer() is always owned by
193
    the caller.
194
195
    \li Just creating an instance of a QRhiResource subclass never allocates or
196
    initializes any native resources. That is only done when calling the
197
    \c create() function of a subclass, for example, QRhiBuffer::create() or
198
    QRhiTexture::create().
199
200
    \li The exceptions are
201
    QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor(),
202
    QRhiSwapChain::newCompatibleRenderPassDescriptor(), and
203
    QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor(). There is no
204
    \c create() operation for these and the returned object is immediately
205
    active.
206
207
    \li The resource objects themselves are treated as immutable: once a
208
    resource has create() called, changing any parameters via the setters, such as,
209
    QRhiTexture::setPixelSize(), has no effect, unless the underlying native
210
    resource is released and \c create() is called again. See more about resource
211
    reuse in the sections below.
212
213
    \li The underlying native resources are scheduled for releasing by the
214
    QRhiResource destructor, or by calling QRhiResource::destroy(). Backends
215
    often queue release requests and defer executing them to an unspecified
216
    time, this is hidden from the applications. This way applications do not
217
    have to worry about releasing native resources that may still be in use by
218
    an in-flight frame.
219
220
    \li Note that this does not mean that a QRhiResource can freely be
221
    destroy()'ed or deleted within a frame (that is, in a
222
    \l{QRhi::beginFrame()}{beginFrame()} - \l{QRhi::endFrame()}{endFrame()}
223
    section). As a general rule, all referenced QRhiResource objects must stay
224
    unchanged until the frame is submitted by calling
225
    \l{QRhi::endFrame()}{endFrame()}. To ease this,
226
    QRhiResource::deleteLater() is provided as a convenience.
227
228
    \endlist
229
230
    \section2 Command buffers and deferred command execution
231
232
    Regardless of the design and capabilities of the underlying graphics API,
233
    all QRhi backends implement some level of command buffers. No
234
    QRhiCommandBuffer function issues any native bind or draw command (such as,
235
    \c glDrawElements) directly. Commands are always recorded in a queue,
236
    either native or provided by the QRhi backend. The command buffer is
237
    submitted, and so execution starts only upon QRhi::endFrame() or
238
    QRhi::finish().
239
240
    The deferred nature has consequences for some types of objects. For example,
241
    writing to a dynamic buffer multiple times within a frame, in case such
242
    buffers are backed by host-visible memory, will result in making the
243
    results of all writes are visible to all draw calls in the command buffer
244
    of the frame, regardless of when the dynamic buffer update was recorded
245
    relative to a draw call.
246
247
    Furthermore, instances of QRhiResource subclasses must be treated immutable
248
    within a frame in which they are referenced in any way. Create
249
    all resources upfront, before starting to record commands for the next
250
    frame. Reusing a QRhiResource instance within a frame (by calling \c create()
251
    then referencing it again in the same \c{beginFrame - endFrame} section)
252
    should be avoided as it may lead to unexpected results, depending on the
253
    backend.
254
255
    As a general rule, all referenced QRhiResource objects must stay valid and
256
    unmodified until the frame is submitted by calling
257
    \l{QRhi::endFrame()}{endFrame()}. On the other hand, calling
258
    \l{QRhiResource::destroy()}{destroy()} or deleting the QRhiResource are
259
    always safe once the frame is submitted, regardless of the status of the
260
    underlying native resources (which may still be in use by the GPU - but
261
    that is taken care of internally).
262
263
    Unlike APIs like OpenGL, upload and copy type of commands cannot be mixed
264
    with draw commands. The typical renderer will involve a sequence similar to
265
    the following:
266
267
    \list
268
    \li (re)create resources
269
    \li begin frame
270
    \li record/issue uploads and copies
271
    \li start recording a render pass
272
    \li record draw calls
273
    \li end render pass
274
    \li end frame
275
    \endlist
276
277
    Recording copy type of operations happens via QRhiResourceUpdateBatch. Such
278
    operations are committed typically on
279
    \l{QRhiCommandBuffer::beginPass()}{beginPass()}.
280
281
    When working with legacy rendering engines designed for OpenGL, the
282
    migration to QRhi often involves redesigning from having a single \c render
283
    step (that performs copies and uploads, clears buffers, and issues draw
284
    calls, all mixed together) to a clearly separated, two phase \c prepare -
285
    \c render setup where the \c render step only starts a renderpass and
286
    records draw calls, while all resource creation and queuing of updates,
287
    uploads and copies happens beforehand, in the \c prepare step.
288
289
    QRhi does not at the moment allow freely creating and submitting command
290
    buffers. This may be lifted in the future to some extent, in particular if
291
    compute support is introduced, but the model of well defined
292
    \c{frame-start} and \c{frame-end} points, combined with a dedicated,
293
    "frame" command buffer, where \c{frame-end} implies presenting, is going to
294
    remain the primary way of operating since this is what fits Qt's various UI
295
    technologies best.
296
297
    \section2 Threading
298
299
    A QRhi instance and the associated resources can be created and used on any
300
    thread but all usage must be limited to that one single thread. When
301
    rendering to multiple QWindows in an application, having a dedicated thread
302
    and QRhi instance for each window is often advisable, as this can eliminate
303
    issues with unexpected throttling caused by presenting to multiple windows.
304
    Conceptually that is then the same as how Qt Quick scene graph's threaded
305
    render loop operates when working directly with OpenGL: one thread for each
306
    window, one QOpenGLContext for each thread. When moving onto QRhi,
307
    QOpenGLContext is replaced by QRhi, making the migration straightforward.
308
309
    When it comes to externally created native objects, such as OpenGL contexts
310
    passed in via QRhiGles2NativeHandles, it is up to the application to ensure
311
    they are not misused by other threads.
312
313
    Resources are not shareable between QRhi instances. This is an intentional
314
    choice since QRhi hides most queue, command buffer, and resource
315
    synchronization related tasks, and provides no API for them. Safe and
316
    efficient concurrent use of graphics resources from multiple threads is
317
    tied to those concepts, however, and is thus a topic that is currently out
318
    of scope, but may be introduced in the future.
319
320
    \note The Metal backend requires that an autorelease pool is available on
321
    the rendering thread, ideally wrapping each iteration of the render loop.
322
    This needs no action from the users of QRhi when rendering on the main
323
    (gui) thread, but becomes important when a separate, dedicated render
324
    thread is used.
325
326
    \section2 Resource synchronization
327
328
    QRhi does not expose APIs for resource barriers or image layout
329
    transitions. Such synchronization is done implicitly by the backends, where
330
    applicable (for example, Vulkan), by tracking resource usage as necessary.
331
    Buffer and image barriers are inserted before render or compute passes
332
    transparently to the application.
333
334
    \note Resources within a render or compute pass are expected to be bound to
335
    a single usage during that pass. For example, a buffer can be used as
336
    vertex, index, uniform, or storage buffer, but not a combination of them
337
    within a single pass. However, it is perfectly fine to use a buffer as a
338
    storage buffer in a compute pass, and then as a vertex buffer in a render
339
    pass, for example, assuming the buffer declared both usages upon creation.
340
341
    \note Textures have this rule relaxed in certain cases, because using two
342
    subresources (typically two different mip levels) of the same texture for
343
    different access (one for load, one for store) is supported even within the
344
    same pass.
345
346
    \section2 Resource reuse
347
348
    From the user's point of view a QRhiResource is reusable immediately after
349
    calling QRhiResource::destroy(). With the exception of swapchains, calling
350
    \c create() on an already created object does an implicit \c destroy(). This
351
    provides a handy shortcut to reuse a QRhiResource instance with different
352
    parameters, with a new native graphics object underneath.
353
354
    The importance of reusing the same object lies in the fact that some
355
    objects reference other objects: for example, a QRhiShaderResourceBindings
356
    can reference QRhiBuffer, QRhiTexture, and QRhiSampler instances. If in a
357
    later frame one of these buffers need to be resized or a sampler parameter
358
    needs changing, destroying and creating a whole new QRhiBuffer or
359
    QRhiSampler would invalidate all references to the old instance. By just
360
    changing the appropriate parameters via QRhiBuffer::setSize() or similar
361
    and then calling QRhiBuffer::create(), everything works as expected and
362
    there is no need to touch the QRhiShaderResourceBindings at all, even
363
    though there is a good chance that under the hood the QRhiBuffer is now
364
    backed by a whole new native buffer.
365
366
    \code
367
        QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 256);
368
        ubuf->create();
369
370
        QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings()
371
        srb->setBindings({
372
            QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf)
373
        });
374
        srb->create();
375
376
        // ...
377
378
        // now in a later frame we need to grow the buffer to a larger size
379
        ubuf->setSize(512);
380
        ubuf->create(); // same as ubuf->destroy(); ubuf->create();
381
382
        // srb needs no changes whatsoever, any references in it to ubuf
383
        // stay valid. When it comes to internal details, such as that
384
        // ubuf may now be backed by a completely different native buffer
385
        // resource, that is is recognized and handled automatically by the
386
        // next setShaderResources().
387
    \endcode
388
389
    QRhiTextureRenderTarget offers the same contract: calling
390
    QRhiCommandBuffer::beginPass() is safe even when one of the render target's
391
    associated textures or renderbuffers has been rebuilt (by calling \c
392
    create() on it) since the creation of the render target object. This allows
393
    the application to resize a texture by setting a new pixel size on the
394
    QRhiTexture and calling create(), thus creating a whole new native texture
395
    resource underneath, without having to update the QRhiTextureRenderTarget
396
    as that will be done implicitly in beginPass().
397
398
    \section2 Pooled objects
399
400
    In addition to resources, there are pooled objects as well, such as,
401
    QRhiResourceUpdateBatch. An instance is retrieved via a \c next function,
402
    such as, nextResourceUpdateBatch(). The caller does not own the returned
403
    instance in this case. The only valid way of operating here is calling
404
    functions on the QRhiResourceUpdateBatch and then passing it to
405
    QRhiCommandBuffer::beginPass() or QRhiCommandBuffer::endPass(). These
406
    functions take care of returning the batch to the pool. Alternatively, a
407
    batch can be "canceled" and returned to the pool without processing by
408
    calling QRhiResourceUpdateBatch::release().
409
410
    A typical pattern is thus:
411
412
    \code
413
        QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
414
        // ...
415
        resUpdates->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
416
        if (!image.isNull()) {
417
            resUpdates->uploadTexture(texture, image);
418
            image = QImage();
419
        }
420
        // ...
421
        QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
422
        // note the last argument
423
        cb->beginPass(swapchain->currentFrameRenderTarget(), clearCol, clearDs, resUpdates);
424
    \endcode
425
426
    \section2 Swapchain specifics
427
428
    QRhiSwapChain features some special semantics due to the peculiar nature of
429
    swapchains.
430
431
    \list
432
433
    \li It has no \c create() but rather a QRhiSwapChain::createOrResize().
434
    Repeatedly calling this function is \b not the same as calling
435
    QRhiSwapChain::destroy() followed by QRhiSwapChain::createOrResize(). This
436
    is because swapchains often have ways to handle the case where buffers need
437
    to be resized in a manner that is more efficient than a brute force
438
    destroying and recreating from scratch.
439
440
    \li An active QRhiSwapChain must be released by calling
441
    \l{QRhiSwapChain::destroy()}{destroy()}, or by destroying the object, before
442
    the QWindow's underlying QPlatformWindow, and so the associated native
443
    window object, is destroyed. It should not be postponed because releasing
444
    the swapchain may become problematic (and with some APIs, like Vulkan, is
445
    explicitly disallowed) when the native window is not around anymore, for
446
    example because the QPlatformWindow got destroyed upon getting a
447
    QWindow::close(). Therefore, releasing the swapchain must happen whenever
448
    the targeted QWindow sends the
449
    QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed event. If the event does
450
    not arrive before the destruction of the QWindow - this can happen when
451
    using QCoreApplication::quit() -, then check QWindow::handle() after the
452
    event loop exits and invoke the swapchain release when non-null (meaning
453
    the underlying native window is still around).
454
455
    \endlist
456
457
    \section2 Ownership
458
459
    The general rule is no ownership transfer. Creating a QRhi with an already
460
    existing graphics device does not mean the QRhi takes ownership of the
461
    device object. Similarly, ownership is not given away when a device or
462
    texture object is "exported" via QRhi::nativeHandles() or
463
    QRhiTexture::nativeTexture(). Most importantly, passing pointers in structs
464
    and via setters does not transfer ownership.
465
466
    \section1 Troubleshooting and Profiling
467
468
    \section2 Error reporting
469
470
    Functions such as \l QRhi::create() and the resource classes' \c create()
471
    member functions (e.g., \l QRhiBuffer::create()) indicate failure with the
472
    return value (\nullptr or
473
    \c false, respectively). When working with QShader, \l QShader::fromSerialized()
474
    returns an invalid QShader (for which \l{QShader::isValid()}{isValid()} returns
475
    \c false) when the data passed to the function cannot be successfully deserialized.
476
    Some functions, beginFrame() in particular, may also sometimes report "soft failures",
477
    such as \l FrameOpSwapChainOutOfDate, which do not indicate an unrecoverable error,
478
    but rather should be seen as a "try again later" response.
479
480
    Warnings and errors may get printed at any time to the debug output via
481
    qWarning(). It is therefore always advisable to inspect the output of the
482
    application.
483
484
    Additional debug messages can be enabled via the following logging
485
    categories. Messages from these categories are not printed by default
486
    unless explicitly enabled via QLoggingCategory or the \c QT_LOGGING_RULES
487
    environment variable. For better interoperation with Qt Quick, the
488
    environment variable \c{QSG_INFO} also enables these debug prints.
489
490
    \list
491
    \li \c{qt.rhi.general}
492
    \endlist
493
494
    Additionally, applications can query the \l{QRhi::backendName()}{QRhi
495
    backend name} and
496
    \l{QRhi::driverInfo()}{graphics device information} from a successfully
497
    initialized QRhi. This can then be printed to the user or stored in the
498
    application logs even in production builds, if desired.
499
500
    \section2 Investigating rendering problems
501
502
    When the rendering results are not as expected, or the application is
503
    experiencing problems, always consider checking with the native 3D
504
    APIs' debug and validation facilities. QRhi itself features limited error
505
    checking since replicating the already existing, vast amount of
506
    functionality in the underlying layers is not reasonable.
507
508
    \list
509
510
    \li For Vulkan, controlling the
511
    \l{https://github.com/KhronosGroup/Vulkan-ValidationLayers}{Vulkan
512
    Validation Layers} is not in the scope of the QRhi, but rather can be
513
    achieved by configuring the \l QVulkanInstance with the appropriate layers.
514
    For example, call \c{instance.setLayers({ "VK_LAYER_KHRONOS_validation" });}
515
    before invoking \l{QVulkanInstance::create()}{create()} on the QVulkanInstance.
516
    (note that this assumes that the validation layers are actually installed
517
    and available, e.g. from the Vulkan SDK) By default, QVulkanInstance conveniently
518
    redirects the Vulkan debug messages to qDebug, meaning the validation messages get
519
    printed just like other Qt warnings.
520
521
    \li With Direct 3D 11 and 12, a graphics device with the debug layer
522
    enabled can be requested by toggling the \c enableDebugLayer flag in the
523
    appropriate \l{QRhiD3D11InitParams}{init params struct}. With Direct 3D 12 the
524
    messages are then printed via qDebug, just like the Vulkan validation
525
    messages, as long as the debug layer supports message callbacks. Otherwise,
526
    and always with Direct 3D 11, the messages appear on the debug output, which
527
    is visible in Qt Creator's messages panel or via a tool such as
528
    \l{https://learn.microsoft.com/en-us/sysinternals/downloads/debugview}{DebugView}.
529
530
    \li For Metal, controlling Metal Validation is outside of QRhi's scope.
531
    Rather, to enable validation, run the application with the environment
532
    variable \c{METAL_DEVICE_WRAPPER_TYPE=1} set, or run the application within
533
    XCode. There may also be further settings and environment variable in modern
534
    XCode and macOS versions. See for instance
535
    \l{https://developer.apple.com/documentation/metal/diagnosing_metal_programming_issues_early}{this
536
    page}.
537
538
    \endlist
539
540
    \section2 Frame captures and performance profiling
541
542
    A Qt application rendering with QRhi to a window while relying on a 3D API
543
    under the hood, is, from the windowing and graphics pipeline perspective at
544
    least, no different from any other (non-Qt) applications using the same 3D
545
    API. This means that tools and practices for debugging and profiling
546
    applications involving 3D graphics, such as games, all apply to such a Qt
547
    application as well.
548
549
    A few examples of tools that can provide insights into the rendering
550
    internals of Qt applications that use QRhi, which includes Qt Quick and Qt
551
    Quick 3D based projects as well:
552
553
    \list
554
555
    \li \l{https://renderdoc.org/}{RenderDoc} allows taking frame captures and
556
    introspecting the recorded commands and pipeline state on Windows and Linux
557
    for applications using OpenGL, Vulkan, D3D11, or D3D12. When trying to
558
    figure out why some parts of the 3D scene do not show up as expected,
559
    RenderDoc is often a fast and efficient way to check the pipeline stages
560
    and the related state and discover the missing or incorrect value. It is
561
    also a tool that is actively used when developing Qt itself.
562
563
    \li For NVIDIA-based systems,
564
    \l{https://developer.nvidia.com/nsight-graphics}{Nsight Graphics} provides
565
    a graphics debugger tool on Windows and Linux. In addition to investigating the commands
566
    in the frame and the pipeline, the vendor-specific tools allow looking at timings and
567
    hardware performance information, which is not something simple frame captures can provide.
568
569
    \li For AMD-based systems, the \l{https://gpuopen.com/rgp/}{Radeon GPU
570
    Profiler} can be used to gain deeper insights into the application's
571
    rendering and its performance.
572
573
    \li Overlays showing live performance information can be highly useful as well, and
574
    are often preferable to implementing simple frames-per-second counters within the
575
    application itself, since they are more reliable and show more information. An example
576
    is \l{https://game.intel.com/us/intel-presentmon/}{PresentMon}, which supports
577
    graphics hardware from multiple vendors.
578
579
    \li As QRhi supports Direct 3D 12, using
580
    \l{https://devblogs.microsoft.com/pix/download/}{PIX}, a performance tuning
581
    and debugging tool for DirectX 12 games on Windows is an option as well.
582
583
    \li On macOS,
584
    \l{https://developer.apple.com/documentation/metal/debugging_tools/viewing_your_gpu_workload_with_the_metal_debugger}{the
585
    XCode Metal debugger} can be used to take and introspect frame
586
    captures, to investigate performance details, and debug shaders. In macOS 13 it is also possible
587
    to enable an overlay that displays frame rate and other information for any Metal-based window by
588
    setting the environment variable \c{MTL_HUD_ENABLED=1}.
589
590
    \endlist
591
592
    On mobile and embedded platforms, there may be vendor and platform-specific
593
    tools, provided by the GPU or SoC vendor, available to perform performance
594
    profiling of application using OpenGL ES or Vulkan.
595
596
    When capturing frames, remember that objects and groups of commands can be
597
    named via debug markers, as long as \l{QRhi::EnableDebugMarkers}{debug
598
    markers were enabled} for the QRhi, and the graphics API in use supports
599
    this. To annotate the command stream, call
600
    \l{QRhiCommandBuffer::debugMarkBegin()}{debugMarkBegin()},
601
    \l{QRhiCommandBuffer::debugMarkEnd()}{debugMarkEnd()} and/or
602
    \l{QRhiCommandBuffer::debugMarkMsg()}{debugMarkMsg()}.
603
    This can be particularly useful in larger frames with multiple render passes.
604
    Resources are named by calling \l{QRhiResource::setName()}{setName()} before create().
605
606
    To perform basic timing measurements on the CPU and GPU side within the
607
    application, \l QElapsedTimer and
608
    \l QRhiCommandBuffer::lastCompletedGpuTime() can be used. The latter is
609
    only available with select graphics APIs at the moment and requires opting
610
    in via the \l QRhi::EnableTimestamps flag.
611
612
    \section2 Resource leak checking
613
614
    When destroying a QRhi object without properly destroying all buffers,
615
    textures, and other resources created from it, warnings about this are
616
    printed to the debug output whenever the application is a debug build, or
617
    when the \c QT_RHI_LEAK_CHECK environment variable is set to a non-zero
618
    value. This is a simple way to discover design issues around resource
619
    handling within the application rendering logic. Note however that some
620
    platforms and underlying graphics APIs may perform their own allocation and
621
    resource leak detection as well, over which Qt will have no direct control.
622
    For example, when using Vulkan, the memory allocator may raise failing
623
    assertions in debug builds when resources that own graphics memory
624
    allocations are not destroyed before the QRhi. In addition, the Vulkan
625
    validation layer, when enabled, will issue warnings about native graphics
626
    resources that were not released. Similarly, with Direct 3D warnings may
627
    get printed about unreleased COM objects when the application does not
628
    destroy the QRhi and its resources in the correct order.
629
630
    \sa {RHI Window Example}, QRhiCommandBuffer, QRhiResourceUpdateBatch,
631
    QRhiShaderResourceBindings, QShader, QRhiBuffer, QRhiTexture,
632
    QRhiRenderBuffer, QRhiSampler, QRhiTextureRenderTarget,
633
    QRhiGraphicsPipeline, QRhiComputePipeline, QRhiSwapChain
634
 */
635
636
/*!
637
    \enum QRhi::Implementation
638
    Describes which graphics API-specific backend gets used by a QRhi instance.
639
640
    \value Null
641
    \value Vulkan
642
    \value OpenGLES2
643
    \value D3D11
644
    \value D3D12
645
    \value Metal
646
 */
647
648
/*!
649
    \enum QRhi::Flag
650
    Describes what special features to enable.
651
652
    \value EnableDebugMarkers Enables debug marker groups. Without this frame
653
    debugging features like making debug groups and custom resource name
654
    visible in external GPU debugging tools will not be available and functions
655
    like QRhiCommandBuffer::debugMarkBegin() will become no-ops. Avoid enabling
656
    in production builds as it may involve a small performance impact. Has no
657
    effect when the QRhi::DebugMarkers feature is not reported as supported.
658
659
    \value EnableTimestamps Enables GPU timestamp collection. When not set,
660
    QRhiCommandBuffer::lastCompletedGpuTime() always returns 0. Enable this
661
    only when needed since there may be a small amount of extra work involved
662
    (e.g. timestamp queries), depending on the underlying graphics API. Has no
663
    effect when the QRhi::Timestamps feature is not reported as supported.
664
665
    \value PreferSoftwareRenderer Indicates that backends should prefer
666
    choosing an adapter or physical device that renders in software on the CPU.
667
    For example, with Direct3D there is typically a "Basic Render Driver"
668
    adapter available with \c{DXGI_ADAPTER_FLAG_SOFTWARE}. Setting this flag
669
    requests the backend to choose that adapter over any other, as long as no
670
    specific adapter was forced by other backend-specific means. With Vulkan
671
    this maps to preferring physical devices with
672
    \c{VK_PHYSICAL_DEVICE_TYPE_CPU}. When not available, or when it is not
673
    possible to decide if an adapter/device is software-based, this flag is
674
    ignored. It may also be ignored with graphics APIs that have no concept and
675
    means of enumerating adapters/devices.
676
677
    \value EnablePipelineCacheDataSave Enables retrieving the pipeline cache
678
    contents, where applicable. When not set, pipelineCacheData() will return
679
    an empty blob always. With backends where retrieving and restoring the
680
    pipeline cache contents is not supported, the flag has no effect and the
681
    serialized cache data is always empty. The flag provides an opt-in
682
    mechanism because the cost of maintaining the related data structures is
683
    not insignificant with some backends. With Vulkan this feature maps
684
    directly to VkPipelineCache, vkGetPipelineCacheData and
685
    VkPipelineCacheCreateInfo::pInitialData. With Direct3D 11 there is no real
686
    pipline cache, but the results of HLSL->DXBC compilations are stored and
687
    can be serialized/deserialized via this mechanism. This allows skipping the
688
    time consuming D3DCompile() in future runs of the applications for shaders
689
    that come with HLSL source instead of offline pre-compiled bytecode. This
690
    can provide a huge boost in startup and load times, if there is a lot of
691
    HLSL source compilation happening. With OpenGL the "pipeline cache" is
692
    simulated by retrieving and loading shader program binaries (if supported
693
    by the driver). With OpenGL there are additional, disk-based caching
694
    mechanisms for shader/program binaries provided by Qt. Writing to those may
695
    get disabled whenever this flag is set since storing program binaries to
696
    multiple caches is not sensible.
697
698
    \value SuppressSmokeTestWarnings Indicates that, with backends where this
699
    is relevant, certain, non-fatal QRhi::create() failures should not
700
    produce qWarning() calls. For example, with D3D11, passing this flag
701
    makes a number of warning messages (that appear due to QRhi::create()
702
    failing) to become categorized debug prints instead under the commonly used
703
    \c{qt.rhi.general} logging category. This can be used by engines, such as
704
    Qt Quick, that feature fallback logic, i.e. they retry calling create()
705
    with a different set of flags (such as, \l PreferSoftwareRenderer), in order
706
    to hide the unconditional warnings from the output that would be printed
707
    when the first create() attempt had failed.
708
 */
709
710
/*!
711
    \enum QRhi::FrameOpResult
712
    Describes the result of operations that can have a soft failure.
713
714
    \value FrameOpSuccess Success
715
716
    \value FrameOpError Unspecified error
717
718
    \value FrameOpSwapChainOutOfDate The swapchain is in an inconsistent state
719
    internally. This can be recoverable by attempting to repeat the operation
720
    (such as, beginFrame()) later.
721
722
    \value FrameOpDeviceLost The graphics device was lost. This can be
723
    recoverable by attempting to repeat the operation (such as, beginFrame())
724
    after releasing and reinitializing all objects backed by native graphics
725
    resources. See isDeviceLost().
726
 */
727
728
/*!
729
    \enum QRhi::Feature
730
    Flag values to indicate what features are supported by the backend currently in use.
731
732
    \value MultisampleTexture Indicates that textures with a sample count larger
733
    than 1 are supported. In practice this feature will be unsupported with
734
    OpenGL ES versions older than 3.1, and OpenGL older than 3.0.
735
736
    \value MultisampleRenderBuffer Indicates that renderbuffers with a sample
737
    count larger than 1 are supported. In practice this feature will be
738
    unsupported with OpenGL ES 2.0, and may also be unsupported with OpenGL 2.x
739
    unless the relevant extensions are present.
740
741
    \value DebugMarkers Indicates that debug marker groups (and so
742
    QRhiCommandBuffer::debugMarkBegin()) are supported.
743
744
    \value Timestamps Indicates that command buffer timestamps are supported.
745
    Relevant for QRhiCommandBuffer::lastCompletedGpuTime(). This can be
746
    expected to be supported on Metal, Vulkan, Direct 3D 11 and 12, and OpenGL
747
    contexts of version 3.3 or newer. However, with some of these APIs support
748
    for timestamp queries is technically optional, and therefore it cannot be
749
    guaranteed that this feature is always supported with every implementation
750
    of them.
751
752
    \value Instancing Indicates that instanced drawing is supported. In
753
    practice this feature will be unsupported with OpenGL ES 2.0 and OpenGL
754
    3.2 or older.
755
756
    \value CustomInstanceStepRate Indicates that instance step rates other
757
    than 1 are supported. In practice this feature will always be unsupported
758
    with OpenGL. In addition, running with Vulkan 1.0 without
759
    VK_EXT_vertex_attribute_divisor will also lead to reporting false for this
760
    feature.
761
762
    \value PrimitiveRestart Indicates that restarting the assembly of
763
    primitives when encountering an index value of 0xFFFF
764
    (\l{QRhiCommandBuffer::IndexUInt16}{IndexUInt16}) or 0xFFFFFFFF
765
    (\l{QRhiCommandBuffer::IndexUInt32}{IndexUInt32}) is enabled, for certain
766
    primitive topologies at least. QRhi will try to enable this with all
767
    backends, but in some cases it will not be supported. Dynamically
768
    controlling primitive restart is not possible since with some APIs
769
    primitive restart with a fixed index is always on. Applications must assume
770
    that whenever this feature is reported as supported, the above mentioned
771
    index values \c may be treated specially, depending on the topology. The
772
    only two topologies where primitive restart is guaranteed to behave
773
    identically across backends, as long as this feature is reported as
774
    supported, are \l{QRhiGraphicsPipeline::LineStrip}{LineStrip} and
775
    \l{QRhiGraphicsPipeline::TriangleStrip}{TriangleStrip}.
776
777
    \value NonDynamicUniformBuffers Indicates that creating buffers with the
778
    usage \l{QRhiBuffer::UniformBuffer}{UniformBuffer} and the types
779
    \l{QRhiBuffer::Immutable}{Immutable} or \l{QRhiBuffer::Static}{Static} is
780
    supported. When reported as unsupported, uniform (constant) buffers must be
781
    created as \l{QRhiBuffer::Dynamic}{Dynamic}. (which is recommended
782
    regardless)
783
784
    \value NonFourAlignedEffectiveIndexBufferOffset Indicates that effective
785
    index buffer offsets (\c{indexOffset + firstIndex * indexComponentSize})
786
    that are not 4 byte aligned are supported. When not supported, attempting
787
    to issue a \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} with a
788
    non-aligned effective offset may lead to unspecified behavior. Relevant in
789
    particular for Metal, where this will be reported as unsupported.
790
791
    \value NPOTTextureRepeat Indicates that the
792
    \l{QRhiSampler::Repeat}{Repeat} wrap mode and mipmap filtering modes are
793
    supported for textures with a non-power-of-two size. In practice this can
794
    only be false with OpenGL ES 2.0 implementations without
795
    \c{GL_OES_texture_npot}.
796
797
    \value RedOrAlpha8IsRed Indicates that the
798
    \l{QRhiTexture::RED_OR_ALPHA8}{RED_OR_ALPHA8} format maps to a one
799
    component 8-bit \c red format. This is the case for all backends except
800
    OpenGL when using either OpenGL ES or a non-core profile context. There
801
    \c{GL_ALPHA}, a one component 8-bit \c alpha format, is used
802
    instead. Using the special texture format allows having a single code
803
    path for creating textures, leaving it up to the backend to decide the
804
    actual format, while the feature flag can be used to pick the
805
    appropriate shader variant for sampling the texture.
806
807
    \value ElementIndexUint Indicates that 32-bit unsigned integer elements are
808
    supported in the index buffer. In practice this is true everywhere except
809
    when running on plain OpenGL ES 2.0 implementations without the necessary
810
    extension. When false, only 16-bit unsigned elements are supported in the
811
    index buffer.
812
813
    \value Compute Indicates that compute shaders, image load/store, and
814
    storage buffers are supported. OpenGL older than 4.3 and OpenGL ES older
815
    than 3.1 have no compute support.
816
817
    \value WideLines Indicates that lines with a width other than 1 are
818
    supported. When reported as not supported, the line width set on the
819
    graphics pipeline state is ignored. This can always be false with some
820
    backends (D3D11, D3D12, Metal). With Vulkan, the value depends on the
821
    implementation. With OpenGL, wide lines are not supported in core profile
822
    contexts.
823
824
    \value VertexShaderPointSize Indicates that the size of rasterized points
825
    set via \c{gl_PointSize} in the vertex shader is taken into account. When
826
    reported as not supported, drawing points with a size other than 1 is not
827
    supported. Setting \c{gl_PointSize} in the shader is still valid then, but
828
    is ignored. (for example, when generating HLSL, the assignment is silently
829
    dropped from the generated code) Note that some APIs (Metal, Vulkan)
830
    require the point size to be set in the shader explicitly whenever drawing
831
    points, even when the size is 1, as they do not automatically default to 1.
832
833
    \value BaseVertex Indicates that
834
    \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} supports the \c
835
    vertexOffset argument. When reported as not supported, the vertexOffset
836
    value in an indexed draw is ignored. In practice this feature will be
837
    unsupported with OpenGL and OpenGL ES versions lower than 3.2, and with
838
    Metal on older iOS devices, including the iOS Simulator.
839
840
    \value BaseInstance Indicates that instanced draw commands support the \c
841
    firstInstance argument. When reported as not supported, the firstInstance
842
    value is ignored and the instance ID starts from 0. In practice this feature
843
    will be unsupported with Metal on older iOS devices, including the iOS
844
    Simulator, and all versions of OpenGL. The latter is due to OpenGL ES not
845
    supporting draw calls with a base instance at all. Currently QRhi's OpenGL
846
    backend does not implement the functionality for OpenGL (non-ES) either,
847
    because portable applications cannot rely on a non-zero base instance in
848
    practice due to GLES. If the application still chooses to do so, it should
849
    be aware of the InstanceIndexIncludesBaseInstance feature as well.
850
851
    \value TriangleFanTopology Indicates that QRhiGraphicsPipeline::setTopology()
852
    supports QRhiGraphicsPipeline::TriangleFan. In practice this feature will be
853
    unsupported with Metal and Direct 3D 11/12.
854
855
    \value ReadBackNonUniformBuffer Indicates that
856
    \l{QRhiResourceUpdateBatch::readBackBuffer()}{reading buffer contents} is
857
    supported for QRhiBuffer instances with a usage different than
858
    UniformBuffer. In practice this feature will be unsupported with OpenGL ES
859
    2.0.
860
861
    \value ReadBackNonBaseMipLevel Indicates that specifying a mip level other
862
    than 0 is supported when reading back texture contents. When not supported,
863
    specifying a non-zero level in QRhiReadbackDescription leads to returning
864
    an all-zero image. In practice this feature will be unsupported with OpenGL
865
    ES 2.0.
866
867
    \value TexelFetch Indicates that texelFetch() and textureLod() are available
868
    in shaders. In practice this will be reported as unsupported with OpenGL ES
869
    2.0 and OpenGL 2.x contexts, because GLSL 100 es and versions before 130 do
870
    not support these functions.
871
872
    \value RenderToNonBaseMipLevel Indicates that specifying a mip level other
873
    than 0 is supported when creating a QRhiTextureRenderTarget with a
874
    QRhiTexture as its color attachment. When not supported, create() will fail
875
    whenever the target mip level is not zero. In practice this feature will be
876
    unsupported with OpenGL ES 2.0.
877
878
    \value IntAttributes Indicates that specifying input attributes with
879
    signed and unsigned integer types for a shader pipeline is supported. When
880
    not supported,
881
    \l{QRhiGraphicsPipeline::create()}{QRhiGraphicsPipeline::create()} will
882
    succeed but show a warning message and the values of the target attributes
883
    will be broken. In practice this feature will be unsupported with OpenGL ES
884
    2.0 and OpenGL 2.x.
885
886
    \value ScreenSpaceDerivatives Indicates that functions such as dFdx(),
887
    dFdy(), and fwidth() are supported in shaders. In practice this feature will
888
    be unsupported with OpenGL ES 2.0 without the GL_OES_standard_derivatives
889
    extension.
890
891
    \value ReadBackAnyTextureFormat Indicates that reading back texture
892
    contents can be expected to work for any QRhiTexture::Format. Backends
893
    other than OpenGL can be expected to return true for this feature. When
894
    reported as false, which will typically happen with OpenGL, only the
895
    formats QRhiTexture::RGBA8 and QRhiTexture::BGRA8 are guaranteed to be
896
    supported for readbacks. In addition, with OpenGL, but not OpenGL ES,
897
    reading back the 1 byte per component formats QRhiTexture::R8 and
898
    QRhiTexture::RED_OR_ALPHA8 are supported as well. Reading back floating
899
    point formats QRhiTexture::RGBA16F and RGBA32F may work too with OpenGL, as
900
    long as the implementation provides support for these, but QRhi can give no
901
    guarantees, as indicated by this flag.
902
903
    \value PipelineCacheDataLoadSave Indicates that the pipelineCacheData() and
904
    setPipelineCacheData() functions are functional. When not supported, the
905
    functions will not perform any action, the retrieved blob is always empty,
906
    and thus no benefits can be expected from retrieving and, during a
907
    subsequent run of the application, reloading the pipeline cache content.
908
909
    \value ImageDataStride Indicates that specifying a custom stride (row
910
    length) for raw image data in texture uploads is supported. When not
911
    supported (which can happen when the underlying API is OpenGL ES 2.0 without
912
    support for GL_UNPACK_ROW_LENGTH),
913
    QRhiTextureSubresourceUploadDescription::setDataStride() must not be used.
914
915
    \value RenderBufferImport Indicates that QRhiRenderBuffer::createFrom() is
916
    supported. For most graphics APIs this is not sensible because
917
    QRhiRenderBuffer encapsulates texture objects internally, just like
918
    QRhiTexture. With OpenGL however, renderbuffer object exist as a separate
919
    object type in the API, and in certain environments (for example, where one
920
    may want to associated a renderbuffer object with an EGLImage object) it is
921
    important to allow wrapping an existing OpenGL renderbuffer object with a
922
    QRhiRenderBuffer.
923
924
    \value ThreeDimensionalTextures Indicates that 3D textures are supported.
925
    In practice this feature will be unsupported with OpenGL and OpenGL ES
926
    versions lower than 3.0.
927
928
    \value RenderTo3DTextureSlice Indicates that rendering to a slice in a 3D
929
    texture is supported. This can be unsupported with Vulkan 1.0 due to
930
    relying on VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT which is a Vulkan 1.1
931
    feature.
932
933
    \value TextureArrays Indicates that texture arrays are supported and
934
    QRhi::newTextureArray() is functional. Note that even when texture arrays
935
    are not supported, arrays of textures are still available as those are two
936
    independent features.
937
938
    \value Tessellation Indicates that the tessellation control and evaluation
939
    stages are supported. When reported as supported, the topology of a
940
    QRhiGraphicsPipeline can be set to
941
    \l{QRhiGraphicsPipeline::Patches}{Patches}, the number of control points
942
    can be set via
943
    \l{QRhiGraphicsPipeline::setPatchControlPointCount()}{setPatchControlPointCount()},
944
    and shaders for tessellation control and evaluation can be specified in the
945
    QRhiShaderStage list. Tessellation shaders have portability issues between
946
    APIs (for example, translating GLSL/SPIR-V to HLSL is problematic due to
947
    the way hull shaders are structured, whereas Metal uses a somewhat
948
    different tessellation pipeline than others), and therefore unexpected
949
    issues may still arise, even though basic functionality is implemented
950
    across all the underlying APIs. For Direct 3D in particular, handwritten
951
    HLSL hull and domain shaders must be injected into each QShader for the
952
    tessellation control and evaluation stages, respectively, since qsb cannot
953
    generate these from SPIR-V. Note that isoline tessellation should be
954
    avoided as it will not be supported by all backends. The maximum patch
955
    control point count portable between backends is 32.
956
957
    \value GeometryShader Indicates that the geometry shader stage is supported.
958
    When supported, a geometry shader can be specified in the QRhiShaderStage
959
    list. Geometry Shaders are considered an experimental feature in QRhi and
960
    can only be expected to be supported with Vulkan, Direct 3D 11 and 12,
961
    OpenGL (3.2+) and OpenGL ES (3.2+), assuming the implementation reports it
962
    as supported at run time. Starting with Qt 6.11 geometry shaders are
963
    automatically translated to HLSL, and therefore no injection of handwritten
964
    HLSL geometry shaders is necessary anymore (but note that gl_in and
965
    expressions such as gl_in[0].gl_Position are not supported; rather, pass the
966
    position as an output variable from the vertex shader). Geometry shaders are
967
    not supported with Metal.
968
969
    \value TextureArrayRange Indicates that for
970
    \l{QRhi::newTextureArray()}{texture arrays} it is possible to specify a
971
    range that is exposed to the shaders. Normally all array layers are exposed
972
    and it is up to the shader to select the layer (via the third coordinate
973
    passed to texture() when sampling the \c sampler2DArray). When supported,
974
    calling QRhiTexture::setArrayRangeStart() and
975
    QRhiTexture::setArrayRangeLength() before
976
    \l{QRhiTexture::create()}{building} or
977
    \l{QRhiTexture::createFrom()}{importing} the native texture has an effect,
978
    and leads to selecting only the specified range from the array. This will
979
    be necessary in special cases, such as when working with accelerated video
980
    decoding and Direct 3D 11, because a texture array with both
981
    \c{D3D11_BIND_DECODER} and \c{D3D11_BIND_SHADER_RESOURCE} on it is only
982
    usable as a shader resource if a single array layer is selected. Note that
983
    all this is applicable only when the texture is used as a
984
    QRhiShaderResourceBinding::SampledTexture or
985
    QRhiShaderResourceBinding::Texture shader resource, and is not compatible
986
    with image load/store. This feature is only available with some backends as
987
    it does not map well to all graphics APIs, and it is only meant to provide
988
    support for special cases anyhow. In practice the feature can be expected to
989
    be supported with Direct3D 11/12 and Vulkan.
990
991
    \value NonFillPolygonMode Indicates that setting a PolygonMode other than
992
    the default Fill is supported for QRhiGraphicsPipeline. A common use case
993
    for changing the mode to Line is to get wireframe rendering. This however
994
    is not available as a core OpenGL ES feature, and is optional with Vulkan
995
    as well as some mobile GPUs may not offer the feature.
996
997
    \value OneDimensionalTextures Indicates that 1D textures are supported.
998
    In practice this feature will be unsupported on OpenGL ES.
999
1000
    \value OneDimensionalTextureMipmaps Indicates that generating 1D texture
1001
    mipmaps is supported. In practice this feature will be unsupported on
1002
    backends that do not report support for
1003
    \l{OneDimensionalTextures}, Metal, and Direct 3D 12.
1004
1005
    \value HalfAttributes Indicates that specifying input attributes with half
1006
    precision (16bit) floating point types for a shader pipeline is supported.
1007
    When not supported,
1008
    \l{QRhiGraphicsPipeline::create()}{QRhiGraphicsPipeline::create()} will
1009
    succeed but show a warning message and the values of the target attributes
1010
    will be broken. In practice this feature will be unsupported in some OpenGL
1011
    ES 2.0 and OpenGL 2.x
1012
    implementations. Note that while Direct3D 11/12 does support half precision
1013
    input attributes, it does not support the half3 type. The D3D backends pass
1014
    half3 attributes as half4. To ensure cross platform compatibility, half3
1015
    inputs should be padded to 8 bytes.
1016
1017
    \value RenderToOneDimensionalTexture Indicates that 1D texture render
1018
    targets are supported. In practice this feature will be unsupported on
1019
    backends that do not report support for
1020
    \l{OneDimensionalTextures}, and Metal.
1021
1022
    \value ThreeDimensionalTextureMipmaps Indicates that generating 3D texture
1023
    mipmaps is supported. This is typically supported with all backends starting
1024
    with Qt 6.10.
1025
1026
    \value MultiView Indicates that multiview, see e.g.
1027
    \l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_multiview.html}{VK_KHR_multiview}
1028
    is supported. With OpenGL ES 2.0, Direct 3D 11, and OpenGL (ES)
1029
    implementations without \c{GL_OVR_multiview2} this feature will not be
1030
    supported. With Vulkan 1.1 and newer, and Direct 3D 12 multiview is
1031
    typically supported. When reported as supported, creating a
1032
    QRhiTextureRenderTarget with a QRhiColorAttachment that references a texture
1033
    array and has \l{QRhiColorAttachment::setMultiViewCount()}{multiViewCount}
1034
    set enables recording a render pass that uses multiview rendering. In addition,
1035
    any QRhiGraphicsPipeline used in that render pass must have
1036
    \l{QRhiGraphicsPipeline::setMultiViewCount()}{the same view count set}. Note that
1037
    multiview is only available in combination with 2D texture arrays. It cannot
1038
    be used to optimize the rendering into individual textures (e.g. two, for
1039
    the left and right eyes). Rather, the target of a multiview render pass is
1040
    always a texture array, automatically rendering to the layer (array element)
1041
    corresponding to each view. Therefore this feature implies \l TextureArrays
1042
    as well. Multiview rendering is not supported in combination with
1043
    tessellation or geometry shaders. See QRhiColorAttachment::setMultiViewCount()
1044
    for further details on multiview rendering. This enum value has been introduced in Qt 6.7.
1045
1046
    \value TextureViewFormat Indicates that setting a
1047
    \l{QRhiTexture::setWriteViewFormat()}{view format} on a QRhiTexture is
1048
    effective. When reported as supported, setting the read (sampling) or write
1049
    (render target / image load-store) view mode changes the texture's viewing
1050
    format. When unsupported, setting a view format has no effect. Note that Qt
1051
    has no knowledge or control over format compatibility or resource view rules
1052
    in the underlying 3D API and its implementation. Passing in unsuitable,
1053
    incompatible formats may lead to errors and unspecified behavior. This is
1054
    provided mainly to allow "casting" rendering into a texture created with an
1055
    sRGB format to non-sRGB to avoid the unwanted linear->sRGB conversion on
1056
    shader writes. Other types of casting may or may not be functional,
1057
    depending on the underlying API. Currently implemented for Vulkan and Direct
1058
    3D 12. With D3D12 the feature is available only if
1059
    \c CastingFullyTypedFormatSupported is supported, see
1060
    \l{https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html} (and
1061
    note that QRhi always uses fully typed formats for textures.) This enum
1062
    value has been introduced in Qt 6.8.
1063
1064
    \value ResolveDepthStencil Indicates that resolving a multisample depth or
1065
    depth-stencil texture is supported. Otherwise,
1066
    \l{QRhiTextureRenderTargetDescription::setDepthResolveTexture()}{setting a
1067
    depth resolve texture} is not functional and must be avoided. Direct 3D 11
1068
    and 12 have no support for resolving depth/depth-stencil formats, and
1069
    therefore this feature will never be supported with those. Vulkan 1.0 has no
1070
    API to request resolving a depth-stencil attachment. Therefore, with Vulkan
1071
    this feature will only be supported with Vulkan 1.2 and up, and on 1.1
1072
    implementations with the appropriate extensions present. This feature is
1073
    provided for the rare case when resolving into a non-multisample depth
1074
    texture becomes necessary, for example when rendering into an
1075
    OpenXR-provided depth texture (XR_KHR_composition_layer_depth). This enum
1076
    value has been introduced in Qt 6.8.
1077
1078
    \value VariableRateShading Indicates that per-draw (per-pipeline) variable
1079
    rate shading is supported. When reported as supported, \l
1080
    QRhiCommandBuffer::setShadingRate() is functional and has an effect for
1081
    QRhiGraphicsPipeline objects that declared \l
1082
    QRhiGraphicsPipeline::UsesShadingRate in their flags. Call \l
1083
    QRhi::supportedShadingRates() to check which rates are supported. (1x1 is
1084
    always supported, other typical values are 2x2, 1x2, 2x1, 2x4, 4x2, 4x4).
1085
    This feature can be expected to be supported with Direct 3D 12 and Vulkan,
1086
    assuming the implementation and GPU used at run time supports VRS. This enum
1087
    value has been introduced in Qt 6.9.
1088
1089
    \value VariableRateShadingMap Indicates that image-based specification of
1090
    the shading rate is possible. The "image" is not necessarily a texture, it
1091
    may be a native 3D API object, depending on the underlying backend and
1092
    graphics API at run time. In practice this feature can be expected to be
1093
    supported with Direct 3D 12, Vulkan, and Metal, assuming the GPU is modern
1094
    enough to support VRS. To check if D3D12/Vulkan-style image-based VRS is
1095
    supported, use VariableRateShadingMapWithTexture instead. When this feature
1096
    is reported as supported, there are two possibilities: when
1097
    VariableRateShadingMapWithTexture is also true, then QRhiShadingRateMap
1098
    consumes QRhiTexture objects via the createFrom() overload taking a
1099
    QRhiTexture argument. When VariableRateShadingMapWithTexture is false, then
1100
    QRhiShadingRateMap consumes some other type of native objects, for example
1101
    an MTLRasterizationRateMap in case of Metal. Use the createFrom() overload
1102
    taking a NativeShadingRateMap in this case. This enum value has been
1103
    introduced in Qt 6.9.
1104
1105
    \value VariableRateShadingMapWithTexture Indicates that image-based
1106
    specification of the shading rate is supported via regular textures. In
1107
    practice this may be supported with Direct 3D 12 and Vulkan. This enum value
1108
    has been introduced in Qt 6.9.
1109
1110
    \value PerRenderTargetBlending Indicates that per rendertarget blending is
1111
    supported i.e. different render targets in MRT framebuffer can have different
1112
    blending modes. In practice this can be expected to be supported everywhere
1113
    except OpenGL ES, where it is only available with GLES 3.2 implementations.
1114
    This enum value has been introduced in Qt 6.9.
1115
1116
    \value SampleVariables Indicates that gl_SampleID, gl_SamplePosition,
1117
    gl_SampleMaskIn and gl_SampleMask variables are available in fragment shaders.
1118
    In practice this can be expected to be supported everywhere except OpenGL ES,
1119
    where it is only available with GLES 3.2 implementations.
1120
    This enum value has been introduced in Qt 6.9.
1121
1122
    \value InstanceIndexIncludesBaseInstance Indicates that \c gl_InstanceIndex
1123
    includes the base instance (the \c firstInstance argument in draw calls) in
1124
    its value. When this feature is unsupported, but BaseInstance is, it
1125
    indicates that \c gl_InstanceIndex always starts at 0, not the base value.
1126
    In practice this will be the case for Direct 3D 11 and 12 at the moment.
1127
    With Vulkan and Metal this feature is expected to be reported as supported
1128
    always. This enum value has been introduced in Qt 6.11.
1129
1130
    \value [since 6.11] DepthClamp Indicates that enabling depth clamping is
1131
    supported. When reported as unsupported, which will be the case with OpenGL
1132
    ES, OpenGL versions before 3.2 without the relevant extension present, and
1133
    Metal on the iOS Simulator, calling \l{QRhiGraphicsPipeline::setDepthClamp()}
1134
    with an argument of \c true has no effect.
1135
1136
    \value [since 6.12] DrawIndirect Indicates that the
1137
    \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
1138
    and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}
1139
    functions are available.
1140
    In practice this can be expected to be supported everywhere except on
1141
    OpenGL ES < 3.1.
1142
1143
    \value [since 6.12] DrawIndirectMulti Indicates that a drawCount > 1 is natively
1144
    supported by the backend in \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
1145
    and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}.
1146
    Otherwise, multiple draw calls are issued on the CPU by the RHI.
1147
    In practice this can be expected to be supported on Vulkan 1.1+, OpenGL 4.3+
1148
    and D3D12.
1149
1150
    \value [since 6.12] ShaderDrawParameters Indicates that the \c{gl_BaseInstance},
1151
    \c{gl_BaseVertex} and \c{gl_DrawID} built-in variables are available in shaders.
1152
    In practice this can be expected to be supported on Vulkan 1.1+ and with desktop OpenGL
1153
    4.6 or \c{GL_ARB_shader_draw_parameters}.
1154
 */
1155
1156
/*!
1157
    \enum QRhi::BeginFrameFlag
1158
    Flag values for QRhi::beginFrame()
1159
 */
1160
1161
/*!
1162
    \enum QRhi::EndFrameFlag
1163
    Flag values for QRhi::endFrame()
1164
1165
    \value SkipPresent Specifies that no present command is to be queued or no
1166
    swapBuffers call is to be made. This way no image is presented. Generating
1167
    multiple frames with all having this flag set is not recommended (except,
1168
    for example, for benchmarking purposes - but keep in mind that backends may
1169
    behave differently when it comes to waiting for command completion without
1170
    presenting so the results are not comparable between them)
1171
 */
1172
1173
/*!
1174
    \enum QRhi::ResourceLimit
1175
    Describes the resource limit to query.
1176
1177
    \value TextureSizeMin Minimum texture width and height. This is typically
1178
    1. The minimum texture size is handled gracefully, meaning attempting to
1179
    create a texture with an empty size will instead create a texture with the
1180
    minimum size.
1181
1182
    \value TextureSizeMax Maximum texture width and height. This depends on the
1183
    graphics API and sometimes the platform or implementation as well.
1184
    Typically the value is in the range 4096 - 16384. Attempting to create
1185
    textures larger than this is expected to fail.
1186
1187
    \value MaxColorAttachments The maximum number of color attachments for a
1188
    QRhiTextureRenderTarget, in case multiple render targets are supported. When
1189
    MRT is not supported, the value is 1. Otherwise this is typically 8, but
1190
    watch out for the fact that OpenGL only mandates 4 as the minimum, and that
1191
    is what some OpenGL ES implementations provide.
1192
1193
    \value FramesInFlight The number of frames the backend may keep "in
1194
    flight": with backends like Vulkan or Metal, it is the responsibility of
1195
    QRhi to block whenever starting a new frame and finding the CPU is already
1196
    \c{N - 1} frames ahead of the GPU (because the command buffer submitted in
1197
    frame no. \c{current} - \c{N} has not yet completed). The value N is what
1198
    is returned from here, and is typically 2. This can be relevant to
1199
    applications that integrate rendering done directly with the graphics API,
1200
    as such rendering code may want to perform double (if the value is 2)
1201
    buffering for resources, such as, buffers, similarly to the QRhi backends
1202
    themselves. The current frame slot index (a value running 0, 1, .., N-1,
1203
    then wrapping around) is retrievable from QRhi::currentFrameSlot(). The
1204
    value is 1 for backends where the graphics API offers no such low level
1205
    control over the command submission process. Note that pipelining may still
1206
    happen even when this value is 1 (some backends, such as D3D11, are
1207
    designed to attempt to enable this, for instance, by using an update
1208
    strategy for uniform buffers that does not stall the pipeline), but that is
1209
    then not controlled by QRhi and so not reflected here in the API.
1210
1211
    \value MaxAsyncReadbackFrames The number of \l{QRhi::endFrame()}{submitted}
1212
    frames (including the one that contains the readback) after which an
1213
    asynchronous texture or buffer readback is guaranteed to complete upon
1214
    \l{QRhi::beginFrame()}{starting a new frame}.
1215
1216
    \value MaxThreadGroupsPerDimension The maximum number of compute
1217
    work/thread groups that can be dispatched. Effectively the maximum value
1218
    for the arguments of QRhiCommandBuffer::dispatch(). Typically 65535.
1219
1220
    \value MaxThreadsPerThreadGroup The maximum number of invocations in a
1221
    single local work group, or in other terminology, the maximum number of
1222
    threads in a thread group. Effectively the maximum value for the product of
1223
    \c local_size_x, \c local_size_y, and \c local_size_z in the compute
1224
    shader. Typical values are 128, 256, 512, 1024, or 1536. Watch out that
1225
    both OpenGL ES and Vulkan specify only 128 as the minimum required limit
1226
    for implementations. While uncommon for Vulkan, some OpenGL ES 3.1
1227
    implementations for mobile/embedded devices only support the spec-mandated
1228
    minimum value.
1229
1230
    \value MaxThreadGroupX The maximum size of a work/thread group in the X
1231
    dimension. Effectively the maximum value of \c local_size_x in the compute
1232
    shader. Typically 256 or 1024.
1233
1234
    \value MaxThreadGroupY The maximum size of a work/thread group in the Y
1235
    dimension. Effectively the maximum value of \c local_size_y in the compute
1236
    shader. Typically 256 or 1024.
1237
1238
    \value MaxThreadGroupZ The maximum size of a work/thread group in the Z
1239
    dimension. Effectively the maximum value of \c local_size_z in the compute
1240
    shader. Typically 64 or 256.
1241
1242
    \value TextureArraySizeMax Maximum texture array size. Typically in range
1243
    256 - 2048. Attempting to \l{QRhi::newTextureArray()}{create a texture
1244
    array} with more elements will likely fail.
1245
1246
    \value MaxUniformBufferRange The number of bytes that can be exposed from a
1247
    uniform buffer to the shaders at once. On OpenGL ES 2.0 and 3.0
1248
    implementations this may be as low as 3584 bytes (224 four component, 32
1249
    bits per component vectors). Elsewhere the value is typically 16384 (1024
1250
    vec4s) or 65536 (4096 vec4s).
1251
1252
    \value MaxVertexInputs The number of input attributes to the vertex shader.
1253
    The location in a QRhiVertexInputAttribute must be in range \c{[0,
1254
    MaxVertexInputs-1]}. The value may be as low as 8 with OpenGL ES 2.0.
1255
    Elsewhere, typical values are 16, 31, or 32.
1256
1257
    \value MaxVertexOutputs The maximum number of outputs (4 component vector
1258
    \c out variables) from the vertex shader. The value may be as low as 8 with
1259
    OpenGL ES 2.0, and 15 with OpenGL ES 3.0 and some Metal devices. Elsewhere,
1260
    a typical value is 32.
1261
1262
    \value ShadingRateImageTileSize The tile size for shading rate textures. 0
1263
    if the QRhi::VariableRateShadingMapWithTexture feature is not supported.
1264
    Otherwise a value such as 16, indicating, for example, a tile size of 16x16.
1265
    Each byte in the (R8UI) shading rate texture defines then the shading rate
1266
    for a tile of 16x16 pixels. See \l QRhiShadingRateMap for details.
1267
1268
    \value [since 6.13] MaxVertexStorageBuffers The maximum number of
1269
    storage buffers that can be bound for reading (bufferLoad) in the
1270
    vertex stage. Can legitimately be 0: OpenGL ES makes vertex-stage
1271
    storage blocks optional even on 3.1 and newer, and many mobile
1272
    drivers report 0 while supporting them via Vulkan on the same GPU;
1273
    Direct 3D 11 has no vertex-stage storage buffer support at all.
1274
    Clients reading storage buffers in the vertex shader must therefore
1275
    check this even when QRhi::Compute is supported. Write access can be
1276
    more restricted than this value suggests: with Vulkan it additionally
1277
    requires the vertexPipelineStoresAndAtomics device feature, and with
1278
    Direct 3D 12 unordered access has lower, resource-binding-tier
1279
    dependent limits. With Metal the value is the size of the buffer
1280
    argument table, which is shared with vertex inputs and uniform
1281
    buffers, so the full count is not available in combination with them.
1282
1283
    \value [since 6.13] MaxFragmentStorageBuffers The maximum number of
1284
    storage buffers that can be bound for reading (bufferLoad) in the
1285
    fragment stage. Like the vertex stage, this is optional in OpenGL ES
1286
    (only compute-stage storage blocks are mandatory), so 0 is a
1287
    legitimate value. The write access and Metal argument table notes
1288
    from MaxVertexStorageBuffers apply here as well; with Direct 3D 11
1289
    the value reflects the unordered access view slots, which are shared
1290
    with render target outputs.
1291
 */
1292
1293
/*!
1294
    \class QRhiInitParams
1295
    \inmodule QtGuiPrivate
1296
    \inheaderfile rhi/qrhi.h
1297
    \since 6.6
1298
    \brief Base class for backend-specific initialization parameters.
1299
1300
    Contains fields that are relevant to all backends.
1301
1302
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1303
    for details.
1304
 */
1305
1306
/*!
1307
    \class QRhiDepthStencilClearValue
1308
    \inmodule QtGuiPrivate
1309
    \inheaderfile rhi/qrhi.h
1310
    \since 6.6
1311
    \brief Specifies clear values for a depth or stencil buffer.
1312
1313
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1314
    for details.
1315
 */
1316
1317
/*!
1318
    \fn QRhiDepthStencilClearValue::QRhiDepthStencilClearValue() = default
1319
1320
    Constructs a depth/stencil clear value with depth clear value 1.0f and
1321
    stencil clear value 0.
1322
 */
1323
1324
/*!
1325
    Constructs a depth/stencil clear value with depth clear value \a d and
1326
    stencil clear value \a s.
1327
 */
1328
QRhiDepthStencilClearValue::QRhiDepthStencilClearValue(float d, quint32 s)
1329
0
    : m_d(d),
1330
0
      m_s(s)
1331
0
{
1332
0
}
1333
1334
/*!
1335
    \fn float QRhiDepthStencilClearValue::depthClearValue() const
1336
    \return the depth clear value. In most cases this is 1.0f.
1337
 */
1338
1339
/*!
1340
    \fn void QRhiDepthStencilClearValue::setDepthClearValue(float d)
1341
    Sets the depth clear value to \a d.
1342
 */
1343
1344
/*!
1345
    \fn quint32 QRhiDepthStencilClearValue::stencilClearValue() const
1346
    \return the stencil clear value. In most cases this is 0.
1347
 */
1348
1349
/*!
1350
    \fn void QRhiDepthStencilClearValue::setStencilClearValue(quint32 s)
1351
    Sets the stencil clear value to \a s.
1352
 */
1353
1354
/*!
1355
    \fn bool QRhiDepthStencilClearValue::operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1356
1357
    \return \c true if the values in the two QRhiDepthStencilClearValue objects
1358
    \a a and \a b are equal.
1359
 */
1360
1361
/*!
1362
    \fn bool QRhiDepthStencilClearValue::operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
1363
1364
    \return \c false if the values in the two QRhiDepthStencilClearValue
1365
    objects \a a and \a b are equal; otherwise returns \c true.
1366
1367
*/
1368
1369
/*!
1370
    \fn size_t QRhiDepthStencilClearValue::qHash(const QRhiDepthStencilClearValue &key, size_t seed)
1371
    \qhash{QRhiDepthStencilClearValue}
1372
 */
1373
1374
#ifndef QT_NO_DEBUG_STREAM
1375
QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
1376
0
{
1377
0
    QDebugStateSaver saver(dbg);
1378
0
    dbg.nospace() << "QRhiDepthStencilClearValue(depth-clear=" << v.depthClearValue()
1379
0
                  << " stencil-clear=" << v.stencilClearValue()
1380
0
                  << ')';
1381
0
    return dbg;
1382
0
}
1383
#endif
1384
1385
/*!
1386
    \class QRhiViewport
1387
    \inmodule QtGuiPrivate
1388
    \inheaderfile rhi/qrhi.h
1389
    \since 6.6
1390
    \brief Specifies a viewport rectangle.
1391
1392
    Used with QRhiCommandBuffer::setViewport().
1393
1394
    QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
1395
    bottom-left. Negative width or height are not allowed.
1396
1397
    Typical usage is like the following:
1398
1399
    \code
1400
      const QSize outputSizeInPixels = swapchain->currentPixelSize();
1401
      const QRhiViewport viewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height());
1402
      cb->beginPass(swapchain->currentFrameRenderTarget(), Qt::black, { 1.0f, 0 });
1403
      cb->setGraphicsPipeline(ps);
1404
      cb->setViewport(viewport);
1405
      // ...
1406
    \endcode
1407
1408
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1409
    for details.
1410
1411
    \sa QRhiCommandBuffer::setViewport(), QRhi::clipSpaceCorrMatrix(), QRhiScissor
1412
 */
1413
1414
/*!
1415
    \fn QRhiViewport::QRhiViewport() = default
1416
1417
    Constructs a viewport description with an empty rectangle and a depth range
1418
    of 0.0f - 1.0f.
1419
1420
    \sa QRhi::clipSpaceCorrMatrix()
1421
 */
1422
1423
/*!
1424
    Constructs a viewport description with the rectangle specified by \a x, \a
1425
    y, \a w, \a h and the depth range \a minDepth and \a maxDepth.
1426
1427
    \note \a x and \a y are assumed to be the bottom-left position. \a w and \a
1428
    h should not be negative, the viewport will be ignored by
1429
    QRhiCommandBuffer::setViewport() otherwise.
1430
1431
    \sa QRhi::clipSpaceCorrMatrix()
1432
 */
1433
QRhiViewport::QRhiViewport(float x, float y, float w, float h, float minDepth, float maxDepth)
1434
0
    : m_rect { { x, y, w, h } },
1435
0
      m_minDepth(minDepth),
1436
0
      m_maxDepth(maxDepth)
1437
0
{
1438
0
}
1439
1440
/*!
1441
    \fn std::array<float, 4> QRhiViewport::viewport() const
1442
    \return the viewport x, y, width, and height.
1443
 */
1444
1445
/*!
1446
    \fn void QRhiViewport::setViewport(float x, float y, float w, float h)
1447
    Sets the viewport's position and size to \a x, \a y, \a w, and \a h.
1448
1449
    \note Viewports are specified in a coordinate system that has its origin in
1450
    the bottom-left.
1451
 */
1452
1453
/*!
1454
    \fn float QRhiViewport::minDepth() const
1455
    \return the minDepth value of the depth range of the viewport.
1456
 */
1457
1458
/*!
1459
    \fn void QRhiViewport::setMinDepth(float minDepth)
1460
    Sets the \a minDepth of the depth range of the viewport.
1461
    By default this is set to 0.0f.
1462
 */
1463
1464
/*!
1465
    \fn float QRhiViewport::maxDepth() const
1466
    \return the maxDepth value of the depth range of the viewport.
1467
 */
1468
1469
/*!
1470
    \fn void QRhiViewport::setMaxDepth(float maxDepth)
1471
    Sets the \a maxDepth of the depth range of the viewport.
1472
    By default this is set to 1.0f.
1473
 */
1474
1475
/*!
1476
    \fn bool QRhiViewport::operator==(const QRhiViewport &a, const QRhiViewport &b) noexcept
1477
1478
    \return \c true if the values in the two QRhiViewport objects
1479
    \a a and \a b are equal.
1480
 */
1481
1482
/*!
1483
    \fn bool QRhiViewport::operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept
1484
1485
    \return \c false if the values in the two QRhiViewport
1486
    objects \a a and \a b are equal; otherwise returns \c true.
1487
*/
1488
1489
/*!
1490
    \fn size_t QRhiViewport::qHash(const QRhiViewport &key, size_t seed)
1491
    \qhash{QRhiViewport}
1492
 */
1493
1494
#ifndef QT_NO_DEBUG_STREAM
1495
QDebug operator<<(QDebug dbg, const QRhiViewport &v)
1496
0
{
1497
0
    QDebugStateSaver saver(dbg);
1498
0
    const std::array<float, 4> r = v.viewport();
1499
0
    dbg.nospace() << "QRhiViewport(bottom-left-x=" << r[0]
1500
0
                  << " bottom-left-y=" << r[1]
1501
0
                  << " width=" << r[2]
1502
0
                  << " height=" << r[3]
1503
0
                  << " minDepth=" << v.minDepth()
1504
0
                  << " maxDepth=" << v.maxDepth()
1505
0
                  << ')';
1506
0
    return dbg;
1507
0
}
1508
#endif
1509
1510
/*!
1511
    \class QRhiScissor
1512
    \inmodule QtGuiPrivate
1513
    \inheaderfile rhi/qrhi.h
1514
    \since 6.6
1515
    \brief Specifies a scissor rectangle.
1516
1517
    Used with QRhiCommandBuffer::setScissor(). Setting a scissor rectangle is
1518
    only possible with a QRhiGraphicsPipeline that has
1519
    QRhiGraphicsPipeline::UsesScissor set.
1520
1521
    QRhi assumes OpenGL-style scissor coordinates, meaning x and y are
1522
    bottom-left. Negative width or height are not allowed. However, apart from
1523
    that, the flexible OpenGL semantics apply: negative x and y, partially out
1524
    of bounds rectangles, etc. will be handled gracefully, clamping as
1525
    appropriate. Therefore, any rendering logic targeting OpenGL can feed
1526
    scissor rectangles into QRhiScissor as-is, without any adaptation.
1527
1528
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1529
    for details.
1530
1531
    \sa QRhiCommandBuffer::setScissor(), QRhiViewport
1532
 */
1533
1534
/*!
1535
    \fn QRhiScissor::QRhiScissor() = default
1536
1537
    Constructs an empty scissor.
1538
 */
1539
1540
/*!
1541
    Constructs a scissor with the rectangle specified by \a x, \a y, \a w, and
1542
    \a h.
1543
1544
    \note \a x and \a y are assumed to be the bottom-left position. Negative \a w
1545
    or \a h are not allowed, such scissor rectangles will be ignored by
1546
    QRhiCommandBuffer. Other than that, the flexible OpenGL semantics apply:
1547
    negative x and y, partially out of bounds rectangles, etc. will be handled
1548
    gracefully, clamping as appropriate.
1549
 */
1550
QRhiScissor::QRhiScissor(int x, int y, int w, int h)
1551
0
    : m_rect { { x, y, w, h } }
1552
0
{
1553
0
}
1554
1555
/*!
1556
    \fn std::array<int, 4> QRhiScissor::scissor() const
1557
    \return the scissor position and size.
1558
 */
1559
1560
/*!
1561
    \fn void QRhiScissor::setScissor(int x, int y, int w, int h)
1562
    Sets the scissor position and size to \a x, \a y, \a w, \a h.
1563
1564
    \note The position is always expected to be specified in a coordinate
1565
    system that has its origin in the bottom-left corner, like OpenGL.
1566
 */
1567
1568
/*!
1569
    \fn bool QRhiScissor::operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept
1570
1571
    \return \c true if the values in the two QRhiScissor objects
1572
    \a a and \a b are equal.
1573
 */
1574
1575
/*!
1576
    \fn bool QRhiScissor::operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept
1577
1578
    \return \c false if the values in the two QRhiScissor
1579
    objects \a a and \a b are equal; otherwise returns \c true.
1580
*/
1581
1582
/*!
1583
    \fn size_t QRhiScissor::qHash(const QRhiScissor &key, size_t seed)
1584
    \qhash{QRhiScissor}
1585
 */
1586
1587
#ifndef QT_NO_DEBUG_STREAM
1588
QDebug operator<<(QDebug dbg, const QRhiScissor &s)
1589
0
{
1590
0
    QDebugStateSaver saver(dbg);
1591
0
    const std::array<int, 4> r = s.scissor();
1592
0
    dbg.nospace() << "QRhiScissor(bottom-left-x=" << r[0]
1593
0
                  << " bottom-left-y=" << r[1]
1594
0
                  << " width=" << r[2]
1595
0
                  << " height=" << r[3]
1596
0
                  << ')';
1597
0
    return dbg;
1598
0
}
1599
#endif
1600
1601
/*!
1602
    \class QRhiVertexInputBinding
1603
    \inmodule QtGuiPrivate
1604
    \inheaderfile rhi/qrhi.h
1605
    \since 6.6
1606
    \brief Describes a vertex input binding.
1607
1608
    Specifies the stride (in bytes, must be a multiple of 4), the
1609
    classification and optionally the instance step rate.
1610
1611
    As an example, assume a vertex shader with the following inputs:
1612
1613
    \badcode
1614
        layout(location = 0) in vec4 position;
1615
        layout(location = 1) in vec2 texcoord;
1616
    \endcode
1617
1618
    Now let's assume also that 3 component vertex positions \c{(x, y, z)} and 2
1619
    component texture coordinates \c{(u, v)} are provided in a non-interleaved
1620
    format in a buffer (or separate buffers even). Defining two bindings
1621
    could then be done like this:
1622
1623
    \code
1624
        QRhiVertexInputLayout inputLayout;
1625
        inputLayout.setBindings({
1626
            { 3 * sizeof(float) },
1627
            { 2 * sizeof(float) }
1628
        });
1629
    \endcode
1630
1631
    Only the stride is interesting here since instancing is not used. The
1632
    binding number is given by the index of the QRhiVertexInputBinding
1633
    element in the bindings vector of the QRhiVertexInputLayout.
1634
1635
    Once a graphics pipeline with this vertex input layout is bound, the vertex
1636
    inputs could be set up like the following for drawing a cube with 36
1637
    vertices, assuming we have a single buffer with first the positions and
1638
    then the texture coordinates:
1639
1640
    \code
1641
        const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1642
            { cubeBuf, 0 },
1643
            { cubeBuf, 36 * 3 * sizeof(float) }
1644
        };
1645
        cb->setVertexInput(0, 2, vbufBindings);
1646
    \endcode
1647
1648
    Note how the index defined by \c {startBinding + i}, where \c i is the
1649
    index in the second argument of
1650
    \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}, matches the
1651
    index of the corresponding entry in the \c bindings vector of the
1652
    QRhiVertexInputLayout.
1653
1654
    \note the stride must always be a multiple of 4.
1655
1656
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1657
    for details.
1658
1659
    \sa QRhiCommandBuffer::setVertexInput()
1660
 */
1661
1662
/*!
1663
    \enum QRhiVertexInputBinding::Classification
1664
    Describes the input data classification.
1665
1666
    \value PerVertex Data is per-vertex
1667
    \value PerInstance Data is per-instance
1668
 */
1669
1670
/*!
1671
    \fn QRhiVertexInputBinding::QRhiVertexInputBinding() = default
1672
1673
    Constructs a default vertex input binding description.
1674
 */
1675
1676
/*!
1677
    Constructs a vertex input binding description with the specified \a stride,
1678
    classification \a cls, and instance step rate \a stepRate.
1679
1680
    \note \a stepRate other than 1 is only supported when
1681
    QRhi::CustomInstanceStepRate is reported to be supported.
1682
 */
1683
QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cls, quint32 stepRate)
1684
0
    : m_stride(stride),
1685
0
      m_classification(cls),
1686
0
      m_instanceStepRate(stepRate)
1687
0
{
1688
0
}
1689
1690
/*!
1691
    \fn quint32 QRhiVertexInputBinding::stride() const
1692
    \return the stride in bytes.
1693
 */
1694
1695
/*!
1696
    \fn void QRhiVertexInputBinding::setStride(quint32 s)
1697
    Sets the stride to \a s.
1698
 */
1699
1700
/*!
1701
    \fn QRhiVertexInputBinding::Classification QRhiVertexInputBinding::classification() const
1702
    \return the input data classification.
1703
 */
1704
1705
/*!
1706
    \fn void QRhiVertexInputBinding::setClassification(Classification c)
1707
    Sets the input data classification \a c. By default this is set to PerVertex.
1708
 */
1709
1710
/*!
1711
    \fn quint32 QRhiVertexInputBinding::instanceStepRate() const
1712
    \return the instance step rate.
1713
 */
1714
1715
/*!
1716
    \fn void QRhiVertexInputBinding::setInstanceStepRate(quint32 rate)
1717
    Sets the instance step \a rate. By default this is set to 1.
1718
 */
1719
1720
/*!
1721
    \fn bool QRhiVertexInputBinding::operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1722
1723
    \return \c true if the values in the two QRhiVertexInputBinding objects
1724
    \a a and \a b are equal.
1725
 */
1726
1727
/*!
1728
    \fn bool QRhiVertexInputBinding::operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
1729
1730
    \return \c false if the values in the two QRhiVertexInputBinding
1731
    objects \a a and \a b are equal; otherwise returns \c true.
1732
*/
1733
1734
/*!
1735
    \fn size_t QRhiVertexInputBinding::qHash(const QRhiVertexInputBinding &key, size_t seed)
1736
    \qhash{QRhiVertexInputBinding}
1737
 */
1738
1739
#ifndef QT_NO_DEBUG_STREAM
1740
QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
1741
0
{
1742
0
    QDebugStateSaver saver(dbg);
1743
0
    dbg.nospace() << "QRhiVertexInputBinding(stride=" << b.stride()
1744
0
                  << " cls=" << b.classification()
1745
0
                  << " step-rate=" << b.instanceStepRate()
1746
0
                  << ')';
1747
0
    return dbg;
1748
0
}
1749
#endif
1750
1751
/*!
1752
    \class QRhiVertexInputAttribute
1753
    \inmodule QtGuiPrivate
1754
    \inheaderfile rhi/qrhi.h
1755
    \since 6.6
1756
    \brief Describes a single vertex input element.
1757
1758
    The members specify the binding number, location, format, and offset for a
1759
    single vertex input element.
1760
1761
    \note For HLSL it is assumed that the vertex shader translated from SPIR-V
1762
    uses
1763
    \c{TEXCOORD<location>} as the semantic for each input. Hence no separate
1764
    semantic name and index.
1765
1766
    As an example, assume a vertex shader with the following inputs:
1767
1768
    \badcode
1769
        layout(location = 0) in vec4 position;
1770
        layout(location = 1) in vec2 texcoord;
1771
    \endcode
1772
1773
    Now let's assume that we have 3 component vertex positions \c{(x, y, z)}
1774
    and 2 component texture coordinates \c{(u, v)} are provided in a
1775
    non-interleaved format in a buffer (or separate buffers even). Once two
1776
    bindings are defined, the attributes could be specified as:
1777
1778
    \code
1779
        QRhiVertexInputLayout inputLayout;
1780
        inputLayout.setBindings({
1781
            { 3 * sizeof(float) },
1782
            { 2 * sizeof(float) }
1783
        });
1784
        inputLayout.setAttributes({
1785
            { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1786
            { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
1787
        });
1788
    \endcode
1789
1790
    Once a graphics pipeline with this vertex input layout is bound, the vertex
1791
    inputs could be set up like the following for drawing a cube with 36
1792
    vertices, assuming we have a single buffer with first the positions and
1793
    then the texture coordinates:
1794
1795
    \code
1796
        const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1797
            { cubeBuf, 0 },
1798
            { cubeBuf, 36 * 3 * sizeof(float) }
1799
        };
1800
        cb->setVertexInput(0, 2, vbufBindings);
1801
    \endcode
1802
1803
    When working with interleaved data, there will typically be just one
1804
    binding, with multiple attributes referring to that same buffer binding
1805
    point:
1806
1807
    \code
1808
        QRhiVertexInputLayout inputLayout;
1809
        inputLayout.setBindings({
1810
            { 5 * sizeof(float) }
1811
        });
1812
        inputLayout.setAttributes({
1813
            { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1814
            { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
1815
        });
1816
    \endcode
1817
1818
    and then:
1819
1820
    \code
1821
        const QRhiCommandBuffer::VertexInput vbufBinding(interleavedCubeBuf, 0);
1822
        cb->setVertexInput(0, 1, &vbufBinding);
1823
    \endcode
1824
1825
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
1826
    for details.
1827
1828
    \sa QRhiCommandBuffer::setVertexInput()
1829
 */
1830
1831
/*!
1832
    \enum QRhiVertexInputAttribute::Format
1833
    Specifies the type of the element data.
1834
1835
    \value Float4 Four component float vector
1836
    \value Float3 Three component float vector
1837
    \value Float2 Two component float vector
1838
    \value Float Float
1839
    \value UNormByte4 Four component normalized unsigned byte vector
1840
    \value UNormByte2 Two component normalized unsigned byte vector
1841
    \value UNormByte Normalized unsigned byte
1842
    \value UInt4 Four component unsigned integer vector
1843
    \value UInt3 Three component unsigned integer vector
1844
    \value UInt2 Two component unsigned integer vector
1845
    \value UInt Unsigned integer
1846
    \value SInt4 Four component signed integer vector
1847
    \value SInt3 Three component signed integer vector
1848
    \value SInt2 Two component signed integer vector
1849
    \value SInt Signed integer
1850
    \value Half4 Four component half precision (16 bit) float vector
1851
    \value Half3 Three component half precision (16 bit) float vector
1852
    \value Half2 Two component half precision (16 bit) float vector
1853
    \value Half Half precision (16 bit) float
1854
    \value UShort4 Four component unsigned short (16 bit) integer vector
1855
    \value UShort3 Three component unsigned short (16 bit) integer vector
1856
    \value UShort2 Two component unsigned short (16 bit) integer vector
1857
    \value UShort Unsigned short (16 bit) integer
1858
    \value SShort4 Four component signed short (16 bit) integer vector
1859
    \value SShort3 Three component signed short (16 bit) integer vector
1860
    \value SShort2 Two component signed short (16 bit) integer vector
1861
    \value SShort Signed short (16 bit) integer
1862
1863
    \note Support for half precision floating point attributes is indicated at
1864
    run time by the QRhi::Feature::HalfAttributes feature flag.
1865
1866
    \note Direct3D 11/12 supports 16 bit input attributes, but does not support
1867
    the Half3, UShort3 or SShort3 types. The D3D backends pass through Half3 as
1868
    Half4, UShort3 as UShort4, and SShort3 as SShort4. To ensure cross platform
1869
    compatibility, 16 bit inputs should be padded to 8 bytes.
1870
 */
1871
1872
/*!
1873
    \fn QRhiVertexInputAttribute::QRhiVertexInputAttribute() = default
1874
1875
    Constructs a default vertex input attribute description.
1876
 */
1877
1878
/*!
1879
    Constructs a vertex input attribute description with the specified \a
1880
    binding number, \a location, \a format, and \a offset.
1881
1882
    \a matrixSlice should be -1 except when this attribute corresponds to a row
1883
    or column of a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming
1884
    4 consecutive vertex input locations), in which case it is the index of the
1885
    row or column. \c{location - matrixSlice} must always be equal to the \c
1886
    location for the first row or column of the unrolled matrix.
1887
 */
1888
QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset, int matrixSlice)
1889
0
    : m_binding(binding),
1890
0
      m_location(location),
1891
0
      m_format(format),
1892
0
      m_offset(offset),
1893
0
      m_matrixSlice(matrixSlice)
1894
0
{
1895
0
}
1896
1897
/*!
1898
    \fn int QRhiVertexInputAttribute::binding() const
1899
    \return the binding point index.
1900
 */
1901
1902
/*!
1903
    \fn void QRhiVertexInputAttribute::setBinding(int b)
1904
    Sets the binding point index to \a b.
1905
    By default this is set to 0.
1906
 */
1907
1908
/*!
1909
    \fn int QRhiVertexInputAttribute::location() const
1910
    \return the location of the vertex input element.
1911
 */
1912
1913
/*!
1914
    \fn void QRhiVertexInputAttribute::setLocation(int loc)
1915
    Sets the location of the vertex input element to \a loc.
1916
    By default this is set to 0.
1917
 */
1918
1919
/*!
1920
    \fn QRhiVertexInputAttribute::Format QRhiVertexInputAttribute::format() const
1921
    \return the format of the vertex input element.
1922
 */
1923
1924
/*!
1925
    \fn void QRhiVertexInputAttribute::setFormat(Format f)
1926
    Sets the format of the vertex input element to \a f.
1927
    By default this is set to Float4.
1928
 */
1929
1930
/*!
1931
    \fn quint32 QRhiVertexInputAttribute::offset() const
1932
    \return the byte offset for the input element.
1933
 */
1934
1935
/*!
1936
    \fn void QRhiVertexInputAttribute::setOffset(quint32 ofs)
1937
    Sets the byte offset for the input element to \a ofs.
1938
 */
1939
1940
/*!
1941
    \fn int QRhiVertexInputAttribute::matrixSlice() const
1942
1943
    \return the matrix slice if the input element corresponds to a row or
1944
    column of a matrix, or -1 if not relevant.
1945
 */
1946
1947
/*!
1948
    \fn void QRhiVertexInputAttribute::setMatrixSlice(int slice)
1949
1950
    Sets the matrix \a slice. By default this is set to -1, and should be set
1951
    to a >= 0 value only when this attribute corresponds to a row or column of
1952
    a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming 4
1953
    consecutive vertex input locations), in which case it is the index of the
1954
    row or column. \c{location - matrixSlice} must always be equal to the \c
1955
    location for the first row or column of the unrolled matrix.
1956
 */
1957
1958
/*!
1959
    \fn bool QRhiVertexInputAttribute::operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
1960
1961
    \return \c true if the values in the two QRhiVertexInputAttribute objects
1962
    \a a and \a b are equal.
1963
 */
1964
1965
/*!
1966
    \fn bool QRhiVertexInputAttribute::operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
1967
1968
    \return \c false if the values in the two QRhiVertexInputAttribute
1969
    objects \a a and \a b are equal; otherwise returns \c true.
1970
*/
1971
1972
/*!
1973
    \fn size_t QRhiVertexInputAttribute::qHash(const QRhiVertexInputAttribute &key, size_t seed)
1974
    \qhash{QRhiVertexInputAttribute}
1975
 */
1976
1977
#ifndef QT_NO_DEBUG_STREAM
1978
QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a)
1979
0
{
1980
0
    QDebugStateSaver saver(dbg);
1981
0
    dbg.nospace() << "QRhiVertexInputAttribute(binding=" << a.binding()
1982
0
                  << " location=" << a.location()
1983
0
                  << " format=" << a.format()
1984
0
                  << " offset=" << a.offset()
1985
0
                  << ')';
1986
0
    return dbg;
1987
0
}
1988
#endif
1989
1990
QRhiVertexInputAttribute::Format QRhiImplementation::shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const
1991
0
{
1992
0
    switch (type) {
1993
0
    case QShaderDescription::Vec4:
1994
0
        return QRhiVertexInputAttribute::Float4;
1995
0
    case QShaderDescription::Vec3:
1996
0
        return QRhiVertexInputAttribute::Float3;
1997
0
    case QShaderDescription::Vec2:
1998
0
        return QRhiVertexInputAttribute::Float2;
1999
0
    case QShaderDescription::Float:
2000
0
        return QRhiVertexInputAttribute::Float;
2001
2002
0
    case QShaderDescription::Int4:
2003
0
        return QRhiVertexInputAttribute::SInt4;
2004
0
    case QShaderDescription::Int3:
2005
0
        return QRhiVertexInputAttribute::SInt3;
2006
0
    case QShaderDescription::Int2:
2007
0
        return QRhiVertexInputAttribute::SInt2;
2008
0
    case QShaderDescription::Int:
2009
0
        return QRhiVertexInputAttribute::SInt;
2010
2011
0
    case QShaderDescription::Uint4:
2012
0
        return QRhiVertexInputAttribute::UInt4;
2013
0
    case QShaderDescription::Uint3:
2014
0
        return QRhiVertexInputAttribute::UInt3;
2015
0
    case QShaderDescription::Uint2:
2016
0
        return QRhiVertexInputAttribute::UInt2;
2017
0
    case QShaderDescription::Uint:
2018
0
        return QRhiVertexInputAttribute::UInt;
2019
2020
0
    case QShaderDescription::Half4:
2021
0
        return QRhiVertexInputAttribute::Half4;
2022
0
    case QShaderDescription::Half3:
2023
0
        return QRhiVertexInputAttribute::Half3;
2024
0
    case QShaderDescription::Half2:
2025
0
        return QRhiVertexInputAttribute::Half2;
2026
0
    case QShaderDescription::Half:
2027
0
        return QRhiVertexInputAttribute::Half;
2028
2029
0
    default:
2030
0
        Q_UNREACHABLE_RETURN(QRhiVertexInputAttribute::Float);
2031
0
    }
2032
0
}
2033
2034
quint32 QRhiImplementation::byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const
2035
0
{
2036
0
    switch (format) {
2037
0
    case QRhiVertexInputAttribute::Float4:
2038
0
        return 4 * sizeof(float);
2039
0
    case QRhiVertexInputAttribute::Float3:
2040
0
        return 4 * sizeof(float); // vec3 still takes 16 bytes
2041
0
    case QRhiVertexInputAttribute::Float2:
2042
0
        return 2 * sizeof(float);
2043
0
    case QRhiVertexInputAttribute::Float:
2044
0
        return sizeof(float);
2045
2046
0
    case QRhiVertexInputAttribute::UNormByte4:
2047
0
        return 4 * sizeof(quint8);
2048
0
    case QRhiVertexInputAttribute::UNormByte2:
2049
0
        return 2 * sizeof(quint8);
2050
0
    case QRhiVertexInputAttribute::UNormByte:
2051
0
        return sizeof(quint8);
2052
2053
0
    case QRhiVertexInputAttribute::UInt4:
2054
0
        return 4 * sizeof(quint32);
2055
0
    case QRhiVertexInputAttribute::UInt3:
2056
0
        return 4 * sizeof(quint32); // ivec3 still takes 16 bytes
2057
0
    case QRhiVertexInputAttribute::UInt2:
2058
0
        return 2 * sizeof(quint32);
2059
0
    case QRhiVertexInputAttribute::UInt:
2060
0
        return sizeof(quint32);
2061
2062
0
    case QRhiVertexInputAttribute::SInt4:
2063
0
        return 4 * sizeof(qint32);
2064
0
    case QRhiVertexInputAttribute::SInt3:
2065
0
        return 4 * sizeof(qint32); // uvec3 still takes 16 bytes
2066
0
    case QRhiVertexInputAttribute::SInt2:
2067
0
        return 2 * sizeof(qint32);
2068
0
    case QRhiVertexInputAttribute::SInt:
2069
0
        return sizeof(qint32);
2070
2071
0
    case QRhiVertexInputAttribute::Half4:
2072
0
        return 4 * sizeof(qfloat16);
2073
0
    case QRhiVertexInputAttribute::Half3:
2074
0
        return 4 * sizeof(qfloat16); // half3 still takes 8 bytes
2075
0
    case QRhiVertexInputAttribute::Half2:
2076
0
        return 2 * sizeof(qfloat16);
2077
0
    case QRhiVertexInputAttribute::Half:
2078
0
        return sizeof(qfloat16);
2079
2080
0
    case QRhiVertexInputAttribute::UShort4:
2081
0
        return 4 * sizeof(quint16);
2082
0
    case QRhiVertexInputAttribute::UShort3:
2083
0
        return 4 * sizeof(quint16); // ivec3 still takes 8 bytes
2084
0
    case QRhiVertexInputAttribute::UShort2:
2085
0
        return 2 * sizeof(quint16);
2086
0
    case QRhiVertexInputAttribute::UShort:
2087
0
        return sizeof(quint16);
2088
2089
0
    case QRhiVertexInputAttribute::SShort4:
2090
0
        return 4 * sizeof(qint16);
2091
0
    case QRhiVertexInputAttribute::SShort3:
2092
0
        return 4 * sizeof(qint16); // uvec3 still takes 8 bytes
2093
0
    case QRhiVertexInputAttribute::SShort2:
2094
0
        return 2 * sizeof(qint16);
2095
0
    case QRhiVertexInputAttribute::SShort:
2096
0
        return sizeof(qint16);
2097
2098
0
    default:
2099
0
        Q_UNREACHABLE_RETURN(1);
2100
0
    }
2101
0
}
2102
2103
/*!
2104
    \class QRhiVertexInputLayout
2105
    \inmodule QtGuiPrivate
2106
    \inheaderfile rhi/qrhi.h
2107
    \since 6.6
2108
    \brief Describes the layout of vertex inputs consumed by a vertex shader.
2109
2110
    The vertex input layout is defined by the collections of
2111
    QRhiVertexInputBinding and QRhiVertexInputAttribute.
2112
2113
    As an example, let's assume that we have a single buffer with 3 component
2114
    vertex positions and 2 component UV coordinates interleaved (\c x, \c y, \c
2115
    z, \c u, \c v), that the position and UV are expected at input locations 0
2116
    and 1 by the vertex shader, and that the vertex buffer will be bound at
2117
    binding point 0 using
2118
    \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()} later on:
2119
2120
    \code
2121
        QRhiVertexInputLayout inputLayout;
2122
        inputLayout.setBindings({
2123
            { 5 * sizeof(float) }
2124
        });
2125
        inputLayout.setAttributes({
2126
            { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
2127
            { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
2128
        });
2129
    \endcode
2130
2131
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2132
    for details.
2133
 */
2134
2135
/*!
2136
    \fn QRhiVertexInputLayout::QRhiVertexInputLayout() = default
2137
2138
    Constructs an empty vertex input layout description.
2139
 */
2140
2141
/*!
2142
    \fn void QRhiVertexInputLayout::setBindings(std::initializer_list<QRhiVertexInputBinding> list)
2143
    Sets the bindings from the specified \a list.
2144
 */
2145
2146
/*!
2147
    \fn template<typename InputIterator> void QRhiVertexInputLayout::setBindings(InputIterator first, InputIterator last)
2148
    Sets the bindings using the iterators \a first and \a last.
2149
 */
2150
2151
/*!
2152
    \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cbeginBindings() const
2153
    \return a const iterator pointing to the first item in the binding list.
2154
 */
2155
2156
/*!
2157
    \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cendBindings() const
2158
    \return a const iterator pointing just after the last item in the binding list.
2159
 */
2160
2161
/*!
2162
    \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::bindingAt(qsizetype index) const
2163
    \return the binding at the given \a index.
2164
 */
2165
2166
/*!
2167
    \fn qsizetype QRhiVertexInputLayout::bindingCount() const
2168
    \return the number of bindings.
2169
 */
2170
2171
/*!
2172
    \fn void QRhiVertexInputLayout::setAttributes(std::initializer_list<QRhiVertexInputAttribute> list)
2173
    Sets the attributes from the specified \a list.
2174
 */
2175
2176
/*!
2177
    \fn template<typename InputIterator> void QRhiVertexInputLayout::setAttributes(InputIterator first, InputIterator last)
2178
    Sets the attributes using the iterators \a first and \a last.
2179
 */
2180
2181
/*!
2182
    \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cbeginAttributes() const
2183
    \return a const iterator pointing to the first item in the attribute list.
2184
 */
2185
2186
/*!
2187
    \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cendAttributes() const
2188
    \return a const iterator pointing just after the last item in the attribute list.
2189
 */
2190
2191
/*!
2192
    \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::attributeAt(qsizetype index) const
2193
    \return the attribute at the given \a index.
2194
 */
2195
2196
/*!
2197
    \fn qsizetype QRhiVertexInputLayout::attributeCount() const
2198
    \return the number of attributes.
2199
 */
2200
2201
/*!
2202
    \fn bool QRhiVertexInputLayout::operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2203
2204
    \return \c true if the values in the two QRhiVertexInputLayout objects
2205
    \a a and \a b are equal.
2206
 */
2207
2208
/*!
2209
    \fn bool QRhiVertexInputLayout::operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
2210
2211
    \return \c false if the values in the two QRhiVertexInputLayout
2212
    objects \a a and \a b are equal; otherwise returns \c true.
2213
*/
2214
2215
/*!
2216
    \fn size_t QRhiVertexInputLayout::qHash(const QRhiVertexInputLayout &key, size_t seed)
2217
    \qhash{QRhiVertexInputLayout}
2218
 */
2219
2220
#ifndef QT_NO_DEBUG_STREAM
2221
QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
2222
0
{
2223
0
    QDebugStateSaver saver(dbg);
2224
0
    dbg.nospace() << "QRhiVertexInputLayout(bindings=" << v.m_bindings
2225
0
                  << " attributes=" << v.m_attributes
2226
0
                  << ')';
2227
0
    return dbg;
2228
0
}
2229
#endif
2230
2231
/*!
2232
    \class QRhiShaderStage
2233
    \inmodule QtGuiPrivate
2234
    \inheaderfile rhi/qrhi.h
2235
    \since 6.6
2236
    \brief Specifies the type and the shader code for a shader stage in the pipeline.
2237
2238
    When setting up a QRhiGraphicsPipeline, a collection of shader stages are
2239
    specified. The QRhiShaderStage contains a QShader and some associated
2240
    metadata, such as the graphics pipeline stage, and the
2241
    \l{QShader::Variant}{shader variant} to select. There is no need to specify
2242
    the shader language or version because the QRhi backend in use at runtime
2243
    will take care of choosing the appropriate shader version from the
2244
    collection within the QShader.
2245
2246
    The typical usage is in combination with
2247
    QRhiGraphicsPipeline::setShaderStages(), shown here with a simple approach
2248
    to load the QShader from \c{.qsb} files generated offline or at build time:
2249
2250
    \code
2251
        QShader getShader(const QString &name)
2252
        {
2253
            QFile f(name);
2254
            return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
2255
        }
2256
2257
        QShader vs = getShader("material.vert.qsb");
2258
        QShader fs = getShader("material.frag.qsb");
2259
        pipeline->setShaderStages({
2260
            { QRhiShaderStage::Vertex, vs },
2261
            { QRhiShaderStage::Fragment, fs }
2262
        });
2263
    \endcode
2264
2265
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2266
    for details.
2267
 */
2268
2269
/*!
2270
    \enum QRhiShaderStage::Type
2271
    Specifies the type of the shader stage.
2272
2273
    \value Vertex Vertex stage
2274
2275
    \value TessellationControl Tessellation control (hull shader) stage. Must
2276
    be used only when the QRhi::Tessellation feature is supported.
2277
2278
    \value TessellationEvaluation Tessellation evaluation (domain shader)
2279
    stage. Must be used only when the QRhi::Tessellation feature is supported.
2280
2281
    \value Fragment Fragment (pixel shader) stage
2282
2283
    \value Compute Compute stage. Must be used only when the QRhi::Compute
2284
    feature is supported.
2285
2286
    \value Geometry Geometry stage. Must be used only when the
2287
    QRhi::GeometryShader feature is supported.
2288
 */
2289
2290
/*!
2291
    \fn QRhiShaderStage::QRhiShaderStage() = default
2292
2293
    Constructs a shader stage description for the vertex stage with an empty
2294
    QShader.
2295
 */
2296
2297
/*!
2298
    \fn QRhiShaderStage::Type QRhiShaderStage::type() const
2299
    \return the type of the stage.
2300
 */
2301
2302
/*!
2303
    \fn void QRhiShaderStage::setType(Type t)
2304
2305
    Sets the type of the stage to \a t. Setters should rarely be needed in
2306
    pratice. Most applications will likely use the QRhiShaderStage constructor
2307
    in most cases.
2308
 */
2309
2310
/*!
2311
    \fn QShader QRhiShaderStage::shader() const
2312
    \return the QShader to be used for this stage in the graphics pipeline.
2313
 */
2314
2315
/*!
2316
    \fn void QRhiShaderStage::setShader(const QShader &s)
2317
    Sets the shader collection \a s.
2318
 */
2319
2320
/*!
2321
    \fn QShader::Variant QRhiShaderStage::shaderVariant() const
2322
    \return the requested shader variant.
2323
 */
2324
2325
/*!
2326
    \fn void QRhiShaderStage::setShaderVariant(QShader::Variant v)
2327
    Sets the requested shader variant \a v.
2328
 */
2329
2330
/*!
2331
    Constructs a shader stage description with the \a type of the stage and the
2332
    \a shader.
2333
2334
    The shader variant \a v defaults to QShader::StandardShader. A
2335
    QShader contains multiple source and binary versions of a shader.
2336
    In addition, it can also contain variants of the shader with slightly
2337
    modified code. \a v can then be used to select the desired variant.
2338
 */
2339
QRhiShaderStage::QRhiShaderStage(Type type, const QShader &shader, QShader::Variant v)
2340
0
    : m_type(type),
2341
0
      m_shader(shader),
2342
0
      m_shaderVariant(v)
2343
0
{
2344
0
}
2345
2346
/*!
2347
    \fn bool QRhiShaderStage::operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2348
2349
    \return \c true if the values in the two QRhiShaderStage objects
2350
    \a a and \a b are equal.
2351
 */
2352
2353
/*!
2354
    \fn bool QRhiShaderStage::operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
2355
2356
    \return \c false if the values in the two QRhiShaderStage
2357
    objects \a a and \a b are equal; otherwise returns \c true.
2358
*/
2359
2360
/*!
2361
    \fn size_t QRhiShaderStage::qHash(const QRhiShaderStage &key, size_t seed)
2362
    \qhash{QRhiShaderStage}
2363
 */
2364
2365
#ifndef QT_NO_DEBUG_STREAM
2366
QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
2367
0
{
2368
0
    QDebugStateSaver saver(dbg);
2369
0
    dbg.nospace() << "QRhiShaderStage(type=" << s.type()
2370
0
                  << " shader=" << s.shader()
2371
0
                  << " variant=" << s.shaderVariant()
2372
0
                  << ')';
2373
0
    return dbg;
2374
0
}
2375
#endif
2376
2377
/*!
2378
    \class QRhiColorAttachment
2379
    \inmodule QtGuiPrivate
2380
    \inheaderfile rhi/qrhi.h
2381
    \since 6.6
2382
    \brief Describes the a single color attachment of a render target.
2383
2384
    A color attachment is either a QRhiTexture or a QRhiRenderBuffer. The
2385
    former, i.e. when texture() is set, is used in most cases.
2386
    QRhiColorAttachment is commonly used in combination with
2387
    QRhiTextureRenderTargetDescription.
2388
2389
    \note texture() and renderBuffer() cannot be both set (be non-null at the
2390
    same time).
2391
2392
    Setting renderBuffer instead is recommended only when multisampling is
2393
    needed. Relying on QRhi::MultisampleRenderBuffer is a better choice than
2394
    QRhi::MultisampleTexture in practice since the former is available in more
2395
    run time configurations (e.g. when running on OpenGL ES 3.0 which has no
2396
    support for multisample textures, but does support multisample
2397
    renderbuffers).
2398
2399
    When targeting a non-multisample texture, the layer() and level() indicate
2400
    the targeted layer (face index \c{0-5} for cubemaps) and mip level. For 3D
2401
    textures layer() specifies the slice (one 2D image within the 3D texture)
2402
    to render to. For texture arrays layer() is the array index.
2403
2404
    When texture() or renderBuffer() is multisample, resolveTexture() can be
2405
    set optionally. When set, samples are resolved automatically into that
2406
    (non-multisample) texture at the end of the render pass. When rendering
2407
    into a multisample renderbuffers, this is the only way to get resolved,
2408
    non-multisample content out of them. Multisample textures allow sampling in
2409
    shaders so for them this is just one option.
2410
2411
    \note when resolving is enabled, the multisample data may not be written
2412
    out at all. This means that the multisample texture() must not be used
2413
    afterwards with shaders for sampling when resolveTexture() is set.
2414
2415
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2416
    for details.
2417
2418
    \sa QRhiTextureRenderTargetDescription
2419
 */
2420
2421
/*!
2422
    \fn QRhiColorAttachment::QRhiColorAttachment() = default
2423
2424
    Constructs an empty color attachment description.
2425
 */
2426
2427
/*!
2428
    Constructs a color attachment description that specifies \a texture as the
2429
    associated color buffer.
2430
 */
2431
QRhiColorAttachment::QRhiColorAttachment(QRhiTexture *texture)
2432
0
    : m_texture(texture)
2433
0
{
2434
0
}
2435
2436
/*!
2437
    Constructs a color attachment description that specifies \a renderBuffer as
2438
    the associated color buffer.
2439
 */
2440
QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
2441
0
    : m_renderBuffer(renderBuffer)
2442
0
{
2443
0
}
2444
2445
/*!
2446
    \fn QRhiTexture *QRhiColorAttachment::texture() const
2447
2448
    \return the texture this attachment description references, or \nullptr if
2449
    there is none.
2450
 */
2451
2452
/*!
2453
    \fn void QRhiColorAttachment::setTexture(QRhiTexture *tex)
2454
2455
    Sets the texture \a tex.
2456
2457
    \note texture() and renderBuffer() cannot be both set (be non-null at the
2458
    same time).
2459
 */
2460
2461
/*!
2462
    \fn QRhiRenderBuffer *QRhiColorAttachment::renderBuffer() const
2463
2464
    \return the renderbuffer this attachment description references, or
2465
    \nullptr if there is none.
2466
2467
    In practice associating a QRhiRenderBuffer with a QRhiColorAttachment makes
2468
    the most sense when setting up multisample rendering via a multisample
2469
    \l{QRhiRenderBuffer::Type}{color} renderbuffer that is then resolved into a
2470
    non-multisample texture at the end of the render pass.
2471
 */
2472
2473
/*!
2474
    \fn void QRhiColorAttachment::setRenderBuffer(QRhiRenderBuffer *rb)
2475
2476
    Sets the renderbuffer \a rb.
2477
2478
    \note texture() and renderBuffer() cannot be both set (be non-null at the
2479
    same time).
2480
 */
2481
2482
/*!
2483
    \fn int QRhiColorAttachment::layer() const
2484
    \return the layer index (cubemap face or array layer). 0 by default.
2485
 */
2486
2487
/*!
2488
    \fn void QRhiColorAttachment::setLayer(int layer)
2489
    Sets the \a layer index.
2490
 */
2491
2492
/*!
2493
    \fn int QRhiColorAttachment::level() const
2494
    \return the mip level. 0 by default.
2495
 */
2496
2497
/*!
2498
    \fn void QRhiColorAttachment::setLevel(int level)
2499
    Sets the mip \a level.
2500
 */
2501
2502
/*!
2503
    \fn QRhiTexture *QRhiColorAttachment::resolveTexture() const
2504
2505
    \return the resolve texture this attachment description references, or
2506
    \nullptr if there is none.
2507
2508
    Setting a non-null resolve texture is applicable when the attachment
2509
    references a multisample texture or renderbuffer. The QRhiTexture in the
2510
    resolveTexture() is then a non-multisample 2D texture (or texture array)
2511
    with the same size (but a sample count of 1). The multisample content is
2512
    automatically resolved into this texture at the end of each render pass.
2513
 */
2514
2515
/*!
2516
    \fn void QRhiColorAttachment::setResolveTexture(QRhiTexture *tex)
2517
2518
    Sets the resolve texture \a tex.
2519
2520
    \a tex is expected to be a 2D texture or a 2D texture array. In either
2521
    case, resolving targets a single mip level of a single layer (array
2522
    element) of \a tex. The mip level and array layer are specified by
2523
    resolveLevel() and resolveLayer().
2524
2525
    An exception is \l{setMultiViewCount()}{multiview}: when the color
2526
    attachment is associated with a texture array and multiview is enabled, the
2527
    resolve texture must also be a texture array with sufficient elements for
2528
    all views. In this case all elements that correspond to views are resolved
2529
    automatically; the behavior is similar to the following pseudo-code:
2530
    \badcode
2531
        for (i = 0; i < multiViewCount(); ++i)
2532
            resolve texture's layer() + i into resolveTexture's resolveLayer() + i
2533
    \endcode
2534
2535
    Setting a non-multisample texture to resolve a multisample texture or
2536
    renderbuffer automatically at the end of the render pass is often
2537
    preferable to working with multisample textures (and not setting a resolve
2538
    texture), because it avoids the need for writing dedicated fragment shaders
2539
    that work exclusively with multisample textures (\c sampler2DMS, \c
2540
    texelFetch, etc.), and rather allows using the same shader as one would if
2541
    the attachment's texture was not multisampled to begin with. This comes at
2542
    the expense of an additional resource (the non-multisample \a tex).
2543
 */
2544
2545
/*!
2546
    \fn int QRhiColorAttachment::resolveLayer() const
2547
    \return the currently set resolve texture layer. Defaults to 0.
2548
 */
2549
2550
/*!
2551
    \fn void QRhiColorAttachment::setResolveLayer(int layer)
2552
    Sets the resolve texture \a layer to use.
2553
 */
2554
2555
/*!
2556
    \fn int QRhiColorAttachment::resolveLevel() const
2557
    \return the currently set resolve texture mip level. Defaults to 0.
2558
 */
2559
2560
/*!
2561
    \fn void QRhiColorAttachment::setResolveLevel(int level)
2562
    Sets the resolve texture mip \a level to use.
2563
 */
2564
2565
/*!
2566
    \fn int QRhiColorAttachment::multiViewCount() const
2567
2568
    \return the currently set number of views. Defaults to 0 which indicates
2569
    the render target with this color attachment is not going to be used with
2570
    multiview rendering.
2571
2572
    \since 6.7
2573
 */
2574
2575
/*!
2576
    \fn void QRhiColorAttachment::setMultiViewCount(int count)
2577
2578
    Sets the view \a count. Setting a value larger than 1 indicates that the
2579
    render target with this color attachment is going to be used with multiview
2580
    rendering. The default value is 0. Values smaller than 2 indicate no
2581
    multiview rendering.
2582
2583
    When \a count is set to \c 2 or greater, the color attachment must be
2584
    associated with a 2D texture array. layer() and multiViewCount() together
2585
    define the range of texture array elements that are targeted during
2586
    multiview rendering.
2587
2588
    For example, if \c layer is \c 0 and \c multiViewCount is \c 2, the texture
2589
    array must have 2 (or more) elements, and the multiview rendering will
2590
    target elements 0 and 1. The \c{gl_ViewIndex} variable in the shaders has a
2591
    value of \c 0 or \c 1 then, where view \c 0 corresponds to the texture array
2592
    element \c 0, and view \c 1 to the array element \c 1.
2593
2594
    \note Setting a \a count larger than 1, using a texture array as texture(),
2595
    and calling \l{QRhiCommandBuffer::beginPass()}{beginPass()} on a
2596
    QRhiTextureRenderTarget with this color attachment implies multiview
2597
    rendering for the entire render pass. multiViewCount() should not be set
2598
    unless multiview rendering is wanted. Multiview cannot be used with texture
2599
    types other than 2D texture arrays. (although 3D textures may work,
2600
    depending on the graphics API and backend; applications are nonetheless
2601
    advised not to rely on that and only use 2D texture arrays as the render
2602
    targets of multiview rendering)
2603
2604
    See
2605
    \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2606
    for more details regarding multiview rendering. Do note that Qt requires
2607
    \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview2.txt}{GL_OVR_multiview2}
2608
    as well, when running on OpenGL (ES).
2609
2610
    Multiview rendering is available only when the
2611
    \l{QRhi::MultiView}{MultiView} feature is reported as supported from
2612
    \l{QRhi::isFeatureSupported()}{isFeatureSupported()}.
2613
2614
    \note For portability, be aware of limitations that exist for multiview
2615
    rendering with some of the graphics APIs. It is recommended that multiview
2616
    render passes do not rely on any of the features that
2617
    \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
2618
    declares as unsupported. The one exception is shader stage outputs other
2619
    than \c{gl_Position} depending on \c{gl_ViewIndex}: that can be relied on
2620
    (even with OpenGL) because QRhi never reports multiview as supported without
2621
    \c{GL_OVR_multiview2} also being present.
2622
2623
    \note Multiview rendering is not supported in combination with tessellation
2624
    or geometry shaders, even though some implementations of some graphics APIs
2625
    may allow this.
2626
2627
    \since 6.7
2628
 */
2629
2630
/*!
2631
    \class QRhiTextureRenderTargetDescription
2632
    \inmodule QtGuiPrivate
2633
    \inheaderfile rhi/qrhi.h
2634
    \since 6.6
2635
    \brief Describes the color and depth or depth/stencil attachments of a render target.
2636
2637
    A texture render target has zero or more textures as color attachments,
2638
    zero or one renderbuffer as combined depth/stencil buffer or zero or one
2639
    texture as depth buffer.
2640
2641
    \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2642
    non-null at the same time).
2643
2644
    Let's look at some example usages in combination with
2645
    QRhiTextureRenderTarget.
2646
2647
    Due to the constructors, the targeting a texture (and no depth/stencil
2648
    buffer) is simple:
2649
2650
    \code
2651
        QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256), 1, QRhiTexture::RenderTarget);
2652
        texture->create();
2653
        QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture }));
2654
    \endcode
2655
2656
    The following creates a texture render target that is set up to target mip
2657
    level #2 of a texture:
2658
2659
    \code
2660
        QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget | QRhiTexture::MipMapped);
2661
        texture->create();
2662
        QRhiColorAttachment colorAtt(texture);
2663
        colorAtt.setLevel(2);
2664
        QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt });
2665
    \endcode
2666
2667
    Another example, this time to render into a depth texture:
2668
2669
    \code
2670
        QRhiTexture *shadowMap = rhi->newTexture(QRhiTexture::D32F, QSize(1024, 1024), 1, QRhiTexture::RenderTarget);
2671
        shadowMap->create();
2672
        QRhiTextureRenderTargetDescription rtDesc;
2673
        rtDesc.setDepthTexture(shadowMap);
2674
        QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2675
    \endcode
2676
2677
    A very common case, having a texture as the color attachment and a
2678
    renderbuffer as depth/stencil to enable depth testing:
2679
2680
    \code
2681
        QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2682
        texture->create();
2683
        QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512));
2684
        depthStencil->create();
2685
        QRhiTextureRenderTargetDescription rtDesc({ texture }, depthStencil);
2686
        QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
2687
    \endcode
2688
2689
    Finally, to enable multisample rendering in a portable manner (so also
2690
    supporting OpenGL ES 3.0), using a QRhiRenderBuffer as the (multisample)
2691
    color buffer and then resolving into a regular (non-multisample) 2D
2692
    texture. To enable depth testing, a depth-stencil buffer, which also must
2693
    use the same sample count, is used as well:
2694
2695
    \code
2696
        QRhiRenderBuffer *colorBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4); // 4x MSAA
2697
        colorBuffer->create();
2698
        QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512), 4);
2699
        depthStencil->create();
2700
        QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
2701
        texture->create();
2702
        QRhiColorAttachment colorAtt(colorBuffer);
2703
        colorAtt.setResolveTexture(texture);
2704
        QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt, depthStencil });
2705
    \endcode
2706
2707
    \note when multisample resolving is enabled, the multisample data may not be
2708
    written out at all. This means that the multisample texture in a color
2709
    attachment must not be used afterwards with shaders for sampling (or other
2710
    purposes) whenever a resolve texture is set, since the multisample color
2711
    buffer is merely an intermediate storage then that gets no data written back
2712
    on some GPU architectures at all. See
2713
    \l{QRhiTextureRenderTarget::Flag}{PreserveColorContents} for more details.
2714
2715
    \note When using setDepthTexture(), not setDepthStencilBuffer(), and the
2716
    depth (stencil) data is not of interest afterwards, set the
2717
    DoNotStoreDepthStencilContents flag on the QRhiTextureRenderTarget. This
2718
    allows indicating to the underlying 3D API that the depth/stencil data can
2719
    be discarded, leading potentially to better performance with tiled GPU
2720
    architectures. When the depth-stencil buffer is a QRhiRenderBuffer (and also
2721
    for the multisample color texture, see previous note) this is implicit, but
2722
    with a depth (stencil) QRhiTexture the intention needs to be declared
2723
    explicitly. By default QRhi assumes that the data is of interest (e.g., the
2724
    depth texture is sampled in a shader afterwards).
2725
2726
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
2727
    for details.
2728
2729
    \sa QRhiColorAttachment, QRhiTextureRenderTarget
2730
 */
2731
2732
/*!
2733
    \fn QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription() = default
2734
2735
    Constructs an empty texture render target description.
2736
 */
2737
2738
/*!
2739
    Constructs a texture render target description with one attachment
2740
    described by \a colorAttachment.
2741
 */
2742
QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment)
2743
0
{
2744
0
    m_colorAttachments.append(colorAttachment);
2745
0
}
2746
2747
/*!
2748
    Constructs a texture render target description with two attachments, a
2749
    color attachment described by \a colorAttachment, and a depth/stencil
2750
    attachment with \a depthStencilBuffer.
2751
 */
2752
QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2753
                                                                       QRhiRenderBuffer *depthStencilBuffer)
2754
0
    : m_depthStencilBuffer(depthStencilBuffer)
2755
0
{
2756
0
    m_colorAttachments.append(colorAttachment);
2757
0
}
2758
2759
/*!
2760
    Constructs a texture render target description with two attachments, a
2761
    color attachment described by \a colorAttachment, and a depth attachment
2762
    with \a depthTexture.
2763
2764
    \note \a depthTexture must have a suitable format, such as QRhiTexture::D16
2765
    or QRhiTexture::D32F.
2766
 */
2767
QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
2768
                                                                       QRhiTexture *depthTexture)
2769
0
    : m_depthTexture(depthTexture)
2770
0
{
2771
0
    m_colorAttachments.append(colorAttachment);
2772
0
}
2773
2774
/*!
2775
    \fn void QRhiTextureRenderTargetDescription::setColorAttachments(std::initializer_list<QRhiColorAttachment> list)
2776
    Sets the \a list of color attachments.
2777
 */
2778
2779
/*!
2780
    \fn template<typename InputIterator> void QRhiTextureRenderTargetDescription::setColorAttachments(InputIterator first, InputIterator last)
2781
    Sets the list of color attachments via the iterators \a first and \a last.
2782
 */
2783
2784
/*!
2785
    \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cbeginColorAttachments() const
2786
    \return a const iterator pointing to the first item in the attachment list.
2787
 */
2788
2789
/*!
2790
    \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cendColorAttachments() const
2791
    \return a const iterator pointing just after the last item in the attachment list.
2792
 */
2793
2794
/*!
2795
    \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::colorAttachmentAt(qsizetype index) const
2796
    \return the color attachment at the specified \a index.
2797
 */
2798
2799
/*!
2800
    \fn qsizetype QRhiTextureRenderTargetDescription::colorAttachmentCount() const
2801
    \return the number of currently set color attachments.
2802
 */
2803
2804
/*!
2805
    \fn QRhiRenderBuffer *QRhiTextureRenderTargetDescription::depthStencilBuffer() const
2806
    \return the renderbuffer used as depth-stencil buffer, or \nullptr if none was set.
2807
 */
2808
2809
/*!
2810
    \fn void QRhiTextureRenderTargetDescription::setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer)
2811
2812
    Sets the \a renderBuffer for depth-stencil. Not mandatory, e.g. when no
2813
    depth test/write or stencil-related features are used within any graphics
2814
    pipelines in any of the render passes for this render target, it can be
2815
    left set to \nullptr.
2816
2817
    \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2818
    non-null at the same time).
2819
2820
    Using a QRhiRenderBuffer over a 2D QRhiTexture as the depth or
2821
    depth/stencil buffer is very common, and is the recommended approach for
2822
    applications. Using a QRhiTexture, and so setDepthTexture() becomes
2823
    relevant if the depth data is meant to be accessed (e.g. sampled in a
2824
    shader) afterwards, or when
2825
    \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering} is
2826
    involved (because then the depth texture must be a texture array).
2827
2828
    \sa setDepthTexture()
2829
 */
2830
2831
/*!
2832
    \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthTexture() const
2833
    \return the currently referenced depth texture, or \nullptr if none was set.
2834
 */
2835
2836
/*!
2837
    \fn void QRhiTextureRenderTargetDescription::setDepthTexture(QRhiTexture *texture)
2838
2839
    Sets the \a texture for depth-stencil. This is an alternative to
2840
    setDepthStencilBuffer(), where instead of a QRhiRenderBuffer a QRhiTexture
2841
    with a suitable type (e.g., QRhiTexture::D32F) is provided.
2842
2843
    \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
2844
    non-null at the same time).
2845
2846
    \a texture can either be a 2D texture or a 2D texture array (when texture
2847
    arrays are supported). Specifying a texture array is relevant in particular
2848
    with
2849
    \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering}.
2850
2851
    \note If \a texture is a format with a stencil component, such as
2852
    \l QRhiTexture::D24S8, it will serve as the stencil buffer as well.
2853
2854
    \sa setDepthStencilBuffer()
2855
 */
2856
2857
/*!
2858
    \fn int QRhiTextureRenderTargetDescription::depthLayer() const
2859
    \return the array slice index to be used for the depth/stencil attachment,
2860
    or -1 by default.
2861
2862
    \since 6.12
2863
    \sa setDepthLayer(), setDepthTexture()
2864
 */
2865
2866
/*!
2867
    \fn void QRhiTextureRenderTargetDescription::setDepthLayer(int depthLayer)
2868
2869
    Sets the array slice index to be used for the depth/stencil attachment.
2870
2871
    Pass -1 (the default) to not target a particular layer. When set to a
2872
    non-negative value, the render target attaches a view that targets exactly
2873
    that layer (slice) of the depth texture. This is only effective when a 2D
2874
    array depth texture is provided via setDepthTexture(); otherwise the value
2875
    is ignored.
2876
2877
    The value must be within the array size of the depth texture; passing an
2878
    out-of-range index leads to undefined behavior. The index is absolute
2879
    with respect to the underlying texture, regardless of any array range
2880
    that may have been specified when creating the texture.
2881
2882
    Specifying a \a depthLayer disables layered/multiview rendering for the
2883
    depth attachment.
2884
2885
    \since 6.12
2886
    \sa depthLayer(), setDepthTexture()
2887
 */
2888
2889
/*!
2890
    \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthResolveTexture() const
2891
2892
    \return the texture to which a multisample depth (or depth-stencil) texture
2893
    (or texture array) is resolved to. \nullptr if there is none, which is the
2894
    most common case.
2895
2896
    \since 6.8
2897
    \sa QRhiColorAttachment::resolveTexture(), depthTexture()
2898
 */
2899
2900
/*!
2901
    \fn void QRhiTextureRenderTargetDescription::setDepthResolveTexture(QRhiTexture *tex)
2902
2903
    Sets the depth (or depth-stencil) resolve texture \a tex.
2904
2905
    \a tex is expected to be a 2D texture or a 2D texture array with a format
2906
    matching the texture set via setDepthTexture().
2907
2908
    \note Resolving depth (or depth-stencil) data is only functional when the
2909
    \l QRhi::ResolveDepthStencil feature is reported as supported at run time.
2910
    Support for depth-stencil resolve is not universally available among the
2911
    graphics APIs. Designs assuming unconditional availability of depth-stencil
2912
    resolve are therefore non-portable, and should be avoided.
2913
2914
    \note As an additional limitation for OpenGL ES in particular, setting a
2915
    depth resolve texture may only be functional in combination with
2916
    setDepthTexture(), not with setDepthStencilBuffer().
2917
2918
    \since 6.8
2919
    \sa QRhiColorAttachment::setResolveTexture(), setDepthTexture()
2920
 */
2921
2922
/*!
2923
    \fn QRhiShadingRateMap *QRhiTextureRenderTargetDescription::shadingRateMap() const
2924
    \return the currently set QRhiShadingRateMap. By default this is \nullptr.
2925
    \since 6.9
2926
 */
2927
2928
/*!
2929
    \fn void QRhiTextureRenderTargetDescription::setShadingRateMap(QRhiShadingRateMap *map)
2930
2931
    Associates with the specified QRhiShadingRateMap \a map. This is functional
2932
    only when the \l QRhi::VariableRateShadingMap feature is reported as
2933
    supported.
2934
2935
    When QRhiCommandBuffer::setShadingRate() is also called, the higher of the
2936
    two shading rates is used for each tile. There is currently no control
2937
    offered over the combiner behavior.
2938
2939
    \note When the render target had already been built (create() was called
2940
    successfully), setting a shading rate map implies that a different, new
2941
    QRhiRenderPassDescriptor is needed and thus a rebuild is needed. Call
2942
    setRenderPassDescriptor() again (outside of a render pass) and then rebuild
2943
    by calling create(). This has other rolling consequences as well, for
2944
    example for graphics pipelines: those also need to be associated with the
2945
    new QRhiRenderPassDescriptor and then rebuilt. See \l
2946
    QRhiRenderPassDescriptor::serializedFormat() for some suggestions on how to
2947
    deal with this. Remember to set the QRhiGraphicsPipeline::UsesShadingRate
2948
    flag as well.
2949
2950
    \since 6.9
2951
 */
2952
2953
/*!
2954
    \class QRhiTextureSubresourceUploadDescription
2955
    \inmodule QtGuiPrivate
2956
    \inheaderfile rhi/qrhi.h
2957
    \since 6.6
2958
    \brief Describes the source for one mip level in a layer in a texture upload operation.
2959
2960
    The source content is specified either as a QImage or as a raw blob. The
2961
    former is only allowed for uncompressed textures with a format that can be
2962
    mapped to QImage, while the latter is supported for all formats, including
2963
    floating point and compressed.
2964
2965
    \note image() and data() cannot be both set at the same time.
2966
2967
    destinationTopLeft() specifies the top-left corner of the target
2968
    rectangle. Defaults to (0, 0).
2969
2970
    An empty sourceSize() (the default) indicates that size is assumed to be
2971
    the size of the subresource. With QImage-based uploads this implies that
2972
    the size of the source image() must match the subresource. When providing
2973
    raw data instead, sufficient number of bytes must be provided in data().
2974
2975
    sourceTopLeft() is supported only for QImage-based uploads, and specifies
2976
    the top-left corner of the source rectangle.
2977
2978
    \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
2979
    internally, depending on the format and the backend.
2980
2981
    When providing raw data, and the stride is not specified via
2982
    setDataStride(), the stride (row pitch, row length in bytes) of the
2983
    provided data must be equal to \c{width * pixelSize} where \c pixelSize is
2984
    the number of bytes used for one pixel, and there must be no additional
2985
    padding between rows. There is no row start alignment requirement.
2986
2987
    When there is unused data at the end of each row in the input raw data,
2988
    call setDataStride() with the total number of bytes per row. The stride
2989
    must always be a multiple of the number of bytes for one pixel. The row
2990
    stride is only applicable to image data for textures with an uncompressed
2991
    format.
2992
2993
    \note The format of the source data must be compatible with the texture
2994
    format. With many graphics APIs the data is copied as-is into a staging
2995
    buffer, there is no intermediate format conversion provided by QRhi. This
2996
    applies to floating point formats as well, with, for example, RGBA16F
2997
    requiring half floats in the source data.
2998
2999
    \note Setting the stride via setDataStride() is only functional when
3000
    QRhi::ImageDataStride is reported as
3001
    \l{QRhi::isFeatureSupported()}{supported}. In practice this can be expected
3002
    to be supported everywhere except for OpenGL ES 2.0.
3003
3004
    \note When a QImage is given, the stride returned from
3005
    QImage::bytesPerLine() is taken into account automatically.
3006
3007
    \warning When a QImage is given and the QImage does not own the underlying
3008
    pixel data, it is up to the caller to ensure that the associated data stays
3009
    valid until the end of the frame. (just submitting the resource update batch
3010
    is not sufficient, the data must stay valid until QRhi::endFrame() is called
3011
    in order to be portable across all backends) If this cannot be ensured, the
3012
    caller is strongly encouraged to call QImage::detach() on the image before
3013
    passing it to uploadTexture().
3014
3015
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3016
    for details.
3017
3018
    \sa QRhiTextureUploadDescription
3019
 */
3020
3021
/*!
3022
    \fn QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription() = default
3023
3024
    Constructs an empty subresource description.
3025
3026
    \note an empty QRhiTextureSubresourceUploadDescription is not useful on its
3027
    own and should not be submitted to a QRhiTextureUploadEntry. At minimum
3028
    image or data must be set first.
3029
 */
3030
3031
/*!
3032
    Constructs a mip level description with a \a image.
3033
3034
    The \l{QImage::size()}{size} of \a image must match the size of the mip
3035
    level. For level 0 that is the \l{QRhiTexture::pixelSize()}{texture size}.
3036
3037
    The bit depth of \a image must be compatible with the
3038
    \l{QRhiTexture::Format}{texture format}.
3039
3040
    To describe a partial upload, call setSourceSize(), setSourceTopLeft(), or
3041
    setDestinationTopLeft() afterwards.
3042
 */
3043
QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QImage &image)
3044
0
    : m_image(image)
3045
0
{
3046
0
}
3047
3048
/*!
3049
    Constructs a mip level description with the image data is specified by \a
3050
    data and \a size. This is suitable for floating point and compressed
3051
    formats as well.
3052
3053
    \a data can safely be destroyed or changed once this function returns.
3054
 */
3055
QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const void *data, quint32 size)
3056
0
    : m_data(reinterpret_cast<const char *>(data), size)
3057
0
{
3058
0
}
3059
3060
/*!
3061
    Constructs a mip level description with the image data specified by \a
3062
    data. This is suitable for floating point and compressed formats as well.
3063
 */
3064
QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QByteArray &data)
3065
0
    : m_data(data)
3066
0
{
3067
0
}
3068
3069
/*!
3070
    \fn QImage QRhiTextureSubresourceUploadDescription::image() const
3071
    \return the currently set QImage.
3072
 */
3073
3074
/*!
3075
    \fn void QRhiTextureSubresourceUploadDescription::setImage(const QImage &image)
3076
3077
    Sets \a image.
3078
    Upon textures loading, the image data will be read as is, with no formats conversions.
3079
3080
    \note image() and data() cannot be both set at the same time.
3081
 */
3082
3083
/*!
3084
    \fn QByteArray QRhiTextureSubresourceUploadDescription::data() const
3085
    \return the currently set raw pixel data.
3086
 */
3087
3088
/*!
3089
    \fn void QRhiTextureSubresourceUploadDescription::setData(const QByteArray &data)
3090
3091
    Sets \a data.
3092
3093
    \note image() and data() cannot be both set at the same time.
3094
 */
3095
3096
/*!
3097
    \fn quint32 QRhiTextureSubresourceUploadDescription::dataStride() const
3098
    \return the currently set data stride.
3099
 */
3100
3101
/*!
3102
    \fn void QRhiTextureSubresourceUploadDescription::setDataStride(quint32 stride)
3103
3104
    Sets the data \a stride in bytes. By default this is 0 and not always
3105
    relevant. When providing raw data(), and the stride is not specified via
3106
    setDataStride(), the stride (row pitch, row length in bytes) of the
3107
    provided data must be equal to \c{width * pixelSize} where \c pixelSize is
3108
    the number of bytes used for one pixel, and there must be no additional
3109
    padding between rows. Otherwise, if there is additional space between the
3110
    lines, set a non-zero \a stride. All this is applicable only when raw image
3111
    data is provided, and is not necessary when working QImage since that has
3112
    its own \l{QImage::bytesPerLine()}{stride} value.
3113
3114
    \note When a non-zero \a stride is set, make sure the data contains the
3115
    trailing padding for the last row as well, i.e. at least \c{stride * height}
3116
    bytes in total. While providing the data without the last row's padding
3117
    (i.e., interpreting stride as not applicable to the last row) could be safe,
3118
    and is in fact safe with Vulkan, OpenGL, and D3D12, this cannot be
3119
    guaranteed for all backends, so the safe approach is to avoid this and treat
3120
    the last line like all others.
3121
3122
    \note Setting the stride via setDataStride() is only functional when
3123
    QRhi::ImageDataStride is reported as
3124
    \l{QRhi::isFeatureSupported()}{supported}.
3125
3126
    \note When a QImage is given, the stride returned from
3127
    QImage::bytesPerLine() is taken into account automatically and therefore
3128
    there is no need to set the data stride manually.
3129
 */
3130
3131
/*!
3132
    \fn QPoint QRhiTextureSubresourceUploadDescription::destinationTopLeft() const
3133
    \return the currently set destination top-left position. Defaults to (0, 0).
3134
 */
3135
3136
/*!
3137
    \fn void QRhiTextureSubresourceUploadDescription::setDestinationTopLeft(const QPoint &p)
3138
    Sets the destination top-left position \a p.
3139
3140
    \note In the most common case of sourcing the image data from a QImage, Qt
3141
    performs clamping of invalid texture upload sizes when the destination
3142
    position + the source size exceeds the size of the targeted texture
3143
    subresource (i.e, the size at the given mip level). There is also a
3144
    qWarning() message printed on the debug output in this case. This is done in
3145
    order to avoid confusion when the underlying 3D APIs crash and lead to GPU
3146
    device removals at a later point when submitting the commands. Regardless,
3147
    developers are encouraged to always validate applications by running with the
3148
    Vulkan, D3D12, or Metal validation/debug layers enabled, since those offer a
3149
    much wider range of checks on API usage.
3150
 */
3151
3152
/*!
3153
    \fn QSize QRhiTextureSubresourceUploadDescription::sourceSize() const
3154
3155
    \return the source size in pixels. Defaults to a default-constructed QSize,
3156
    which indicates the entire subresource.
3157
 */
3158
3159
/*!
3160
    \fn void QRhiTextureSubresourceUploadDescription::setSourceSize(const QSize &size)
3161
3162
    Sets the source \a size in pixels.
3163
3164
    \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3165
    internally, depending on the format and the backend.
3166
 */
3167
3168
/*!
3169
    \fn QPoint QRhiTextureSubresourceUploadDescription::sourceTopLeft() const
3170
    \return the currently set source top-left position. Defaults to (0, 0).
3171
 */
3172
3173
/*!
3174
    \fn void QRhiTextureSubresourceUploadDescription::setSourceTopLeft(const QPoint &p)
3175
3176
    Sets the source top-left position \a p.
3177
3178
    \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
3179
    internally, depending on the format and the backend.
3180
 */
3181
3182
/*!
3183
    \class QRhiTextureUploadEntry
3184
    \inmodule QtGuiPrivate
3185
    \inheaderfile rhi/qrhi.h
3186
    \since 6.6
3187
3188
    \brief Describes one layer (face for cubemaps, slice for 3D textures,
3189
    element for texture arrays) in a texture upload operation.
3190
3191
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3192
    for details.
3193
 */
3194
3195
/*!
3196
    \fn QRhiTextureUploadEntry::QRhiTextureUploadEntry()
3197
3198
    Constructs an empty QRhiTextureUploadEntry targeting layer 0 and level 0.
3199
3200
    \note an empty QRhiTextureUploadEntry should not be submitted without
3201
    setting a QRhiTextureSubresourceUploadDescription via setDescription()
3202
    first.
3203
 */
3204
3205
/*!
3206
    Constructs a QRhiTextureUploadEntry targeting the given \a layer and mip
3207
    \a level, with the subresource contents described by \a desc.
3208
 */
3209
QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
3210
                                               const QRhiTextureSubresourceUploadDescription &desc)
3211
0
    : m_layer(layer),
3212
0
      m_level(level),
3213
0
      m_desc(desc)
3214
0
{
3215
0
}
3216
3217
/*!
3218
    \fn int QRhiTextureUploadEntry::layer() const
3219
    \return the currently set layer index (cubemap face, array layer). Defaults to 0.
3220
 */
3221
3222
/*!
3223
    \fn void QRhiTextureUploadEntry::setLayer(int layer)
3224
    Sets the \a layer.
3225
 */
3226
3227
/*!
3228
    \fn int QRhiTextureUploadEntry::level() const
3229
    \return the currently set mip level. Defaults to 0.
3230
 */
3231
3232
/*!
3233
    \fn void QRhiTextureUploadEntry::setLevel(int level)
3234
    Sets the mip \a level.
3235
 */
3236
3237
/*!
3238
    \fn QRhiTextureSubresourceUploadDescription QRhiTextureUploadEntry::description() const
3239
    \return the currently set subresource description.
3240
 */
3241
3242
/*!
3243
    \fn void QRhiTextureUploadEntry::setDescription(const QRhiTextureSubresourceUploadDescription &desc)
3244
    Sets the subresource description \a desc.
3245
 */
3246
3247
/*!
3248
    \class QRhiTextureUploadDescription
3249
    \inmodule QtGuiPrivate
3250
    \inheaderfile rhi/qrhi.h
3251
    \since 6.6
3252
    \brief Describes a texture upload operation.
3253
3254
    Used with QRhiResourceUpdateBatch::uploadTexture(). That function has two
3255
    variants: one taking a QImage and one taking a
3256
    QRhiTextureUploadDescription. The former is a convenience version,
3257
    internally creating a QRhiTextureUploadDescription with a single image
3258
    targeting level 0 for layer 0.
3259
3260
    An example of the common, simple case of wanting to upload the contents
3261
    of a QImage to a QRhiTexture with a matching pixel size:
3262
3263
    \code
3264
        QImage image(256, 256, QImage::Format_RGBA8888);
3265
        image.fill(Qt::green); // or could use a QPainter targeting image
3266
        QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256));
3267
        texture->create();
3268
        QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
3269
        u->uploadTexture(texture, image);
3270
    \endcode
3271
3272
    When cubemaps, pre-generated mip images, compressed textures, or partial
3273
    uploads are involved, applications will have to use this class instead.
3274
3275
    QRhiTextureUploadDescription also enables specifying batched uploads, which
3276
    are useful for example when generating an atlas or glyph cache texture:
3277
    multiple, partial uploads for the same subresource (meaning the same layer
3278
    and level) are supported, and can be, depending on the backend and the
3279
    underlying graphics API, more efficient when batched into the same
3280
    QRhiTextureUploadDescription as opposed to issuing individual
3281
    \l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} commands for
3282
    each of them.
3283
3284
    \note Cubemaps have one layer for each of the six faces in the order +X,
3285
    -X, +Y, -Y, +Z, -Z.
3286
3287
    For example, specifying the faces of a cubemap could look like the following:
3288
3289
    \code
3290
        QImage faces[6];
3291
        // ...
3292
        QVarLengthArray<QRhiTextureUploadEntry, 6> entries;
3293
        for (int i = 0; i < 6; ++i)
3294
          entries.append(QRhiTextureUploadEntry(i, 0, faces[i]));
3295
        QRhiTextureUploadDescription desc;
3296
        desc.setEntries(entries.cbegin(), entries.cend());
3297
        resourceUpdates->uploadTexture(texture, desc);
3298
    \endcode
3299
3300
    Another example that specifies mip images for a compressed texture:
3301
3302
    \code
3303
        QList<QRhiTextureUploadEntry> entries;
3304
        const int mipCount = rhi->mipLevelsForSize(compressedTexture->pixelSize());
3305
        for (int level = 0; level < mipCount; ++level) {
3306
            const QByteArray compressedDataForLevel = ..
3307
            entries.append(QRhiTextureUploadEntry(0, level, compressedDataForLevel));
3308
        }
3309
        QRhiTextureUploadDescription desc;
3310
        desc.setEntries(entries.cbegin(), entries.cend());
3311
        resourceUpdates->uploadTexture(compressedTexture, desc);
3312
    \endcode
3313
3314
    With partial uploads targeting the same subresource, it is recommended to
3315
    batch them into a single upload request, whenever possible:
3316
3317
    \code
3318
      QRhiTextureSubresourceUploadDescription subresDesc(image);
3319
      subresDesc.setSourceSize(QSize(10, 10));
3320
      subResDesc.setDestinationTopLeft(QPoint(50, 40));
3321
      QRhiTextureUploadEntry entry(0, 0, subresDesc); // layer 0, level 0
3322
3323
      QRhiTextureSubresourceUploadDescription subresDesc2(image);
3324
      subresDesc2.setSourceSize(QSize(30, 40));
3325
      subResDesc2.setDestinationTopLeft(QPoint(100, 200));
3326
      QRhiTextureUploadEntry entry2(0, 0, subresDesc2); // layer 0, level 0, i.e. same subresource
3327
3328
      QRhiTextureUploadDescription desc({ entry, entry2});
3329
      resourceUpdates->uploadTexture(texture, desc);
3330
    \endcode
3331
3332
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3333
    for details.
3334
3335
    \sa QRhiResourceUpdateBatch
3336
 */
3337
3338
/*!
3339
    \fn QRhiTextureUploadDescription::QRhiTextureUploadDescription()
3340
3341
    Constructs an empty texture upload description.
3342
 */
3343
3344
/*!
3345
    Constructs a texture upload description with a single subresource upload
3346
    described by \a entry.
3347
 */
3348
QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry)
3349
0
{
3350
0
    m_entries.append(entry);
3351
0
}
3352
3353
/*!
3354
    Constructs a texture upload description with the specified \a list of entries.
3355
3356
    \note \a list can also contain multiple QRhiTextureUploadEntry elements
3357
    with the same layer and level. This makes sense when those uploads are
3358
    partial, meaning their subresource description has a source size or image
3359
    smaller than the subresource dimensions, and can be more efficient than
3360
    issuing separate uploadTexture()'s.
3361
 */
3362
QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list)
3363
0
    : m_entries(list)
3364
0
{
3365
0
}
3366
3367
/*!
3368
    \fn void QRhiTextureUploadDescription::setEntries(std::initializer_list<QRhiTextureUploadEntry> list)
3369
    Sets the \a list of entries.
3370
 */
3371
3372
/*!
3373
    \fn template<typename InputIterator> void QRhiTextureUploadDescription::setEntries(InputIterator first, InputIterator last)
3374
    Sets the list of entries using the iterators \a first and \a last.
3375
 */
3376
3377
/*!
3378
    \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cbeginEntries() const
3379
    \return a const iterator pointing to the first item in the entry list.
3380
 */
3381
3382
/*!
3383
    \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cendEntries() const
3384
    \return a const iterator pointing just after the last item in the entry list.
3385
 */
3386
3387
/*!
3388
    \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::entryAt(qsizetype index) const
3389
    \return the entry at \a index.
3390
 */
3391
3392
/*!
3393
    \fn qsizetype QRhiTextureUploadDescription::entryCount() const
3394
    \return the number of entries.
3395
 */
3396
3397
/*!
3398
    \class QRhiTextureCopyDescription
3399
    \inmodule QtGuiPrivate
3400
    \inheaderfile rhi/qrhi.h
3401
    \since 6.6
3402
    \brief Describes a texture-to-texture copy operation.
3403
3404
    An empty pixelSize() indicates that the entire subresource is to be copied.
3405
    A default constructed copy description therefore leads to copying the
3406
    entire subresource at level 0 of layer 0.
3407
3408
    \note The source texture must be created with
3409
    QRhiTexture::UsedAsTransferSource.
3410
3411
    \note The source and destination rectangles defined by pixelSize(),
3412
    sourceTopLeft(), and destinationTopLeft() must fit the source and
3413
    destination textures, respectively. The behavior is undefined otherwise.
3414
3415
    With cubemaps, 3D textures, and texture arrays one face or slice can be
3416
    copied at a time. The face or slice is specified by the source and
3417
    destination layer indices.  With mipmapped textures one mip level can be
3418
    copied at a time. The source and destination layer and mip level indices can
3419
    differ, but the size and position must be carefully controlled to avoid out
3420
    of bounds copies, in which case the behavior is undefined.
3421
3422
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3423
    for details.
3424
 */
3425
3426
/*!
3427
    \fn QRhiTextureCopyDescription::QRhiTextureCopyDescription()
3428
3429
    Constructs an empty texture copy description.
3430
 */
3431
3432
/*!
3433
    \fn QSize QRhiTextureCopyDescription::pixelSize() const
3434
    \return the size of the region to copy.
3435
3436
    \note An empty pixelSize() indicates that the entire subresource is to be
3437
    copied. A default constructed copy description therefore leads to copying
3438
    the entire subresource at level 0 of layer 0.
3439
 */
3440
3441
/*!
3442
    \fn void QRhiTextureCopyDescription::setPixelSize(const QSize &sz)
3443
    Sets the size of the region to copy to \a sz.
3444
 */
3445
3446
/*!
3447
    \fn int QRhiTextureCopyDescription::sourceLayer() const
3448
    \return the source array layer (cubemap face or array layer index). Defaults to 0.
3449
 */
3450
3451
/*!
3452
    \fn void QRhiTextureCopyDescription::setSourceLayer(int layer)
3453
    Sets the source array \a layer.
3454
 */
3455
3456
/*!
3457
    \fn int QRhiTextureCopyDescription::sourceLevel() const
3458
    \return the source mip level. Defaults to 0.
3459
 */
3460
3461
/*!
3462
    \fn void QRhiTextureCopyDescription::setSourceLevel(int level)
3463
    Sets the source mip \a level.
3464
 */
3465
3466
/*!
3467
    \fn QPoint QRhiTextureCopyDescription::sourceTopLeft() const
3468
    \return the source top-left position (in pixels). Defaults to (0, 0).
3469
 */
3470
3471
/*!
3472
    \fn void QRhiTextureCopyDescription::setSourceTopLeft(const QPoint &p)
3473
    Sets the source top-left position to \a p.
3474
 */
3475
3476
/*!
3477
    \fn int QRhiTextureCopyDescription::destinationLayer() const
3478
    \return the destination array layer (cubemap face or array layer index). Default to 0.
3479
 */
3480
3481
/*!
3482
    \fn void QRhiTextureCopyDescription::setDestinationLayer(int layer)
3483
    Sets the destination array \a layer.
3484
 */
3485
3486
/*!
3487
    \fn int QRhiTextureCopyDescription::destinationLevel() const
3488
    \return the destionation mip level. Defaults to 0.
3489
 */
3490
3491
/*!
3492
    \fn void QRhiTextureCopyDescription::setDestinationLevel(int level)
3493
    Sets the destination mip \a level.
3494
 */
3495
3496
/*!
3497
    \fn QPoint QRhiTextureCopyDescription::destinationTopLeft() const
3498
    \return the destionation top-left position in pixels. Defaults to (0, 0).
3499
 */
3500
3501
/*!
3502
    \fn void QRhiTextureCopyDescription::setDestinationTopLeft(const QPoint &p)
3503
    Sets the destination top-left position \a p.
3504
 */
3505
3506
/*!
3507
    \class QRhiReadbackDescription
3508
    \inmodule QtGuiPrivate
3509
    \inheaderfile rhi/qrhi.h
3510
    \since 6.6
3511
    \brief Describes a readback (reading back texture contents from possibly GPU-only memory) operation.
3512
3513
    The source of the readback operation is either a QRhiTexture or the
3514
    current backbuffer of the currently targeted QRhiSwapChain. When
3515
    texture() is not set, the swapchain is used. Otherwise the specified
3516
    QRhiTexture is treated as the source.
3517
3518
    \note Textures used in readbacks must be created with
3519
    QRhiTexture::UsedAsTransferSource.
3520
3521
    \note Swapchains used in readbacks must be created with
3522
    QRhiSwapChain::UsedAsTransferSource.
3523
3524
    layer() and level() are only applicable when the source is a QRhiTexture.
3525
3526
    \note Multisample textures cannot be read back. Readbacks are supported for
3527
    multisample swapchain buffers however.
3528
3529
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3530
    for details.
3531
 */
3532
3533
/*!
3534
    \fn QRhiReadbackDescription::QRhiReadbackDescription() = default
3535
3536
    Constructs an empty texture readback description.
3537
3538
    \note The source texture is set to null by default, which is still a valid
3539
    readback: it specifies that the backbuffer of the current swapchain is to
3540
    be read back. (current meaning the frame's target swapchain at the time of
3541
    committing the QRhiResourceUpdateBatch with the
3542
    \l{QRhiResourceUpdateBatch::readBackTexture()}{texture readback} on it)
3543
 */
3544
3545
/*!
3546
    Constructs an texture readback description that specifies that level 0 of
3547
    layer 0 of \a texture is to be read back.
3548
3549
    \note \a texture can also be null in which case this constructor is
3550
    identical to the argumentless variant.
3551
 */
3552
QRhiReadbackDescription::QRhiReadbackDescription(QRhiTexture *texture)
3553
0
    : m_texture(texture)
3554
0
{
3555
0
}
3556
3557
/*!
3558
    \fn QRhiTexture *QRhiReadbackDescription::texture() const
3559
3560
    \return the QRhiTexture that is read back. Can be left set to \nullptr
3561
    which indicates that the backbuffer of the current swapchain is to be used
3562
    instead.
3563
 */
3564
3565
/*!
3566
    \fn void QRhiReadbackDescription::setTexture(QRhiTexture *tex)
3567
3568
    Sets the texture \a tex as the source of the readback operation.
3569
3570
    Setting \nullptr is valid too, in which case the current swapchain's
3571
    current backbuffer is used. (but then the readback cannot be issued in a
3572
    non-swapchain-based frame)
3573
3574
    \note Multisample textures cannot be read back. Readbacks are supported for
3575
    multisample swapchain buffers however.
3576
3577
    \note Textures used in readbacks must be created with
3578
    QRhiTexture::UsedAsTransferSource.
3579
3580
    \note Swapchains used in readbacks must be created with
3581
    QRhiSwapChain::UsedAsTransferSource.
3582
 */
3583
3584
/*!
3585
    \fn int QRhiReadbackDescription::layer() const
3586
3587
    \return the currently set array layer (cubemap face, array index). Defaults to 0.
3588
3589
    Applicable only when the source of the readback is a QRhiTexture.
3590
 */
3591
3592
/*!
3593
    \fn void QRhiReadbackDescription::setLayer(int layer)
3594
    Sets the array \a layer to read back.
3595
 */
3596
3597
/*!
3598
    \fn int QRhiReadbackDescription::level() const
3599
3600
    \return the currently set mip level. Defaults to 0.
3601
3602
    Applicable only when the source of the readback is a QRhiTexture.
3603
 */
3604
3605
/*!
3606
    \fn void QRhiReadbackDescription::setLevel(int level)
3607
    Sets the mip \a level to read back.
3608
 */
3609
3610
/*!
3611
    \fn const QRect &QRhiReadbackDescription::rect() const
3612
    \since 6.10
3613
3614
    \return the rectangle to read back. Defaults to an invalid rectangle.
3615
3616
    If invalid, the entire texture or swapchain backbuffer is read back.
3617
 */
3618
3619
/*!
3620
    \fn void QRhiReadbackDescription::setRect(const QRect &rectangle)
3621
    \since 6.10
3622
3623
    Sets the \a rectangle to read back.
3624
 */
3625
3626
/*!
3627
    \class QRhiReadbackResult
3628
    \inmodule QtGuiPrivate
3629
    \inheaderfile rhi/qrhi.h
3630
    \since 6.6
3631
    \brief Describes the results of a potentially asynchronous buffer or texture readback operation.
3632
3633
    When \l completed is set, the function is invoked when the \l data is
3634
    available. \l format and \l pixelSize are set upon completion together with
3635
    \l data.
3636
3637
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3638
    for details.
3639
 */
3640
3641
/*!
3642
    \variable QRhiReadbackResult::completed
3643
3644
    Callback that is invoked upon completion, on the thread the QRhi operates
3645
    on. Can be left set to \nullptr, in which case no callback is invoked.
3646
 */
3647
3648
/*!
3649
    \variable QRhiReadbackResult::format
3650
3651
    Valid only for textures, the texture format.
3652
 */
3653
3654
/*!
3655
    \variable QRhiReadbackResult::pixelSize
3656
3657
    Valid only for textures, the size in pixels.
3658
 */
3659
3660
/*!
3661
    \variable QRhiReadbackResult::data
3662
3663
    The buffer or image data.
3664
3665
    \sa QRhiResourceUpdateBatch::readBackTexture(), QRhiResourceUpdateBatch::readBackBuffer()
3666
 */
3667
3668
3669
/*!
3670
    \class QRhiNativeHandles
3671
    \inmodule QtGuiPrivate
3672
    \inheaderfile rhi/qrhi.h
3673
    \since 6.6
3674
    \brief Base class for classes exposing backend-specific collections of native resource objects.
3675
3676
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3677
    for details.
3678
 */
3679
3680
/*!
3681
    \class QRhiResource
3682
    \inmodule QtGuiPrivate
3683
    \inheaderfile rhi/qrhi.h
3684
    \since 6.6
3685
    \brief Base class for classes encapsulating native resource objects.
3686
3687
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3688
    for details.
3689
 */
3690
3691
/*!
3692
    \enum QRhiResource::Type
3693
    Specifies type of the resource.
3694
3695
    \value Buffer
3696
    \value Texture
3697
    \value Sampler
3698
    \value RenderBuffer
3699
    \value RenderPassDescriptor
3700
    \value SwapChainRenderTarget
3701
    \value TextureRenderTarget
3702
    \value ShaderResourceBindings
3703
    \value GraphicsPipeline
3704
    \value SwapChain
3705
    \value ComputePipeline
3706
    \value CommandBuffer
3707
    \value ShadingRateMap
3708
 */
3709
3710
/*!
3711
    \fn virtual QRhiResource::Type QRhiResource::resourceType() const = 0
3712
3713
    \return the type of the resource.
3714
 */
3715
3716
/*!
3717
    \internal
3718
 */
3719
QRhiResource::QRhiResource(QRhiImplementation *rhi)
3720
0
    : m_rhi(rhi)
3721
0
{
3722
0
    m_id = QRhiGlobalObjectIdGenerator::newId();
3723
0
}
3724
3725
/*!
3726
    Destructor.
3727
3728
    Releases (or requests deferred releasing of) the underlying native graphics
3729
    resources, if there are any.
3730
3731
    \note Resources referenced by commands for the current frame should not be
3732
    released until the frame is submitted by QRhi::endFrame().
3733
3734
    \sa destroy()
3735
 */
3736
QRhiResource::~QRhiResource()
3737
0
{
3738
    // destroy() cannot be called here, due to virtuals; it is up to the
3739
    // subclasses to do that.
3740
0
}
3741
3742
/*!
3743
    \fn virtual void QRhiResource::destroy() = 0
3744
3745
    Releases (or requests deferred releasing of) the underlying native graphics
3746
    resources. Safe to call multiple times, subsequent invocations will be a
3747
    no-op then.
3748
3749
    Once destroy() is called, the QRhiResource instance can be reused, by
3750
    calling \c create() again. That will then result in creating new native
3751
    graphics resources underneath.
3752
3753
    \note Resources referenced by commands for the current frame should not be
3754
    released until the frame is submitted by QRhi::endFrame().
3755
3756
    The QRhiResource destructor also performs the same task, so calling this
3757
    function is not necessary before deleting a QRhiResource.
3758
3759
    \sa deleteLater()
3760
 */
3761
3762
/*!
3763
    When called without a frame being recorded, this function is equivalent to
3764
    deleting the object. Between a QRhi::beginFrame() and QRhi::endFrame()
3765
    however the behavior is different: the QRhiResource will not be destroyed
3766
    until the frame is submitted via QRhi::endFrame(), thus satisfying the QRhi
3767
    requirement of not altering QRhiResource objects that are referenced by the
3768
    frame being recorded.
3769
3770
    If the QRhi that created this object is already destroyed, the object is
3771
    deleted immediately.
3772
3773
    Using deleteLater() can be a useful convenience in many cases, and it
3774
    complements the low-level guarantee (that the underlying native graphics
3775
    objects are never destroyed until it is safe to do so and it is known for
3776
    sure that they are not used by the GPU in an still in-flight frame), by
3777
    offering a way to make sure the C++ object instances (of QRhiBuffer,
3778
    QRhiTexture, etc.) themselves also stay valid until the end of the current
3779
    frame.
3780
3781
    The following example shows a convenient way of creating a throwaway buffer
3782
    that is only used in one frame and gets automatically released in
3783
    endFrame(). (when it comes to the underlying native buffer(s), the usual
3784
    guarantee applies: the QRhi backend defers the releasing of those until it
3785
    is guaranteed that the frame in which the buffer is accessed by the GPU has
3786
    completed)
3787
3788
    \code
3789
        rhi->beginFrame(swapchain);
3790
        QRhiBuffer *buf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, 256);
3791
        buf->deleteLater(); // !
3792
        u = rhi->nextResourceUpdateBatch();
3793
        u->uploadStaticBuffer(buf, data);
3794
        // ... draw with buf
3795
        rhi->endFrame();
3796
    \endcode
3797
3798
    \sa destroy()
3799
 */
3800
void QRhiResource::deleteLater()
3801
0
{
3802
0
    if (m_rhi)
3803
0
        m_rhi->addDeleteLater(this);
3804
0
    else
3805
0
        delete this;
3806
0
}
3807
3808
/*!
3809
    \return the currently set object name. By default the name is empty.
3810
 */
3811
QByteArray QRhiResource::name() const
3812
0
{
3813
0
    return m_objectName;
3814
0
}
3815
3816
/*!
3817
    Sets a \a name for the object.
3818
3819
    This allows getting descriptive names for the native graphics
3820
    resources visible in graphics debugging tools, such as
3821
    \l{https://renderdoc.org/}{RenderDoc} and
3822
    \l{https://developer.apple.com/xcode/}{XCode}.
3823
3824
    When it comes to naming native objects by relaying the name via the
3825
    appropriate graphics API, note that the name is ignored when
3826
    QRhi::DebugMarkers are not supported, and may, depending on the backend,
3827
    also be ignored when QRhi::EnableDebugMarkers is not set.
3828
3829
    \note The name may be ignored for objects other than buffers,
3830
    renderbuffers, and textures, depending on the backend.
3831
3832
    \note The name may be modified. For slotted resources, such as a QRhiBuffer
3833
    backed by multiple native buffers, QRhi will append a suffix to make the
3834
    underlying native buffers easily distinguishable from each other.
3835
 */
3836
void QRhiResource::setName(const QByteArray &name)
3837
0
{
3838
0
    m_objectName = name;
3839
0
}
3840
3841
/*!
3842
    \return the global, unique identifier of this QRhiResource.
3843
3844
    User code rarely needs to deal with the value directly. It is used
3845
    internally for tracking and bookkeeping purposes.
3846
 */
3847
quint64 QRhiResource::globalResourceId() const
3848
0
{
3849
0
    return m_id;
3850
0
}
3851
3852
/*!
3853
    \return the QRhi that created this resource.
3854
3855
    If the QRhi that created this object is already destroyed, the result is
3856
    \nullptr.
3857
 */
3858
QRhi *QRhiResource::rhi() const
3859
0
{
3860
0
    return m_rhi ? m_rhi->q : nullptr;
3861
0
}
3862
3863
/*!
3864
    \class QRhiBuffer
3865
    \inmodule QtGuiPrivate
3866
    \inheaderfile rhi/qrhi.h
3867
    \since 6.6
3868
    \brief Vertex, index, or uniform (constant) buffer resource.
3869
3870
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
3871
    for details.
3872
3873
    A QRhiBuffer encapsulates zero, one, or more native buffer objects (such as
3874
    a \c VkBuffer or \c MTLBuffer). With some graphics APIs and backends
3875
    certain types of buffers may not use a native buffer object at all (e.g.
3876
    OpenGL if uniform buffer objects are not used), but this is transparent to
3877
    the user of the QRhiBuffer API. Similarly, the fact that some types of
3878
    buffers may use two or three native buffers underneath, in order to allow
3879
    efficient per-frame content update without stalling the GPU pipeline, is
3880
    mostly invisible to the applications and libraries.
3881
3882
    A QRhiBuffer instance is always created by calling
3883
    \l{QRhi::newBuffer()}{the QRhi's newBuffer() function}. This creates no
3884
    native graphics resources. To do that, call create() after setting the
3885
    appropriate options, such as the type, usage flags, size, although in most cases these
3886
    are already set based on the arguments passed to
3887
    \l{QRhi::newBuffer()}{newBuffer()}.
3888
3889
    \section2 Example usage
3890
3891
    To create a uniform buffer for a shader where the GLSL uniform block
3892
    contains a single \c mat4 member, and update the contents:
3893
3894
    \code
3895
        QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64);
3896
        if (!ubuf->create()) { error(); }
3897
        QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3898
        QMatrix4x4 mvp;
3899
        // ... set up the modelview-projection matrix
3900
        batch->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
3901
        // ...
3902
        commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
3903
    \endcode
3904
3905
    An example of creating a buffer with vertex data:
3906
3907
    \code
3908
        const float vertices[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f };
3909
        QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices));
3910
        if (!vbuf->create()) { error(); }
3911
        QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3912
        batch->uploadStaticBuffer(vbuf, vertices);
3913
        // ...
3914
        commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
3915
    \endcode
3916
3917
    An index buffer:
3918
3919
    \code
3920
        static const quint16 indices[] = { 0, 1, 2 };
3921
        QRhiBuffer *ibuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices));
3922
        if (!ibuf->create()) { error(); }
3923
        QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3924
        batch->uploadStaticBuffer(ibuf, indices);
3925
        // ...
3926
        commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
3927
    \endcode
3928
3929
    \section2 Common patterns
3930
3931
    A call to create() destroys any existing native resources if create() was
3932
    successfully called before. If those native resources are still in use by
3933
    an in-flight frame (i.e., there's a chance they are still read by the GPU),
3934
    the destroying of those resources is deferred automatically. Thus a very
3935
    common and convenient pattern to safely increase the size of an already
3936
    initialized buffer is the following. In practice this drops and creates a
3937
    whole new set of native resources underneath, so it is not necessarily a
3938
    cheap operation, but is more convenient and still faster than the
3939
    alternatives, because by not destroying the \c buf object itself, all
3940
    references to it stay valid in other data structures (e.g., in any
3941
    QRhiShaderResourceBinding the QRhiBuffer is referenced from).
3942
3943
    \code
3944
        if (buf->size() < newSize) {
3945
            buf->setSize(newSize);
3946
            if (!buf->create()) { error(); }
3947
        }
3948
        // continue using buf, fill it with new data
3949
    \endcode
3950
3951
    When working with uniform buffers, it will sometimes be necessary to
3952
    combine data for multiple draw calls into a single buffer for efficiency
3953
    reasons. Be aware of the aligment requirements: with some graphics APIs
3954
    offsets for a uniform buffer must be aligned to 256 bytes. This applies
3955
    both to QRhiShaderResourceBinding and to the dynamic offsets passed to
3956
    \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}. Use the
3957
    \l{QRhi::ubufAlignment()}{ubufAlignment()} and
3958
    \l{QRhi::ubufAligned()}{ubufAligned()} functions to create portable code.
3959
    As an example, the following is an outline for issuing multiple (\c N) draw
3960
    calls with the same pipeline and geometry, but with a different data in the
3961
    uniform buffers exposed at binding point 0. This assumes the buffer is
3962
    exposed via
3963
    \l{QRhiShaderResourceBinding::uniformBufferWithDynamicOffset()}{uniformBufferWithDynamicOffset()}
3964
    which allows passing a QRhiCommandBuffer::DynamicOffset list to
3965
    \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}.
3966
3967
    \code
3968
        const int N = 2;
3969
        const int UB_SIZE = 64 + 4; // assuming a uniform block with { mat4 matrix; float opacity; }
3970
        const int ONE_UBUF_SIZE = rhi->ubufAligned(UB_SIZE);
3971
        const int TOTAL_UBUF_SIZE = N * ONE_UBUF_SIZE;
3972
        QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, TOTAL_UBUF_SIZE);
3973
        if (!ubuf->create()) { error(); }
3974
        QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
3975
        for (int i = 0; i < N; ++i) {
3976
            batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE, 64, matrix.constData());
3977
            batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE + 64, 4, &opacity);
3978
        }
3979
        // ...
3980
        // beginPass(), set pipeline, etc., and then:
3981
        for (int i = 0; i < N; ++i) {
3982
            QRhiCommandBuffer::DynamicOffset dynOfs[] = { { 0, i * ONE_UBUF_SIZE } };
3983
            cb->setShaderResources(srb, 1, dynOfs);
3984
            cb->draw(36);
3985
        }
3986
    \endcode
3987
3988
    \sa QRhiResourceUpdateBatch, QRhi, QRhiCommandBuffer
3989
 */
3990
3991
/*!
3992
    \enum QRhiBuffer::Type
3993
    Specifies storage type of buffer resource.
3994
3995
    \value Immutable Indicates that the data is not expected to change ever
3996
    after the initial upload. Under the hood such buffer resources are
3997
    typically placed in device local (GPU) memory (on systems where
3998
    applicable). Uploading new data is possible, but may be expensive. The
3999
    upload typically happens by copying to a separate, host visible staging
4000
    buffer from which a GPU buffer-to-buffer copy is issued into the actual
4001
    GPU-only buffer.
4002
4003
    \value Static Indicates that the data is expected to change only
4004
    infrequently. Typically placed in device local (GPU) memory, where
4005
    applicable. On backends where host visible staging buffers are used for
4006
    uploading, the staging buffers are kept around for this type, unlike with
4007
    Immutable, so subsequent uploads do not suffer in performance. Frequent
4008
    updates, especially updates in consecutive frames, should be avoided.
4009
4010
    \value Dynamic Indicates that the data is expected to change frequently.
4011
    Not recommended for large buffers. Typically backed by host visible memory
4012
    in 2 copies in order to allow for changing without stalling the graphics
4013
    pipeline. The double buffering is managed transparently to the applications
4014
    and is not exposed in the API here in any form. This is the recommended,
4015
    and, with some backends, the only possible, type for buffers with
4016
    UniformBuffer usage.
4017
 */
4018
4019
/*!
4020
    \enum QRhiBuffer::UsageFlag
4021
    Flag values to specify how the buffer is going to be used.
4022
4023
    \value VertexBuffer Vertex buffer. This allows the QRhiBuffer to be used in
4024
    \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
4025
4026
    \value IndexBuffer Index buffer. This allows the QRhiBuffer to be used in
4027
    \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
4028
4029
    \value UniformBuffer Uniform buffer (also called constant buffer). This
4030
    allows the QRhiBuffer to be used in combination with
4031
    \l{QRhiShaderResourceBinding::UniformBuffer}{UniformBuffer}. When
4032
    \l{QRhi::NonDynamicUniformBuffers}{NonDynamicUniformBuffers} is reported as
4033
    not supported, this usage can only be combined with the type Dynamic.
4034
4035
    \value StorageBuffer Storage buffer. This allows the QRhiBuffer to be used
4036
    in combination with \l{QRhiShaderResourceBinding::BufferLoad}{BufferLoad},
4037
    \l{QRhiShaderResourceBinding::BufferStore}{BufferStore}, or
4038
    \l{QRhiShaderResourceBinding::BufferLoadStore}{BufferLoadStore}. This usage
4039
    can only be combined with the types Immutable or Static, and is only
4040
    available when the \l{QRhi::Compute}{Compute feature} is reported as
4041
    supported.
4042
4043
    \value [since 6.12] IndirectBuffer Indirect draw buffer. This allows the
4044
    QRhiBuffer to be used in \l{QRhiCommandBuffer::drawIndirect()}{drawIndirect()}
4045
    and \l{QRhiCommandBuffer::drawIndexedIndirect()}{drawIndexedIndirect()}.
4046
    This usage can be combined with types Immutable or Static. Combining it with
4047
    Dynamic is unsupported with D3D11, where create() will fail. This usage may
4048
    also be combined with StorageBuffer on backends that support
4049
    \l{QRhi::Compute}{compute shaders}, allowing indirect draw commands to be
4050
    generated by compute shaders and consumed by indirect draw calls.
4051
 */
4052
4053
/*!
4054
    \class QRhiBuffer::NativeBuffer
4055
    \inmodule QtGuiPrivate
4056
    \inheaderfile rhi/qrhi.h
4057
    \brief Contains information about the underlying native resources of a buffer.
4058
 */
4059
4060
/*!
4061
    \variable QRhiBuffer::NativeBuffer::objects
4062
    \brief an array with pointers to the native object handles.
4063
4064
    With OpenGL, the native handle is a GLuint value, so the elements in the \c
4065
    objects array are pointers to a GLuint. With Vulkan, the native handle is a
4066
    VkBuffer, so the elements of the array are pointers to a VkBuffer. With
4067
    Direct3D 11 and Metal the elements are pointers to a ID3D11Buffer or
4068
    MTLBuffer pointer, respectively. With Direct3D 12, the elements are
4069
    pointers to a ID3D12Resource.
4070
4071
    \note Pay attention to the fact that the elements are always pointers to
4072
    the native buffer handle type, even if the native type itself is a pointer.
4073
    (so the elements are \c{VkBuffer *} on Vulkan, even though VkBuffer itself
4074
    is a pointer on 64-bit architectures).
4075
 */
4076
4077
/*!
4078
    \variable QRhiBuffer::NativeBuffer::slotCount
4079
    \brief Specifies the number of valid elements in the objects array.
4080
4081
    The value can be 0, 1, 2, or 3 in practice. 0 indicates that the QRhiBuffer
4082
    is not backed by any native buffer objects. This can happen with
4083
    QRhiBuffers with the usage UniformBuffer when the underlying API does not
4084
    support (or the backend chooses not to use) native uniform buffers. 1 is
4085
    commonly used for Immutable and Static types (but some backends may
4086
    differ). 2 or 3 is typical when the type is Dynamic (but some backends may
4087
    differ).
4088
4089
    \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4090
 */
4091
4092
/*!
4093
    \internal
4094
 */
4095
QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, quint32 size_)
4096
0
    : QRhiResource(rhi),
4097
0
      m_type(type_), m_usage(usage_), m_size(size_)
4098
0
{
4099
0
}
4100
4101
/*!
4102
    \return the resource type.
4103
 */
4104
QRhiResource::Type QRhiBuffer::resourceType() const
4105
0
{
4106
0
    return Buffer;
4107
0
}
4108
4109
/*!
4110
    \fn virtual bool QRhiBuffer::create() = 0
4111
4112
    Creates the corresponding native graphics resources. If there are already
4113
    resources present due to an earlier create() with no corresponding
4114
    destroy(), then destroy() is called implicitly first.
4115
4116
    \return \c true when successful, \c false when a graphics operation failed.
4117
    Regardless of the return value, calling destroy() is always safe.
4118
 */
4119
4120
/*!
4121
    \fn QRhiBuffer::Type QRhiBuffer::type() const
4122
    \return the buffer type.
4123
 */
4124
4125
/*!
4126
    \fn void QRhiBuffer::setType(Type t)
4127
    Sets the buffer's type to \a t.
4128
 */
4129
4130
/*!
4131
    \fn QRhiBuffer::UsageFlags QRhiBuffer::usage() const
4132
    \return the buffer's usage flags.
4133
 */
4134
4135
/*!
4136
    \fn void QRhiBuffer::setUsage(UsageFlags u)
4137
    Sets the buffer's usage flags to \a u.
4138
 */
4139
4140
/*!
4141
    \fn quint32 QRhiBuffer::size() const
4142
4143
    \return the buffer's size in bytes.
4144
4145
    This is always the value that was passed to setSize() or QRhi::newBuffer().
4146
    Internally, the native buffers may be bigger if that is required by the
4147
    underlying graphics API.
4148
 */
4149
4150
/*!
4151
    \fn void QRhiBuffer::setSize(quint32 sz)
4152
4153
    Sets the size of the buffer in bytes. The size is normally specified in
4154
    QRhi::newBuffer() so this function is only used when the size has to be
4155
    changed. As with other setters, the size only takes effect when calling
4156
    create(), and for already created buffers this involves releasing the previous
4157
    native resource and creating new ones under the hood.
4158
4159
    Backends may choose to allocate buffers bigger than \a sz in order to
4160
    fulfill alignment requirements. This is hidden from the applications and
4161
    size() will always report the size requested in \a sz.
4162
 */
4163
4164
/*!
4165
    \return the underlying native resources for this buffer. The returned value
4166
    will be empty if exposing the underlying native resources is not supported by
4167
    the backend.
4168
4169
    A QRhiBuffer may be backed by multiple native buffer objects, depending on
4170
    the type() and the QRhi backend in use. When this is the case, all of them
4171
    are returned in the objects array in the returned struct, with slotCount
4172
    specifying the number of native buffer objects. While
4173
    \l{QRhi::beginFrame()}{recording a frame}, QRhi::currentFrameSlot() can be
4174
    used to determine which of the native buffers QRhi is using for operations
4175
    that read or write from this QRhiBuffer within the frame being recorded.
4176
4177
    In some cases a QRhiBuffer will not be backed by a native buffer object at
4178
    all. In this case slotCount will be set to 0 and no valid native objects
4179
    are returned. This is not an error, and is perfectly valid when a given
4180
    backend does not use native buffers for QRhiBuffers with certain types or
4181
    usages.
4182
4183
    \note Be aware that QRhi backends may employ various buffer update
4184
    strategies. Unlike textures, where uploading image data always means
4185
    recording a buffer-to-image (or similar) copy command on the command
4186
    buffer, buffers, in particular Dynamic and UniformBuffer ones, can operate
4187
    in many different ways. For example, a QRhiBuffer with usage type
4188
    UniformBuffer may not even be backed by a native buffer object at all if
4189
    uniform buffers are not used or supported by a given backend and graphics
4190
    API. There are also differences to how data is written to the buffer and
4191
    the type of backing memory used. For buffers backed by host visible memory,
4192
    calling this function guarantees that pending host writes are executed for
4193
    all the returned native buffers.
4194
4195
    \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
4196
 */
4197
QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
4198
0
{
4199
0
    return { {}, 0 };
4200
0
}
4201
4202
/*!
4203
    \return a pointer to a memory block with the host visible buffer data.
4204
4205
    This is a shortcut for medium-to-large dynamic uniform buffers that have
4206
    their \b entire contents (or at least all regions that are read by the
4207
    shaders in the current frame) changed \b{in every frame} and the
4208
    QRhiResourceUpdateBatch-based update mechanism is seen too heavy due to the
4209
    amount of data copying involved.
4210
4211
    The call to this function must be eventually followed by a call to
4212
    endFullDynamicUniformBufferUpdateForCurrentFrame(), before recording any
4213
    render or compute pass that relies on this buffer.
4214
4215
    \warning Updating data via this method is not compatible with
4216
    QRhiResourceUpdateBatch-based updates and readbacks. Unexpected behavior
4217
    may occur when attempting to combine the two update models for the same
4218
    buffer. Similarly, the data updated this direct way may not be visible to
4219
    \l{QRhiResourceUpdateBatch::readBackBuffer()}{readBackBuffer operations},
4220
    depending on the backend.
4221
4222
    \warning When updating buffer data via this method, the update must be done
4223
    in every frame, otherwise backends that perform double or triple buffering
4224
    of resources may end up in unexpected behavior.
4225
4226
    \warning Partial updates are not possible with this approach since some
4227
    backends may choose a strategy where the previous contents of the buffer is
4228
    lost upon calling this function. Data must be written to all regions that
4229
    are read by shaders in the frame currently being prepared.
4230
4231
    \warning This function can only be called when recording a frame, so
4232
    between QRhi::beginFrame() and QRhi::endFrame().
4233
4234
    \warning This function can only be called on Dynamic buffers.
4235
 */
4236
char *QRhiBuffer::beginFullDynamicBufferUpdateForCurrentFrame()
4237
0
{
4238
0
    return nullptr;
4239
0
}
4240
4241
/*!
4242
    To be called when the entire contents of the buffer data has been updated
4243
    in the memory block returned from
4244
    beginFullDynamicBufferUpdateForCurrentFrame().
4245
 */
4246
void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
4247
0
{
4248
0
}
4249
4250
/*!
4251
    \internal
4252
 */
4253
void QRhiBuffer::fullDynamicBufferUpdateForCurrentFrame(const void *data, quint32 size)
4254
0
{
4255
0
    char *p = beginFullDynamicBufferUpdateForCurrentFrame();
4256
0
    if (p) {
4257
0
        memcpy(p, data, size > 0 ? size : m_size);
4258
0
        endFullDynamicBufferUpdateForCurrentFrame();
4259
0
    }
4260
0
}
4261
4262
/*!
4263
    \class QRhiRenderBuffer
4264
    \inmodule QtGuiPrivate
4265
    \inheaderfile rhi/qrhi.h
4266
    \since 6.6
4267
    \brief Renderbuffer resource.
4268
4269
    Renderbuffers cannot be sampled or read but have some benefits over
4270
    textures in some cases:
4271
4272
    A \l DepthStencil renderbuffer may be lazily allocated and be backed by
4273
    transient memory with some APIs. On some platforms this may mean the
4274
    depth/stencil buffer uses no physical backing at all.
4275
4276
    \l Color renderbuffers are useful since QRhi::MultisampleRenderBuffer may be
4277
    supported even when QRhi::MultisampleTexture is not.
4278
4279
    How the renderbuffer is implemented by a backend is not exposed to the
4280
    applications. In some cases it may be backed by ordinary textures, while in
4281
    others there may be a different kind of native resource used.
4282
4283
    Renderbuffers that are used as (and are only used as) depth-stencil buffers
4284
    in combination with a QRhiSwapChain's color buffers should have the
4285
    UsedWithSwapChainOnly flag set. This serves a double purpose: such buffers,
4286
    depending on the backend and the underlying APIs, be more efficient, and
4287
    QRhi provides automatic sizing behavior to match the color buffers, which
4288
    means calling setPixelSize() and create() are not necessary for such
4289
    renderbuffers.
4290
4291
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4292
    for details.
4293
 */
4294
4295
/*!
4296
    \enum QRhiRenderBuffer::Type
4297
    Specifies the type of the renderbuffer
4298
4299
    \value DepthStencil Combined depth/stencil
4300
    \value Color Color
4301
 */
4302
4303
/*!
4304
    \struct QRhiRenderBuffer::NativeRenderBuffer
4305
    \inmodule QtGuiPrivate
4306
    \inheaderfile rhi/qrhi.h
4307
    \brief Wraps a native renderbuffer object.
4308
 */
4309
4310
/*!
4311
    \variable QRhiRenderBuffer::NativeRenderBuffer::object
4312
    \brief 64-bit integer containing the native object handle.
4313
4314
    Used with QRhiRenderBuffer::createFrom().
4315
4316
    With OpenGL the native handle is a GLuint value. \c object is expected to
4317
    be a valid OpenGL renderbuffer object ID.
4318
 */
4319
4320
/*!
4321
    \enum QRhiRenderBuffer::Flag
4322
    Flag values for flags() and setFlags()
4323
4324
    \value UsedWithSwapChainOnly For DepthStencil renderbuffers this indicates
4325
    that the renderbuffer is only used in combination with a QRhiSwapChain, and
4326
    never in any other way. This provides automatic sizing and resource
4327
    rebuilding, so calling setPixelSize() or create() is not needed whenever
4328
    this flag is set. This flag value may also trigger backend-specific
4329
    behavior, for example with OpenGL, where a separate windowing system
4330
    interface API is in use (EGL, GLX, etc.), the flag is especially important
4331
    as it avoids creating any actual renderbuffer resource as there is already
4332
    a windowing system provided depth/stencil buffer as requested by
4333
    QSurfaceFormat.
4334
 */
4335
4336
/*!
4337
    \internal
4338
 */
4339
QRhiRenderBuffer::QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
4340
                                   int sampleCount_, Flags flags_,
4341
                                   QRhiTexture::Format backingFormatHint_)
4342
0
    : QRhiResource(rhi),
4343
0
      m_type(type_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_),
4344
0
      m_backingFormatHint(backingFormatHint_)
4345
0
{
4346
0
}
4347
4348
/*!
4349
    \return the resource type.
4350
 */
4351
QRhiResource::Type QRhiRenderBuffer::resourceType() const
4352
0
{
4353
0
    return RenderBuffer;
4354
0
}
4355
4356
/*!
4357
    \fn virtual bool QRhiRenderBuffer::create() = 0
4358
4359
    Creates the corresponding native graphics resources. If there are already
4360
    resources present due to an earlier create() with no corresponding
4361
    destroy(), then destroy() is called implicitly first.
4362
4363
    \return \c true when successful, \c false when a graphics operation failed.
4364
    Regardless of the return value, calling destroy() is always safe.
4365
 */
4366
4367
/*!
4368
    Similar to create() except that no new native renderbuffer objects are
4369
    created. Instead, the native renderbuffer object specified by \a src is
4370
    used.
4371
4372
    This allows importing an existing renderbuffer object (which must belong to
4373
    the same device or sharing context, depending on the graphics API) from an
4374
    external graphics engine.
4375
4376
    \note This is currently applicable to OpenGL only. This function exists
4377
    solely to allow importing a renderbuffer object that is bound to some
4378
    special, external object, such as an EGLImageKHR. Once the application
4379
    performed the glEGLImageTargetRenderbufferStorageOES call, the renderbuffer
4380
    object can be passed to this function to create a wrapping
4381
    QRhiRenderBuffer, which in turn can be passed in as a color attachment to
4382
    a QRhiTextureRenderTarget to enable rendering to the EGLImage.
4383
4384
    \note pixelSize(), sampleCount(), and flags() must still be set correctly.
4385
    Passing incorrect sizes and other values to QRhi::newRenderBuffer() and
4386
    then following it with a createFrom() expecting that the native
4387
    renderbuffer object alone is sufficient to deduce such values is \b wrong
4388
    and will lead to problems.
4389
4390
    \note QRhiRenderBuffer does not take ownership of the native object, and
4391
    destroy() will not release that object.
4392
4393
    \note This function is only implemented when the QRhi::RenderBufferImport
4394
    feature is reported as \l{QRhi::isFeatureSupported()}{supported}. Otherwise,
4395
    the function does nothing and the return value is \c false.
4396
4397
    \return \c true when successful, \c false when not supported.
4398
 */
4399
bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
4400
0
{
4401
0
    Q_UNUSED(src);
4402
0
    return false;
4403
0
}
4404
4405
/*!
4406
    \fn QRhiRenderBuffer::Type QRhiRenderBuffer::type() const
4407
    \return the renderbuffer type.
4408
 */
4409
4410
/*!
4411
    \fn void QRhiRenderBuffer::setType(Type t)
4412
    Sets the type to \a t.
4413
 */
4414
4415
/*!
4416
    \fn QSize QRhiRenderBuffer::pixelSize() const
4417
    \return the pixel size.
4418
 */
4419
4420
/*!
4421
    \fn void QRhiRenderBuffer::setPixelSize(const QSize &sz)
4422
    Sets the size (in pixels) to \a sz.
4423
 */
4424
4425
/*!
4426
    \fn int QRhiRenderBuffer::sampleCount() const
4427
    \return the sample count. 1 means no multisample antialiasing.
4428
 */
4429
4430
/*!
4431
    \fn void QRhiRenderBuffer::setSampleCount(int s)
4432
    Sets the sample count to \a s.
4433
 */
4434
4435
/*!
4436
    \fn QRhiRenderBuffer::Flags QRhiRenderBuffer::flags() const
4437
    \return the flags.
4438
 */
4439
4440
/*!
4441
    \fn void QRhiRenderBuffer::setFlags(Flags f)
4442
    Sets the flags to \a f.
4443
 */
4444
4445
/*!
4446
    \fn virtual QRhiTexture::Format QRhiRenderBuffer::backingFormat() const = 0
4447
4448
    \internal
4449
 */
4450
4451
/*!
4452
    \class QRhiTexture
4453
    \inmodule QtGuiPrivate
4454
    \inheaderfile rhi/qrhi.h
4455
    \since 6.6
4456
    \brief Texture resource.
4457
4458
    A QRhiTexture encapsulates a native texture object, such as a \c VkImage or
4459
    \c MTLTexture.
4460
4461
    A QRhiTexture instance is always created by calling
4462
    \l{QRhi::newTexture()}{the QRhi's newTexture() function}. This creates no
4463
    native graphics resources. To do that, call create() after setting the
4464
    appropriate options, such as the format and size, although in most cases
4465
    these are already set based on the arguments passed to
4466
    \l{QRhi::newTexture()}{newTexture()}.
4467
4468
    Setting the \l{QRhiTexture::Flags}{flags} correctly is essential, otherwise
4469
    various errors can occur depending on the underlying QRhi backend and
4470
    graphics API. For example, when a texture will be rendered into from a
4471
    render pass via QRhiTextureRenderTarget, the texture must be created with
4472
    the \l RenderTarget flag set. Similarly, when the texture is going to be
4473
    \l{QRhiResourceUpdateBatch::readBackTexture()}{read back}, the \l
4474
    UsedAsTransferSource flag must be set upfront. Mipmapped textures must have
4475
    the MipMapped flag set. And so on. It is not possible to change the flags
4476
    once create() has succeeded. To release the existing and create a new
4477
    native texture object with the changed settings, call the setters and call
4478
    create() again. This then might be a potentially expensive operation.
4479
4480
    \section2 Example usage
4481
4482
    To create a 2D texture with a size of 512x512 pixels and set its contents to all green:
4483
4484
    \code
4485
        QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512));
4486
        if (!texture->create()) { error(); }
4487
        QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
4488
        QImage image(512, 512, QImage::Format_RGBA8888);
4489
        image.fill(Qt::green);
4490
        batch->uploadTexture(texture, image);
4491
        // ...
4492
        commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
4493
    \endcode
4494
4495
    \section2 Common patterns
4496
4497
    A call to create() destroys any existing native resources if create() was
4498
    successfully called before. If those native resources are still in use by
4499
    an in-flight frame (i.e., there's a chance they are still read by the GPU),
4500
    the destroying of those resources is deferred automatically. Thus a very
4501
    common and convenient pattern to safely change the size of an already
4502
    existing texture is the following. In practice this drops and creates a
4503
    whole new native texture resource underneath, so it is not necessarily a
4504
    cheap operation, but is more convenient and still faster than the
4505
    alternatives, because by not destroying the \c texture object itself, all
4506
    references to it stay valid in other data structures (e.g., in any
4507
    QShaderResourceBinding the QRhiTexture is referenced from).
4508
4509
    \code
4510
        // determine newSize, e.g. based on the swapchain's output size or other factors
4511
        if (texture->pixelSize() != newSize) {
4512
            texture->setPixelSize(newSize);
4513
            if (!texture->create()) { error(); }
4514
        }
4515
        // continue using texture, fill it with new data
4516
    \endcode
4517
4518
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4519
    for details.
4520
4521
    \sa QRhiResourceUpdateBatch, QRhi, QRhiTextureRenderTarget
4522
 */
4523
4524
/*!
4525
    \enum QRhiTexture::Flag
4526
4527
    Flag values to specify how the texture is going to be used. Not honoring
4528
    the flags set before create() and attempting to use the texture in ways that
4529
    was not declared upfront can lead to unspecified behavior or decreased
4530
    performance depending on the backend and the underlying graphics API.
4531
4532
    \value RenderTarget The texture going to be used in combination with
4533
    QRhiTextureRenderTarget.
4534
4535
    \value CubeMap The texture is a cubemap. Such textures have 6 layers, one
4536
    for each face in the order of +X, -X, +Y, -Y, +Z, -Z. Cubemap textures
4537
    cannot be multisample.
4538
4539
     \value MipMapped The texture has mipmaps. The appropriate mip count is
4540
     calculated automatically and can also be retrieved via
4541
     QRhi::mipLevelsForSize(). The images for the mip levels have to be
4542
     provided in the texture uploaded or generated via
4543
     QRhiResourceUpdateBatch::generateMips(). Multisample textures cannot have
4544
     mipmaps.
4545
4546
    \value sRGB Use an sRGB format.
4547
4548
    \value UsedAsTransferSource The texture is used as the source of a texture
4549
    copy or readback, meaning the texture is given as the source in
4550
    QRhiResourceUpdateBatch::copyTexture() or
4551
    QRhiResourceUpdateBatch::readBackTexture().
4552
4553
     \value UsedWithGenerateMips The texture is going to be used with
4554
     QRhiResourceUpdateBatch::generateMips().
4555
4556
     \value UsedWithLoadStore The texture is going to be used with image
4557
     load/store operations, for example, in a compute shader.
4558
4559
     \value UsedAsCompressedAtlas The texture has a compressed format and the
4560
     dimensions of subresource uploads may not match the texture size.
4561
4562
     \value ExternalOES The texture should use the GL_TEXTURE_EXTERNAL_OES
4563
     target with OpenGL. This flag is ignored with other graphics APIs.
4564
4565
     \value ThreeDimensional The texture is a 3D texture. Such textures should
4566
     be created with the QRhi::newTexture() overload taking a depth in addition
4567
     to width and height. A 3D texture can have mipmaps but cannot be
4568
     multisample. When rendering into, or uploading data to a 3D texture, the \c
4569
     layer specified in the render target's color attachment or the upload
4570
     description refers to a single slice in range [0..depth-1]. The underlying
4571
     graphics API may not support 3D textures at run time. Support is indicated
4572
     by the QRhi::ThreeDimensionalTextures feature.
4573
4574
     \value TextureRectangleGL The texture should use the GL_TEXTURE_RECTANGLE
4575
     target with OpenGL. This flag is ignored with other graphics APIs. Just
4576
     like ExternalOES, this flag is useful when working with platform APIs where
4577
     native OpenGL texture objects received from the platform are wrapped in a
4578
     QRhiTexture, and the platform can only provide textures for a non-2D
4579
     texture target.
4580
4581
     \value TextureArray The texture is a texture array, i.e. a single texture
4582
     object that is a homogeneous array of 2D textures. Texture arrays are
4583
     created with QRhi::newTextureArray(). The underlying graphics API may not
4584
     support texture array objects at run time. Support is indicated by the
4585
     QRhi::TextureArrays feature. When rendering into, or uploading data to a
4586
     texture array, the \c layer specified in the render target's color
4587
     attachment or the upload description selects a single element in the array.
4588
4589
     \value OneDimensional The texture is a 1D texture. Such textures can be
4590
     created by passing a 0 height and depth to QRhi::newTexture(). Note that
4591
     there can be limitations on one dimensional textures depending on the
4592
     underlying graphics API. For example, rendering to them or using them with
4593
     mipmap-based filtering may be unsupported. This is indicated by the
4594
     QRhi::OneDimensionalTextures and QRhi::OneDimensionalTextureMipmaps
4595
     feature flags.
4596
4597
     \value UsedAsShadingRateMap
4598
 */
4599
4600
/*!
4601
    \enum QRhiTexture::Format
4602
4603
    Specifies the texture format. See also QRhi::isTextureFormatSupported() and
4604
    note that flags() can modify the format when QRhiTexture::sRGB is set.
4605
4606
    \value UnknownFormat Not a valid format. This cannot be passed to setFormat().
4607
4608
    \value RGBA8 Four components, unsigned normalized 8-bit per component. Always supported. (32 bits total)
4609
4610
    \value BGRA8 Four components, unsigned normalized 8-bit per component. (32 bits total)
4611
4612
    \value R8 One component, unsigned normalized 8-bit. (8 bits total)
4613
4614
    \value RG8 Two components, unsigned normalized 8-bit. (16 bits total)
4615
4616
    \value R16 One component, unsigned normalized 16-bit. (16 bits total)
4617
4618
    \value RG16 Two components, unsigned normalized 16-bit. (32 bits total)
4619
4620
    \value RED_OR_ALPHA8 Either same as R8, or is a similar format with the component swizzled to alpha,
4621
    depending on \l{QRhi::RedOrAlpha8IsRed}{RedOrAlpha8IsRed}. (8 bits total)
4622
4623
    \value RGBA16F Four components, 16-bit float. (64 bits total)
4624
4625
    \value RGBA32F Four components, 32-bit float. (128 bits total)
4626
4627
    \value R16F One component, 16-bit float. (16 bits total)
4628
4629
    \value R32F One component, 32-bit float. (32 bits total)
4630
4631
    \value RGB10A2 Four components, unsigned normalized 10 bit R, G, and B,
4632
    2-bit alpha. This is a packed format so native endianness applies. Note
4633
    that there is no BGR10A2. This is because RGB10A2 maps to
4634
    DXGI_FORMAT_R10G10B10A2_UNORM with D3D, MTLPixelFormatRGB10A2Unorm with
4635
    Metal, VK_FORMAT_A2B10G10R10_UNORM_PACK32 with Vulkan, and
4636
    GL_RGB10_A2/GL_RGB/GL_UNSIGNED_INT_2_10_10_10_REV on OpenGL (ES). This is
4637
    the only universally supported RGB30 option. The corresponding QImage
4638
    formats are QImage::Format_BGR30 and QImage::Format_A2BGR30_Premultiplied.
4639
    (32 bits total)
4640
4641
    \value D16 16-bit depth (normalized unsigned integer)
4642
4643
    \value D24 24-bit depth (normalized unsigned integer)
4644
4645
    \value D24S8 24-bit depth (normalized unsigned integer), 8 bit stencil
4646
4647
    \value D32F 32-bit depth (32-bit float)
4648
4649
    \value [since 6.9] D32FS8 32-bit depth (32-bit float), 8 bits of stencil, 24 bits unused
4650
    (64 bits total)
4651
4652
    \value BC1
4653
    \value BC2
4654
    \value BC3
4655
    \value BC4
4656
    \value BC5
4657
    \value BC6H
4658
    \value BC7
4659
4660
    \value ETC2_RGB8
4661
    \value ETC2_RGB8A1
4662
    \value ETC2_RGBA8
4663
4664
    \value ASTC_4x4
4665
    \value ASTC_5x4
4666
    \value ASTC_5x5
4667
    \value ASTC_6x5
4668
    \value ASTC_6x6
4669
    \value ASTC_8x5
4670
    \value ASTC_8x6
4671
    \value ASTC_8x8
4672
    \value ASTC_10x5
4673
    \value ASTC_10x6
4674
    \value ASTC_10x8
4675
    \value ASTC_10x10
4676
    \value ASTC_12x10
4677
    \value ASTC_12x12
4678
4679
    \value [since 6.9] R8UI One component, unsigned 8-bit. (8 bits total)
4680
    \value [since 6.9] R32UI One component, unsigned 32-bit. (32 bits total)
4681
    \value [since 6.9] RG32UI Two components, unsigned 32-bit. (64 bits total)
4682
    \value [since 6.9] RGBA32UI Four components, unsigned 32-bit. (128 bits total)
4683
4684
    \value [since 6.10] R8SI One component, signed 8-bit. (8 bits total)
4685
    \value [since 6.10] R32SI One component, signed 32-bit. (32 bits total)
4686
    \value [since 6.10] RG32SI Two components, signed 32-bit. (64 bits total)
4687
    \value [since 6.10] RGBA32SI Four components, signed 32-bit. (128 bits total)
4688
 */
4689
4690
// When adding new texture formats, update void tst_QRhi::textureFormats_data().
4691
4692
/*!
4693
    \struct QRhiTexture::NativeTexture
4694
    \inmodule QtGuiPrivate
4695
    \inheaderfile rhi/qrhi.h
4696
    \brief Contains information about the underlying native resources of a texture.
4697
 */
4698
4699
/*!
4700
    \variable QRhiTexture::NativeTexture::object
4701
    \brief 64-bit integer containing the native object handle.
4702
4703
    With OpenGL, the native handle is a GLuint value, so \c object can then be
4704
    cast to a GLuint. With Vulkan, the native handle is a VkImage, so \c object
4705
    can be cast to a VkImage. With Direct3D 11 and Metal \c object contains a
4706
    ID3D11Texture2D or MTLTexture pointer, respectively. With Direct3D 12
4707
    \c object contains a ID3D12Resource pointer.
4708
 */
4709
4710
/*!
4711
    \variable QRhiTexture::NativeTexture::layout
4712
    \brief Specifies the current image layout for APIs like Vulkan.
4713
4714
    For Vulkan, \c layout contains a \c VkImageLayout value.
4715
 */
4716
4717
/*!
4718
    \internal
4719
 */
4720
QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
4721
                         int arraySize_, int sampleCount_, Flags flags_)
4722
0
    : QRhiResource(rhi),
4723
0
      m_format(format_), m_pixelSize(pixelSize_), m_depth(depth_),
4724
0
      m_arraySize(arraySize_), m_sampleCount(sampleCount_), m_flags(flags_)
4725
0
{
4726
0
}
4727
4728
/*!
4729
    \return the resource type.
4730
 */
4731
QRhiResource::Type QRhiTexture::resourceType() const
4732
0
{
4733
0
    return Texture;
4734
0
}
4735
4736
/*!
4737
    \fn virtual bool QRhiTexture::create() = 0
4738
4739
    Creates the corresponding native graphics resources. If there are already
4740
    resources present due to an earlier create() with no corresponding
4741
    destroy(), then destroy() is called implicitly first.
4742
4743
    \return \c true when successful, \c false when a graphics operation failed.
4744
    Regardless of the return value, calling destroy() is always safe.
4745
 */
4746
4747
/*!
4748
    \return the underlying native resources for this texture. The returned value
4749
    will be empty if exposing the underlying native resources is not supported by
4750
    the backend.
4751
4752
    \sa createFrom()
4753
 */
4754
QRhiTexture::NativeTexture QRhiTexture::nativeTexture()
4755
0
{
4756
0
    return {};
4757
0
}
4758
4759
/*!
4760
    Similar to create(), except that no new native textures are created.
4761
    Instead, the native texture resources specified by \a src is used.
4762
4763
    This allows importing an existing native texture object (which must belong
4764
    to the same device or sharing context, depending on the graphics API) from
4765
    an external graphics engine.
4766
4767
    \return true if the specified existing native texture object has been
4768
    successfully wrapped as a non-owning QRhiTexture.
4769
4770
    \note format(), pixelSize(), sampleCount(), and flags() must still be set
4771
    correctly. Passing incorrect sizes and other values to QRhi::newTexture()
4772
    and then following it with a createFrom() expecting that the native texture
4773
    object alone is sufficient to deduce such values is \b wrong and will lead
4774
    to problems.
4775
4776
    \note QRhiTexture does not take ownership of the texture object. destroy()
4777
    does not free the object or any associated memory.
4778
4779
    The opposite of this operation, exposing a QRhiTexture-created native
4780
    texture object to a foreign engine, is possible via nativeTexture().
4781
4782
    \note When importing a 3D texture, or a texture array object, or, with
4783
    OpenGL ES, an external texture, it is then especially important to set the
4784
    corresponding flags (ThreeDimensional, TextureArray, ExternalOES) via
4785
    setFlags() before calling this function.
4786
*/
4787
bool QRhiTexture::createFrom(QRhiTexture::NativeTexture src)
4788
0
{
4789
0
    Q_UNUSED(src);
4790
0
    return false;
4791
0
}
4792
4793
/*!
4794
    With some graphics APIs, such as Vulkan, integrating custom rendering code
4795
    that uses the graphics API directly needs special care when it comes to
4796
    image layouts. This function allows communicating the expected \a layout the
4797
    image backing the QRhiTexture is in after the native rendering commands.
4798
4799
    For example, consider rendering into a QRhiTexture's VkImage directly with
4800
    Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and
4801
    QRhiCommandBuffer::endExternal(), followed by using the image for texture
4802
    sampling in a QRhi-based render pass. To avoid potentially incorrect image
4803
    layout transitions, this function can be used to indicate what the image
4804
    layout will be once the commands recorded in said code block complete.
4805
4806
    Calling this function makes sense only after
4807
    QRhiCommandBuffer::endExternal() and before a subsequent
4808
    QRhiCommandBuffer::beginPass().
4809
4810
    This function has no effect with QRhi backends where the underlying
4811
    graphics API does not expose a concept of image layouts.
4812
4813
    \note With Vulkan \a layout is a \c VkImageLayout. With Direct 3D 12 \a
4814
    layout is a value composed of the bits from \c D3D12_RESOURCE_STATES.
4815
 */
4816
void QRhiTexture::setNativeLayout(int layout)
4817
0
{
4818
0
    Q_UNUSED(layout);
4819
0
}
4820
4821
/*!
4822
    \fn QRhiTexture::Format QRhiTexture::format() const
4823
    \return the texture format.
4824
 */
4825
4826
/*!
4827
    \fn void QRhiTexture::setFormat(QRhiTexture::Format fmt)
4828
4829
    Sets the requested texture format to \a fmt.
4830
4831
    \note The value set is only taken into account upon the next call to
4832
    create(), i.e. when the underlying graphics resource are (re)created.
4833
    Setting a new value is futile otherwise and must be avoided since it can
4834
    lead to inconsistent state.
4835
 */
4836
4837
/*!
4838
    \fn QSize QRhiTexture::pixelSize() const
4839
    \return the size in pixels.
4840
 */
4841
4842
/*!
4843
    \fn void QRhiTexture::setPixelSize(const QSize &sz)
4844
4845
    Sets the texture size, specified in pixels, to \a sz.
4846
4847
    \note The value set is only taken into account upon the next call to
4848
    create(), i.e. when the underlying graphics resource are (re)created.
4849
    Setting a new value is futile otherwise and must be avoided since it can
4850
    lead to inconsistent state. The same applies to all other setters as well.
4851
 */
4852
4853
/*!
4854
    \fn int QRhiTexture::depth() const
4855
    \return the depth for 3D textures.
4856
 */
4857
4858
/*!
4859
    \fn void QRhiTexture::setDepth(int depth)
4860
    Sets the \a depth for a 3D texture.
4861
 */
4862
4863
/*!
4864
    \fn int QRhiTexture::arraySize() const
4865
    \return the texture array size.
4866
 */
4867
4868
/*!
4869
    \fn void QRhiTexture::setArraySize(int arraySize)
4870
    Sets the texture \a arraySize.
4871
 */
4872
4873
/*!
4874
    \fn int QRhiTexture::arrayRangeStart() const
4875
4876
    \return the first array layer when setArrayRange() was called.
4877
4878
    \sa setArrayRange()
4879
 */
4880
4881
/*!
4882
    \fn int QRhiTexture::arrayRangeLength() const
4883
4884
    \return the exposed array range size when setArrayRange() was called.
4885
4886
    \sa setArrayRange()
4887
*/
4888
4889
/*!
4890
    \fn void QRhiTexture::setArrayRange(int startIndex, int count)
4891
4892
    Normally all array layers are exposed and it is up to the shader to select
4893
    the layer via the third coordinate passed to the \c{texture()} GLSL
4894
    function when sampling the \c sampler2DArray. When QRhi::TextureArrayRange
4895
    is reported as supported, calling setArrayRange() before create() or
4896
    createFrom() requests selecting only the specified range, \a count elements
4897
    starting from \a startIndex. The shader logic can then be written with this
4898
    in mind.
4899
4900
    \sa QRhi::TextureArrayRange
4901
 */
4902
4903
/*!
4904
    \fn Flags QRhiTexture::flags() const
4905
    \return the texture flags.
4906
 */
4907
4908
/*!
4909
    \fn void QRhiTexture::setFlags(Flags f)
4910
    Sets the texture flags to \a f.
4911
 */
4912
4913
/*!
4914
    \fn int QRhiTexture::sampleCount() const
4915
    \return the sample count. 1 means no multisample antialiasing.
4916
 */
4917
4918
/*!
4919
    \fn void QRhiTexture::setSampleCount(int s)
4920
    Sets the sample count to \a s.
4921
 */
4922
4923
/*!
4924
    \struct QRhiTexture::ViewFormat
4925
    \inmodule QtGuiPrivate
4926
    \inheaderfile rhi/qrhi.h
4927
    \since 6.8
4928
    \brief Specifies the view format for reading or writing from or to the texture.
4929
4930
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
4931
    for details.
4932
 */
4933
4934
/*!
4935
    \variable QRhiTexture::ViewFormat::format
4936
 */
4937
4938
/*!
4939
    \variable QRhiTexture::ViewFormat::srgb
4940
 */
4941
4942
/*!
4943
    \fn QRhiTexture::ViewFormat QRhiTexture::readViewFormat() const
4944
    \since 6.8
4945
    \return the view format used when sampling the texture. When not called, the view
4946
    format is assumed to be the same as format().
4947
 */
4948
4949
/*!
4950
    \fn void QRhiTexture::setReadViewFormat(const ViewFormat &fmt)
4951
    \since 6.8
4952
4953
    Sets the shader resource view format (or the format of the view used for
4954
    sampling the texture) to \a fmt. By default the same format (and sRGB-ness)
4955
    is used as the texture itself, and in most cases this function does not need
4956
    to be called.
4957
4958
    This setting is only taken into account when the \l QRhi::TextureViewFormat
4959
    feature is reported as supported.
4960
4961
    \note This functionality is provided to allow "casting" between
4962
    non-sRGB and sRGB in order to get the shader reads perform, or not perform,
4963
    the implicit sRGB conversions. Other types of casting may or may not be
4964
    functional.
4965
 */
4966
4967
/*!
4968
    \fn QRhiTexture::ViewFormat QRhiTexture::writeViewFormat() const
4969
    \since 6.8
4970
    \return the view format used when writing to the texture and when using it
4971
    with image load/store. When not called, the view format is assumed to be the
4972
    same as format().
4973
 */
4974
4975
/*!
4976
    \fn void QRhiTexture::setWriteViewFormat(const ViewFormat &fmt)
4977
    \since 6.8
4978
4979
    Sets the render target view format to \a fmt. By default the same format
4980
    (and sRGB-ness) is used as the texture itself, and in most cases this
4981
    function does not need to be called.
4982
4983
    One common use case for providing a write view format is working with
4984
    externally provided textures that, outside of our control, use an sRGB
4985
    format with 3D APIs such as Vulkan or Direct 3D, but the rendering engine is
4986
    already prepared to handle linearization and conversion to sRGB at the end
4987
    of its shading pipeline. In this case what is wanted when rendering into
4988
    such a texture is a render target view (e.g. VkImageView) that has the same,
4989
    but non-sRGB format. (if e.g. from an OpenXR implementation one gets a
4990
    VK_FORMAT_R8G8B8A8_SRGB texture, it is likely that rendering into it should
4991
    be done using a VK_FORMAT_R8G8B8A8_UNORM view, if that is what the rendering
4992
    engine's pipeline requires; in this example one would call this function
4993
    with a ViewFormat that has a format of QRhiTexture::RGBA8 and \c srgb set to
4994
    \c false).
4995
4996
    This setting is only taken into account when the \l QRhi::TextureViewFormat
4997
    feature is reported as supported.
4998
4999
    \note This functionality is provided to allow "casting" between
5000
    non-sRGB and sRGB in order to get the shader write not perform, or perform,
5001
    the implicit sRGB conversions. Other types of casting may or may not be
5002
    functional.
5003
 */
5004
5005
/*!
5006
    \class QRhiSampler
5007
    \inmodule QtGuiPrivate
5008
    \inheaderfile rhi/qrhi.h
5009
    \since 6.6
5010
    \brief Sampler resource.
5011
5012
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5013
    for details.
5014
 */
5015
5016
/*!
5017
    \enum QRhiSampler::Filter
5018
    Specifies the minification, magnification, or mipmap filtering
5019
5020
    \value None Applicable only for mipmapMode(), indicates no mipmaps to be used
5021
    \value Nearest
5022
    \value Linear
5023
 */
5024
5025
/*!
5026
    \enum QRhiSampler::AddressMode
5027
    Specifies the addressing mode
5028
5029
    \value Repeat
5030
    \value ClampToEdge
5031
    \value Mirror
5032
 */
5033
5034
/*!
5035
    \enum QRhiSampler::CompareOp
5036
    Specifies the texture comparison function.
5037
5038
    \value Never (default)
5039
    \value Less
5040
    \value Equal
5041
    \value LessOrEqual
5042
    \value Greater
5043
    \value NotEqual
5044
    \value GreaterOrEqual
5045
    \value Always
5046
 */
5047
5048
/*!
5049
    \internal
5050
 */
5051
QRhiSampler::QRhiSampler(QRhiImplementation *rhi,
5052
                         Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
5053
                         AddressMode u_, AddressMode v_, AddressMode w_)
5054
0
    : QRhiResource(rhi),
5055
0
      m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_),
5056
0
      m_addressU(u_), m_addressV(v_), m_addressW(w_),
5057
0
      m_compareOp(QRhiSampler::Never)
5058
0
{
5059
0
}
5060
5061
/*!
5062
    \return the resource type.
5063
 */
5064
QRhiResource::Type QRhiSampler::resourceType() const
5065
0
{
5066
0
    return Sampler;
5067
0
}
5068
5069
/*!
5070
    \fn QRhiSampler::Filter QRhiSampler::magFilter() const
5071
    \return the magnification filter mode.
5072
 */
5073
5074
/*!
5075
    \fn void QRhiSampler::setMagFilter(Filter f)
5076
    Sets the magnification filter mode to \a f.
5077
 */
5078
5079
/*!
5080
    \fn QRhiSampler::Filter QRhiSampler::minFilter() const
5081
    \return the minification filter mode.
5082
 */
5083
5084
/*!
5085
    \fn void QRhiSampler::setMinFilter(Filter f)
5086
    Sets the minification filter mode to \a f.
5087
 */
5088
5089
/*!
5090
    \fn QRhiSampler::Filter QRhiSampler::mipmapMode() const
5091
    \return the mipmap filter mode.
5092
 */
5093
5094
/*!
5095
    \fn void QRhiSampler::setMipmapMode(Filter f)
5096
5097
    Sets the mipmap filter mode to \a f.
5098
5099
    Leave this set to None when the texture has no mip levels, or when the mip
5100
    levels are not to be taken into account.
5101
 */
5102
5103
/*!
5104
    \fn QRhiSampler::AddressMode QRhiSampler::addressU() const
5105
    \return the horizontal wrap mode.
5106
 */
5107
5108
/*!
5109
    \fn void QRhiSampler::setAddressU(AddressMode mode)
5110
    Sets the horizontal wrap \a mode.
5111
 */
5112
5113
/*!
5114
    \fn QRhiSampler::AddressMode QRhiSampler::addressV() const
5115
    \return the vertical wrap mode.
5116
 */
5117
5118
/*!
5119
    \fn void QRhiSampler::setAddressV(AddressMode mode)
5120
    Sets the vertical wrap \a mode.
5121
 */
5122
5123
/*!
5124
    \fn QRhiSampler::AddressMode QRhiSampler::addressW() const
5125
    \return the depth wrap mode.
5126
 */
5127
5128
/*!
5129
    \fn void QRhiSampler::setAddressW(AddressMode mode)
5130
    Sets the depth wrap \a mode.
5131
 */
5132
5133
/*!
5134
    \fn QRhiSampler::CompareOp QRhiSampler::textureCompareOp() const
5135
    \return the texture comparison function.
5136
 */
5137
5138
/*!
5139
    \fn void QRhiSampler::setTextureCompareOp(CompareOp op)
5140
    Sets the texture comparison function \a op.
5141
 */
5142
5143
/*!
5144
    \class QRhiShadingRateMap
5145
    \inmodule QtGuiPrivate
5146
    \inheaderfile rhi/qrhi.h
5147
    \since 6.9
5148
    \brief An object that wraps a texture or another kind of native 3D API object.
5149
5150
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5151
    for details.
5152
5153
    For an introduction to Variable Rate Shading (VRS), see
5154
    \l{https://learn.microsoft.com/en-us/windows/win32/direct3d12/vrs}. Qt
5155
    supports a subset of the VRS features offered by Direct 3D 12 and Vulkan. In
5156
    addition, Metal's somewhat different mechanism is supported by making it
5157
    possible to set up a QRhiShadingRateMap with an existing
5158
    MTLRasterizationRateMap object.
5159
 */
5160
5161
/*!
5162
    \struct QRhiShadingRateMap::NativeShadingRateMap
5163
    \inmodule QtGuiPrivate
5164
    \inheaderfile rhi/qrhi.h
5165
    \since 6.9
5166
    \brief Wraps a native shading rate map.
5167
5168
    An example is MTLRasterizationRateMap with Metal. Other 3D APIs that use
5169
    textures for image-based VRS do not use this struct since those can function
5170
    via the QRhiTexture-based overload of QRhiShadingRateMap::createFrom().
5171
 */
5172
5173
/*!
5174
    \variable QRhiShadingRateMap::NativeShadingRateMap::object
5175
    \brief 64-bit integer containing the native object handle.
5176
5177
    Used with QRhiShadingRateMap::createFrom(). For example, with Metal,
5178
    \c object is expected to be an id<MTLRasterizationRateMap>.
5179
 */
5180
5181
/*!
5182
    \internal
5183
 */
5184
QRhiShadingRateMap::QRhiShadingRateMap(QRhiImplementation *rhi)
5185
0
    : QRhiResource(rhi)
5186
0
{
5187
0
}
5188
5189
/*!
5190
    \return the resource type.
5191
 */
5192
QRhiResource::Type QRhiShadingRateMap::resourceType() const
5193
0
{
5194
0
    return ShadingRateMap;
5195
0
}
5196
5197
/*!
5198
    Sets up the shading rate map to use a native 3D API shading rate object
5199
    \a src.
5200
5201
    \return \c true when successful, \c false when not supported.
5202
5203
    \note This is functional only when the QRhi::VariableRateShadingMap feature
5204
    is reported as supported, while QRhi::VariableRateShadingMapWithTexture
5205
    feature is not. Currently this is true for Metal, assuming variable rate
5206
    shading is supported by the GPU.
5207
5208
    \note With Metal, the \c object field of \a src is expected to contain an
5209
    id<MTLRasterizationRateMap>. Note that Qt does not perform anything else
5210
    apart from passing the MTLRasterizationRateMap on to the
5211
    MTLRenderPassDescriptor. If any special scaling is required, it is up to the
5212
    application (or the XR compositor) to perform that.
5213
 */
5214
bool QRhiShadingRateMap::createFrom(NativeShadingRateMap src)
5215
0
{
5216
0
    Q_UNUSED(src);
5217
0
    return false;
5218
0
}
5219
5220
/*!
5221
    Sets up the shading rate map to use the texture \a src as the
5222
    image containing the per-tile shading rates.
5223
5224
    \return \c true when successful, \c false when not supported.
5225
5226
    The QRhiShadingRateMap does not take ownership of \a src.
5227
5228
    \note This is functional only when the
5229
    QRhi::VariableRateShadingMapWithTexture feature is reported as supported. In
5230
    practice may be supported on Vulkan and Direct 3D 12 when using modern
5231
    graphics cards. It will never be supported on OpenGL or Metal, for example.
5232
5233
    \note \a src must have a format of QRhiTexture::R8UI.
5234
5235
    \note \a src must have a width of \c{ceil(render_target_pixel_width /
5236
    (float)tile_width)} and a height of \c{ceil(render_target_pixel_height /
5237
    (float)tile_height)}. It is up to the application to ensure the size of the
5238
    texture is as expected, using the above formula, at all times. The tile size
5239
    can be queried via \l QRhi::resourceLimit() and
5240
    QRhi::ShadingRateImageTileSize.
5241
5242
    Each byte (texel) in the texture corresponds to the shading rate value for
5243
    one tile. 0 indicates 1x1, while a value of 10 indicates 4x4. See
5244
    \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shading_rate}{D3D12_SHADING_RATE}
5245
    for other possible values.
5246
 */
5247
bool QRhiShadingRateMap::createFrom(QRhiTexture *src)
5248
0
{
5249
0
    Q_UNUSED(src);
5250
0
    return false;
5251
0
}
5252
5253
/*!
5254
    \class QRhiRenderPassDescriptor
5255
    \inmodule QtGuiPrivate
5256
    \inheaderfile rhi/qrhi.h
5257
    \since 6.6
5258
    \brief Render pass resource.
5259
5260
    A render pass, if such a concept exists in the underlying graphics API, is
5261
    a collection of attachments (color, depth, stencil) and describes how those
5262
    attachments are used.
5263
5264
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5265
    for details.
5266
 */
5267
5268
/*!
5269
    \internal
5270
 */
5271
QRhiRenderPassDescriptor::QRhiRenderPassDescriptor(QRhiImplementation *rhi)
5272
0
    : QRhiResource(rhi)
5273
0
{
5274
0
}
5275
5276
/*!
5277
    \return the resource type.
5278
 */
5279
QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
5280
0
{
5281
0
    return RenderPassDescriptor;
5282
0
}
5283
5284
/*!
5285
    \fn virtual bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const = 0
5286
5287
    \return true if the \a other QRhiRenderPassDescriptor is compatible with
5288
    this one, meaning \c this and \a other can be used interchangeably in
5289
    QRhiGraphicsPipeline::setRenderPassDescriptor().
5290
5291
    The concept of the compatibility of renderpass descriptors is similar to
5292
    the \l{QRhiShaderResourceBindings::isLayoutCompatible}{layout
5293
    compatibility} of QRhiShaderResourceBindings instances. They allow better
5294
    reuse of QRhiGraphicsPipeline instances: for example, a
5295
    QRhiGraphicsPipeline instance cache is expected to use these functions to
5296
    look for a matching pipeline, instead of just comparing pointers, thus
5297
    allowing a different QRhiRenderPassDescriptor and
5298
    QRhiShaderResourceBindings to be used in combination with the pipeline, as
5299
    long as they are compatible.
5300
5301
    The exact details of compatibility depend on the underlying graphics API.
5302
    Two renderpass descriptors
5303
    \l{QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()}{created}
5304
    from the same QRhiTextureRenderTarget are always compatible.
5305
5306
    Similarly to QRhiShaderResourceBindings, compatibility can also be tested
5307
    without having two existing objects available. Extracting the opaque blob by
5308
    calling serializedFormat() allows testing for compatibility by comparing the
5309
    returned vector to another QRhiRenderPassDescriptor's
5310
    serializedFormat(). This has benefits in certain situations, because it
5311
    allows testing the compatibility of a QRhiRenderPassDescriptor with a
5312
    QRhiGraphicsPipeline even when the QRhiRenderPassDescriptor the pipeline was
5313
    originally built with is no longer available (but the data returned from its
5314
    serializedFormat() still is).
5315
5316
    \sa newCompatibleRenderPassDescriptor(), serializedFormat()
5317
 */
5318
5319
/*!
5320
    \fn virtual QRhiRenderPassDescriptor *QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor() const = 0
5321
5322
    \return a new QRhiRenderPassDescriptor that is
5323
    \l{isCompatible()}{compatible} with this one.
5324
5325
    This function allows cloning a QRhiRenderPassDescriptor. The returned
5326
    object is ready to be used, and the ownership is transferred to the caller.
5327
    Cloning a QRhiRenderPassDescriptor object can become useful in situations
5328
    where the object is stored in data structures related to graphics pipelines
5329
    (in order to allow creating new pipelines which in turn requires a
5330
    renderpass descriptor object), and the lifetime of the renderpass
5331
    descriptor created from a render target may be shorter than the pipelines.
5332
    (for example, because the engine manages and destroys renderpasses together
5333
    with the textures and render targets it was created from) In such a
5334
    situation, it can be beneficial to store a cloned version in the data
5335
    structures, and thus transferring ownership as well.
5336
5337
    \sa isCompatible()
5338
 */
5339
5340
/*!
5341
    \fn virtual QVector<quint32> QRhiRenderPassDescriptor::serializedFormat() const = 0
5342
5343
    \return a vector of integers containing an opaque blob describing the data
5344
    relevant for \l{isCompatible()}{compatibility}.
5345
5346
    Given two QRhiRenderPassDescriptor objects \c rp1 and \c rp2, if the data
5347
    returned from this function is identical, then \c{rp1->isCompatible(rp2)},
5348
    and vice versa hold true as well.
5349
5350
    \note The returned data is meant to be used for storing in memory and
5351
    comparisons during the lifetime of the QRhi the object belongs to. It is not
5352
    meant for storing on disk, reusing between processes, or using with multiple
5353
    QRhi instances with potentially different backends.
5354
5355
    \note Calling this function is expected to be a cheap operation since the
5356
    backends are not supposed to calculate the data in this function, but rather
5357
    return an already calculated series of data.
5358
5359
    When creating reusable components as part of a library, where graphics
5360
    pipelines are created and maintained while targeting a QRhiRenderTarget (be
5361
    it a swapchain or a texture) managed by the client of the library, the
5362
    components must be able to deal with a changing QRhiRenderPassDescriptor.
5363
    For example, because the render target changes and so invalidates the
5364
    previously QRhiRenderPassDescriptor (with regards to the new render target
5365
    at least) due to having a potentially different color format and attachments
5366
    now. Or because \l{QRhiShadingRateMap}{variable rate shading} is taken into
5367
    use dynamically. A simple pattern that helps dealing with this is performing
5368
    the following check on every frame, to recognize the case when the pipeline
5369
    needs to be associated with a new QRhiRenderPassDescriptor, because
5370
    something is different about the render target now, compared to earlier
5371
    frames:
5372
5373
    \code
5374
        QRhiRenderPassDescriptor *rp = m_renderTarget->renderPassDescriptor();
5375
        if (m_pipeline && rp->serializedFormat() != m_renderPassFormat) {
5376
            m_pipeline->setRenderPassDescriptor(rp);
5377
            m_renderPassFormat = rp->serializedFormat();
5378
            m_pipeline->create();
5379
        }
5380
        // remember to store m_renderPassFormat also when creating m_pipeline the first time
5381
    \endcode
5382
5383
    \sa isCompatible()
5384
 */
5385
5386
/*!
5387
    \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
5388
    QRhiVulkanRenderPassNativeHandles. The returned value is \nullptr when exposing
5389
    the underlying native resources is not supported by the backend.
5390
5391
    \sa QRhiVulkanRenderPassNativeHandles
5392
 */
5393
const QRhiNativeHandles *QRhiRenderPassDescriptor::nativeHandles()
5394
0
{
5395
0
    return nullptr;
5396
0
}
5397
5398
/*!
5399
    \class QRhiRenderTarget
5400
    \inmodule QtGuiPrivate
5401
    \inheaderfile rhi/qrhi.h
5402
    \since 6.6
5403
    \brief Represents an onscreen (swapchain) or offscreen (texture) render target.
5404
5405
    Applications do not create an instance of this class directly. Rather, it
5406
    is the subclass QRhiTextureRenderTarget that is instantiable by clients of
5407
    the API via \l{QRhi::newTextureRenderTarget()}{newTextureRenderTarget()}.
5408
    The other subclass is QRhiSwapChainRenderTarget, which is the type
5409
    QRhiSwapChain returns when calling
5410
    \l{QRhiSwapChain::currentFrameRenderTarget()}{currentFrameRenderTarget()}.
5411
5412
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5413
    for details.
5414
5415
    \sa QRhiSwapChainRenderTarget, QRhiTextureRenderTarget
5416
 */
5417
5418
/*!
5419
    \internal
5420
 */
5421
QRhiRenderTarget::QRhiRenderTarget(QRhiImplementation *rhi)
5422
0
    : QRhiResource(rhi)
5423
0
{
5424
0
}
5425
5426
/*!
5427
    \fn virtual QSize QRhiRenderTarget::pixelSize() const = 0
5428
5429
    \return the size in pixels.
5430
5431
    Valid only after create() has been called successfully. Until then the
5432
    result is a default-constructed QSize.
5433
5434
    With QRhiTextureRenderTarget the returned size is the size of the
5435
    associated attachments at the time of create(), in practice the size of the
5436
    first color attachment, or the depth/stencil buffer if there are no color
5437
    attachments. If the associated textures or renderbuffers are resized and
5438
    rebuilt afterwards, then pixelSize() performs an implicit call to create()
5439
    in order to rebuild the underlying data structures. This implicit check is
5440
    similar to what QRhiCommandBuffer::beginPass() does, and ensures that the
5441
    returned size is always up-to-date.
5442
 */
5443
5444
/*!
5445
    \fn virtual float QRhiRenderTarget::devicePixelRatio() const = 0
5446
5447
    \return the device pixel ratio. For QRhiTextureRenderTarget this is always
5448
    1. For targets retrieved from a QRhiSwapChain the value reflects the
5449
    \l{QWindow::devicePixelRatio()}{device pixel ratio} of the targeted
5450
    QWindow.
5451
 */
5452
5453
/*!
5454
    \fn virtual int QRhiRenderTarget::sampleCount() const = 0
5455
5456
    \return the sample count or 1 if multisample antialiasing is not relevant for
5457
    this render target.
5458
 */
5459
5460
/*!
5461
    \fn QRhiRenderPassDescriptor *QRhiRenderTarget::renderPassDescriptor() const
5462
5463
    \return the associated QRhiRenderPassDescriptor.
5464
 */
5465
5466
/*!
5467
    \fn void QRhiRenderTarget::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
5468
5469
    Sets the QRhiRenderPassDescriptor \a desc for use with this render target.
5470
 */
5471
5472
/*!
5473
    \internal
5474
 */
5475
QRhiSwapChainRenderTarget::QRhiSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain_)
5476
0
    : QRhiRenderTarget(rhi),
5477
0
      m_swapchain(swapchain_)
5478
0
{
5479
0
}
5480
5481
/*!
5482
    \class QRhiSwapChainRenderTarget
5483
    \inmodule QtGuiPrivate
5484
    \inheaderfile rhi/qrhi.h
5485
    \since 6.6
5486
    \brief Swapchain render target resource.
5487
5488
    When targeting the color buffers of a swapchain, active render target is a
5489
    QRhiSwapChainRenderTarget. This is what
5490
    QRhiSwapChain::currentFrameRenderTarget() returns.
5491
5492
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5493
    for details.
5494
5495
    \sa QRhiSwapChain
5496
 */
5497
5498
/*!
5499
    \return the resource type.
5500
 */
5501
QRhiResource::Type QRhiSwapChainRenderTarget::resourceType() const
5502
0
{
5503
0
    return SwapChainRenderTarget;
5504
0
}
5505
5506
/*!
5507
    \fn QRhiSwapChain *QRhiSwapChainRenderTarget::swapChain() const
5508
5509
    \return the swapchain object.
5510
 */
5511
5512
/*!
5513
    \class QRhiTextureRenderTarget
5514
    \inmodule QtGuiPrivate
5515
    \inheaderfile rhi/qrhi.h
5516
    \since 6.6
5517
    \brief Texture render target resource.
5518
5519
    A texture render target allows rendering into one or more textures,
5520
    optionally with a depth texture or depth/stencil renderbuffer.
5521
5522
    For multisample rendering the common approach is to use a renderbuffer as
5523
    the color attachment and set the non-multisample destination texture as the
5524
    \c{resolve texture}. For more information, read the detailed description of
5525
    the \l QRhiColorAttachment class.
5526
5527
    \note Textures used in combination with QRhiTextureRenderTarget must be
5528
    created with the QRhiTexture::RenderTarget flag.
5529
5530
    The simplest example of creating a render target with a texture as its
5531
    single color attachment:
5532
5533
    \code
5534
        QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
5535
        texture->create();
5536
        QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture });
5537
        rp = rt->newCompatibleRenderPassDescriptor();
5538
        rt->setRenderPassDescriptor(rp);
5539
        rt->create();
5540
        // rt can now be used with beginPass()
5541
    \endcode
5542
5543
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5544
    for details.
5545
 */
5546
5547
/*!
5548
    \enum QRhiTextureRenderTarget::Flag
5549
5550
    Flag values describing the load/store behavior for the render target. The
5551
    load/store behavior may be baked into native resources under the hood,
5552
    depending on the backend, and therefore it needs to be known upfront and
5553
    cannot be changed without rebuilding (and so releasing and creating new
5554
    native resources).
5555
5556
    \value PreserveColorContents Indicates that the contents of the color
5557
    attachments is to be loaded when starting a render pass, instead of
5558
    clearing. This is potentially more expensive, especially on mobile (tiled)
5559
    GPUs, but allows preserving the existing contents between passes. When doing
5560
    multisample rendering with a resolve texture set, setting this flag also
5561
    requests the multisample color data to be stored (written out) to the
5562
    multisample texture or render buffer. (for non-multisample rendering the
5563
    color data is always stored, but for MSAA storing the multisample data
5564
    decreases efficiency for certain GPU architectures, hence defaulting to not
5565
    writing it out) Note however that this is non-portable: in some cases there
5566
    is no intermediate multisample texture on the graphics API level, e.g. when
5567
    using OpenGL ES's \c{GL_EXT_multisampled_render_to_texture} as it is all
5568
    implicit, handled by the OpenGL ES implementation. In that case,
5569
    PreserveColorContents will likely have no effect. Therefore, avoid relying
5570
    on this flag when using multisample rendering and the color attachment is
5571
    using a multisample QRhiTexture (not QRhiRenderBuffer).
5572
5573
    \value PreserveDepthStencilContents Indicates that the contents of the
5574
    depth texture is to be loaded when starting a render pass, instead
5575
    clearing. Only applicable when a texture is used as the depth buffer
5576
    (QRhiTextureRenderTargetDescription::depthTexture() is set) because
5577
    depth/stencil renderbuffers may not have any physical backing and data may
5578
    not be written out in the first place.
5579
5580
    \value DoNotStoreDepthStencilContents Indicates that the contents of the
5581
    depth texture does not need to be written out. Relevant only when a
5582
    QRhiTexture, not QRhiRenderBuffer, is used as the depth-stencil buffer,
5583
    because for QRhiRenderBuffer this is implicit. When a depthResolveTexture is
5584
    set, the flag is not relevant, because the behavior is then as if the flag
5585
    was set. This enum value is introduced in Qt 6.8.
5586
 */
5587
5588
/*!
5589
    \internal
5590
 */
5591
QRhiTextureRenderTarget::QRhiTextureRenderTarget(QRhiImplementation *rhi,
5592
                                                 const QRhiTextureRenderTargetDescription &desc_,
5593
                                                 Flags flags_)
5594
0
    : QRhiRenderTarget(rhi),
5595
0
      m_desc(desc_),
5596
0
      m_flags(flags_)
5597
0
{
5598
0
}
5599
5600
/*!
5601
    \return the resource type.
5602
 */
5603
QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
5604
0
{
5605
0
    return TextureRenderTarget;
5606
0
}
5607
5608
/*!
5609
    \fn virtual QRhiRenderPassDescriptor *QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() = 0
5610
5611
    \return a new QRhiRenderPassDescriptor that is compatible with this render
5612
    target.
5613
5614
    The returned value is used in two ways: it can be passed to
5615
    setRenderPassDescriptor() and
5616
    QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
5617
    describes the attachments (color, depth/stencil) and the load/store
5618
    behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
5619
    be used in combination with a render target that has a
5620
    \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
5621
    QRhiRenderPassDescriptor set.
5622
5623
    Two QRhiTextureRenderTarget instances can share the same render pass
5624
    descriptor as long as they have the same number and type of attachments.
5625
    The associated QRhiTexture or QRhiRenderBuffer instances are not part of
5626
    the render pass descriptor so those can differ in the two
5627
    QRhiTextureRenderTarget instances.
5628
5629
    \note resources, such as QRhiTexture instances, referenced in description()
5630
    must already have create() called on them.
5631
5632
    \sa create()
5633
 */
5634
5635
/*!
5636
    \fn virtual bool QRhiTextureRenderTarget::create() = 0
5637
5638
    Creates the corresponding native graphics resources. If there are already
5639
    resources present due to an earlier create() with no corresponding
5640
    destroy(), then destroy() is called implicitly first.
5641
5642
    \note renderPassDescriptor() must be set before calling create(). To obtain
5643
    a QRhiRenderPassDescriptor compatible with the render target, call
5644
    newCompatibleRenderPassDescriptor() before create() but after setting all
5645
    other parameters, such as description() and flags(). To save resources,
5646
    reuse the same QRhiRenderPassDescriptor with multiple
5647
    QRhiTextureRenderTarget instances, whenever possible. Sharing the same
5648
    render pass descriptor is only possible when the render targets have the
5649
    same number and type of attachments (the actual textures can differ) and
5650
    the same flags.
5651
5652
    \note resources, such as QRhiTexture instances, referenced in description()
5653
    must already have create() called on them.
5654
5655
    \return \c true when successful, \c false when a graphics operation failed.
5656
    Regardless of the return value, calling destroy() is always safe.
5657
 */
5658
5659
/*!
5660
    \fn QRhiTextureRenderTargetDescription QRhiTextureRenderTarget::description() const
5661
    \return the render target description.
5662
 */
5663
5664
/*!
5665
    \fn void QRhiTextureRenderTarget::setDescription(const QRhiTextureRenderTargetDescription &desc)
5666
    Sets the render target description \a desc.
5667
 */
5668
5669
/*!
5670
    \fn QRhiTextureRenderTarget::Flags QRhiTextureRenderTarget::flags() const
5671
    \return the currently set flags.
5672
 */
5673
5674
/*!
5675
    \fn void QRhiTextureRenderTarget::setFlags(Flags f)
5676
    Sets the flags to \a f.
5677
 */
5678
5679
/*!
5680
    \class QRhiShaderResourceBindings
5681
    \inmodule QtGuiPrivate
5682
    \inheaderfile rhi/qrhi.h
5683
    \since 6.6
5684
    \brief Encapsulates resources for making buffer, texture, sampler resources visible to shaders.
5685
5686
    A QRhiShaderResourceBindings is a collection of QRhiShaderResourceBinding
5687
    objects, each of which describe a single binding.
5688
5689
    Take a fragment shader with the following interface:
5690
5691
    \badcode
5692
        layout(std140, binding = 0) uniform buf {
5693
            mat4 mvp;
5694
            int flip;
5695
        } ubuf;
5696
5697
        layout(binding = 1) uniform sampler2D tex;
5698
    \endcode
5699
5700
    To make resources visible to the shader, the following
5701
    QRhiShaderResourceBindings could be created and then passed to
5702
    QRhiGraphicsPipeline::setShaderResourceBindings():
5703
5704
    \code
5705
        QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings();
5706
        srb->setBindings({
5707
            QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf),
5708
            QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler)
5709
        });
5710
        srb->create();
5711
        // ...
5712
        QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
5713
        // ...
5714
        ps->setShaderResourceBindings(srb);
5715
        ps->create();
5716
        // ...
5717
        cb->setGraphicsPipeline(ps);
5718
        cb->setShaderResources(); // binds srb
5719
    \endcode
5720
5721
    This assumes that \c ubuf is a QRhiBuffer, \c texture is a QRhiTexture,
5722
    while \a sampler is a QRhiSampler. The example also assumes that the
5723
    uniform block is present in the vertex shader as well so the same buffer is
5724
    made visible to the vertex stage too.
5725
5726
    \section3 Advanced usage
5727
5728
    Building on the above example, let's assume that a pass now needs to use
5729
    the exact same pipeline and shaders with a different texture. Creating a
5730
    whole separate QRhiGraphicsPipeline just for this would be an overkill.
5731
    This is why QRhiCommandBuffer::setShaderResources() allows specifying a \a
5732
    srb argument. As long as the layouts (so the number of bindings and the
5733
    binding points) match between two QRhiShaderResourceBindings, they can both
5734
    be used with the same pipeline, assuming the pipeline was created with one of
5735
    them in the first place. See isLayoutCompatible() for more details.
5736
5737
    \code
5738
        QRhiShaderResourceBindings *srb2 = rhi->newShaderResourceBindings();
5739
        // ...
5740
        cb->setGraphicsPipeline(ps);
5741
        cb->setShaderResources(srb2); // binds srb2
5742
    \endcode
5743
5744
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5745
    for details.
5746
 */
5747
5748
/*!
5749
    \typedef QRhiShaderResourceBindingSet
5750
    \relates QRhi
5751
    \since 6.7
5752
5753
    Synonym for QRhiShaderResourceBindings.
5754
*/
5755
5756
/*!
5757
    \internal
5758
 */
5759
QRhiShaderResourceBindings::QRhiShaderResourceBindings(QRhiImplementation *rhi)
5760
0
    : QRhiResource(rhi)
5761
0
{
5762
0
    m_layoutDesc.reserve(BINDING_PREALLOC * QRhiShaderResourceBinding::LAYOUT_DESC_ENTRIES_PER_BINDING);
5763
0
}
5764
5765
/*!
5766
    \return the resource type.
5767
 */
5768
QRhiResource::Type QRhiShaderResourceBindings::resourceType() const
5769
0
{
5770
0
    return ShaderResourceBindings;
5771
0
}
5772
5773
/*!
5774
    \return \c true if the layout is compatible with \a other. The layout does
5775
    not include the actual resource (such as, buffer or texture) and related
5776
    parameters (such as, offset or size). It does include the binding point,
5777
    pipeline stage, and resource type, however. The number and order of the
5778
    bindings must also match in order to be compatible.
5779
5780
    When there is a QRhiGraphicsPipeline created with this
5781
    QRhiShaderResourceBindings, and the function returns \c true, \a other can
5782
    then safely be passed to QRhiCommandBuffer::setShaderResources(), and so
5783
    be used with the pipeline in place of this QRhiShaderResourceBindings.
5784
5785
    \note This function must only be called after a successful create(), because
5786
    it relies on data generated during the baking of the underlying data
5787
    structures. This way the function can implement a comparison approach that
5788
    is more efficient than iterating through two binding lists and calling
5789
    QRhiShaderResourceBinding::isLayoutCompatible() on each pair. This becomes
5790
    relevant especially when this function is called at a high frequency.
5791
5792
    \sa serializedLayoutDescription()
5793
 */
5794
bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBindings *other) const
5795
0
{
5796
0
    if (other == this)
5797
0
        return true;
5798
5799
0
    if (!other)
5800
0
        return false;
5801
5802
    // This can become a hot code path. Therefore we do not iterate and call
5803
    // isLayoutCompatible() on m_bindings, but rather check a pre-calculated
5804
    // hash code and then, if the hash matched, do a uint array comparison
5805
    // (that's still more cache friendly).
5806
5807
0
    return m_layoutDescHash == other->m_layoutDescHash
5808
0
            && m_layoutDesc == other->m_layoutDesc;
5809
0
}
5810
5811
/*!
5812
    \fn QVector<quint32> QRhiShaderResourceBindings::serializedLayoutDescription() const
5813
5814
    \return a vector of integers containing an opaque blob describing the layout
5815
    of the binding list, i.e. the data relevant for
5816
    \l{isLayoutCompatible()}{layout compatibility tests}.
5817
5818
    Given two objects \c srb1 and \c srb2, if the data returned from this
5819
    function is identical, then \c{srb1->isLayoutCompatible(srb2)}, and vice
5820
    versa hold true as well.
5821
5822
    \note The returned data is meant to be used for storing in memory and
5823
    comparisons during the lifetime of the QRhi the object belongs to. It is not
5824
    meant for storing on disk, reusing between processes, or using with multiple
5825
    QRhi instances with potentially different backends.
5826
5827
    \sa isLayoutCompatible()
5828
 */
5829
5830
void QRhiImplementation::updateLayoutDesc(QRhiShaderResourceBindings *srb)
5831
0
{
5832
0
    srb->m_layoutDescHash = 0;
5833
0
    srb->m_layoutDesc.clear();
5834
0
    auto layoutDescAppender = std::back_inserter(srb->m_layoutDesc);
5835
0
    for (const QRhiShaderResourceBinding &b : std::as_const(srb->m_bindings)) {
5836
0
        const QRhiShaderResourceBinding::Data *d = &b.d;
5837
0
        srb->m_layoutDescHash ^= uint(d->binding) ^ uint(d->stage) ^ uint(d->type)
5838
0
            ^ uint(d->arraySize());
5839
0
        layoutDescAppender = d->serialize(layoutDescAppender);
5840
0
    }
5841
0
}
5842
5843
/*!
5844
    \fn virtual bool QRhiShaderResourceBindings::create() = 0
5845
5846
    Creates the corresponding resource binding set. Depending on the underlying
5847
    graphics API, this may involve creating native graphics resources, and
5848
    therefore it should not be assumed that this is a cheap operation.
5849
5850
    If create() has been called before with no corresponding destroy(), then
5851
    destroy() is called implicitly first.
5852
5853
    \return \c true when successful, \c false when failed.
5854
    Regardless of the return value, calling destroy() is always safe.
5855
 */
5856
5857
/*!
5858
    \fn void QRhiShaderResourceBindings::setBindings(std::initializer_list<QRhiShaderResourceBinding> list)
5859
    Sets the \a list of bindings.
5860
 */
5861
5862
/*!
5863
    \fn template<typename InputIterator> void QRhiShaderResourceBindings::setBindings(InputIterator first, InputIterator last)
5864
    Sets the list of bindings from the iterators \a first and \a last.
5865
 */
5866
5867
/*!
5868
    \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cbeginBindings() const
5869
    \return a const iterator pointing to the first item in the binding list.
5870
 */
5871
5872
/*!
5873
    \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cendBindings() const
5874
    \return a const iterator pointing just after the last item in the binding list.
5875
 */
5876
5877
/*!
5878
    \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::bindingAt(qsizetype index) const
5879
    \return the binding at the specified \a index.
5880
 */
5881
5882
/*!
5883
    \fn qsizetype QRhiShaderResourceBindings::bindingCount() const
5884
    \return the number of bindings.
5885
 */
5886
5887
/*!
5888
    \class QRhiShaderResourceBinding
5889
    \inmodule QtGuiPrivate
5890
    \inheaderfile rhi/qrhi.h
5891
    \since 6.6
5892
    \brief Describes the shader resource for a single binding point.
5893
5894
    A QRhiShaderResourceBinding cannot be constructed directly. Instead, use the
5895
    static functions such as uniformBuffer() or sampledTexture() to get an
5896
    instance.
5897
5898
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
5899
    for details.
5900
 */
5901
5902
/*!
5903
    \enum QRhiShaderResourceBinding::Type
5904
    Specifies type of the shader resource bound to a binding point
5905
5906
    \value UniformBuffer Uniform buffer
5907
5908
    \value SampledTexture Combined image sampler (a texture and sampler pair).
5909
    Even when the shading language associated with the underlying 3D API has no
5910
    support for this concept (e.g. D3D and HLSL), this is still supported
5911
    because the shader translation layer takes care of the appropriate
5912
    translation and remapping of binding points or shader registers.
5913
5914
    \value Texture Texture (separate)
5915
5916
    \value Sampler Sampler (separate)
5917
5918
    \value ImageLoad Image load (with GLSL this maps to doing imageLoad() on a
5919
    single level - and either one or all layers - of a texture exposed to the
5920
    shader as an image object)
5921
5922
    \value ImageStore Image store (with GLSL this maps to doing imageStore() or
5923
    imageAtomic*() on a single level - and either one or all layers - of a
5924
    texture exposed to the shader as an image object)
5925
5926
    \value ImageLoadStore Image load and store
5927
5928
    \value BufferLoad Storage buffer load (with GLSL this maps to reading from
5929
    a shader storage buffer)
5930
5931
    \value BufferStore Storage buffer store (with GLSL this maps to writing to
5932
    a shader storage buffer)
5933
5934
    \value BufferLoadStore Storage buffer load and store
5935
 */
5936
5937
/*!
5938
    \enum QRhiShaderResourceBinding::StageFlag
5939
    Flag values to indicate which stages the shader resource is visible in
5940
5941
    \value VertexStage Vertex stage
5942
    \value TessellationControlStage Tessellation control (hull shader) stage
5943
    \value TessellationEvaluationStage Tessellation evaluation (domain shader) stage
5944
    \value FragmentStage Fragment (pixel shader) stage
5945
    \value ComputeStage Compute stage
5946
    \value GeometryStage Geometry stage
5947
 */
5948
5949
/*!
5950
    \return \c true if the layout is compatible with \a other. The layout does not
5951
    include the actual resource (such as, buffer or texture) and related
5952
    parameters (such as, offset or size).
5953
5954
    For example, \c a and \c b below are not equal, but are compatible layout-wise:
5955
5956
    \code
5957
        auto a = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buffer);
5958
        auto b = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, someOtherBuffer, 256);
5959
    \endcode
5960
 */
5961
bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBinding &other) const
5962
0
{
5963
    // everything that goes into a VkDescriptorSetLayoutBinding must match
5964
0
    return d.binding == other.d.binding
5965
0
            && d.stage == other.d.stage
5966
0
            && d.type == other.d.type
5967
0
            && d.arraySize() == other.d.arraySize();
5968
0
}
5969
5970
/*!
5971
    \return a shader resource binding for the given binding number, pipeline
5972
    stages, and buffer specified by \a binding, \a stage, and \a buf.
5973
5974
    \note When \a buf is not null, it must have been created with
5975
    QRhiBuffer::UniformBuffer.
5976
5977
    \note \a buf can be null. It is valid to create a
5978
    QRhiShaderResourceBindings with unspecified resources, but such an object
5979
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
5980
    suitable for creating pipelines. Such a pipeline must then always be used
5981
    together with another, layout compatible QRhiShaderResourceBindings with
5982
    resources present passed to QRhiCommandBuffer::setShaderResources().
5983
5984
    \note If the size of \a buf exceeds the limit reported for
5985
    QRhi::MaxUniformBufferRange, unexpected errors may occur.
5986
 */
5987
QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
5988
        int binding, StageFlags stage, QRhiBuffer *buf)
5989
0
{
5990
0
    QRhiShaderResourceBinding b;
5991
0
    b.d.binding = binding;
5992
0
    b.d.stage = stage;
5993
0
    b.d.type = UniformBuffer;
5994
0
    b.d.u.ubuf.buf = buf;
5995
0
    b.d.u.ubuf.offset = 0;
5996
0
    b.d.u.ubuf.maybeSize = 0; // entire buffer
5997
0
    b.d.u.ubuf.hasDynamicOffset = false;
5998
0
    return b;
5999
0
}
6000
6001
/*!
6002
    \return a shader resource binding for the given binding number, pipeline
6003
    stages, and buffer specified by \a binding, \a stage, and \a buf. This
6004
    overload binds a region only, as specified by \a offset and \a size.
6005
6006
    \note It is up to the user to ensure the offset is aligned to
6007
    QRhi::ubufAlignment().
6008
6009
    \note \a size must be greater than 0.
6010
6011
    \note When \a buf is not null, it must have been created with
6012
    QRhiBuffer::UniformBuffer.
6013
6014
    \note \a buf can be null. It is valid to create a
6015
    QRhiShaderResourceBindings with unspecified resources, but such an object
6016
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6017
    suitable for creating pipelines. Such a pipeline must then always be used
6018
    together with another, layout compatible QRhiShaderResourceBindings with
6019
    resources present passed to QRhiCommandBuffer::setShaderResources().
6020
6021
    \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
6022
    unexpected errors may occur.
6023
 */
6024
QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
6025
        int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6026
0
{
6027
0
    Q_ASSERT(size > 0);
6028
0
    QRhiShaderResourceBinding b;
6029
0
    b.d.binding = binding;
6030
0
    b.d.stage = stage;
6031
0
    b.d.type = UniformBuffer;
6032
0
    b.d.u.ubuf.buf = buf;
6033
0
    b.d.u.ubuf.offset = offset;
6034
0
    b.d.u.ubuf.maybeSize = size;
6035
0
    b.d.u.ubuf.hasDynamicOffset = false;
6036
0
    return b;
6037
0
}
6038
6039
/*!
6040
    \return a shader resource binding for the given binding number, pipeline
6041
    stages, and buffer specified by \a binding, \a stage, and \a buf. The
6042
    uniform buffer is assumed to have dynamic offset. The dynamic offset can be
6043
    specified in QRhiCommandBuffer::setShaderResources(), thus allowing using
6044
    varying offset values without creating new bindings for the buffer. The
6045
    size of the bound region is specified by \a size. Like with non-dynamic
6046
    offsets, \c{offset + size} cannot exceed the size of \a buf.
6047
6048
    \note When \a buf is not null, it must have been created with
6049
    QRhiBuffer::UniformBuffer.
6050
6051
    \note \a buf can be null. It is valid to create a
6052
    QRhiShaderResourceBindings with unspecified resources, but such an object
6053
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6054
    suitable for creating pipelines. Such a pipeline must then always be used
6055
    together with another, layout compatible QRhiShaderResourceBindings with
6056
    resources present passed to QRhiCommandBuffer::setShaderResources().
6057
6058
    \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
6059
    unexpected errors may occur.
6060
 */
6061
QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(
6062
        int binding, StageFlags stage, QRhiBuffer *buf, quint32 size)
6063
0
{
6064
0
    Q_ASSERT(size > 0);
6065
0
    QRhiShaderResourceBinding b;
6066
0
    b.d.binding = binding;
6067
0
    b.d.stage = stage;
6068
0
    b.d.type = UniformBuffer;
6069
0
    b.d.u.ubuf.buf = buf;
6070
0
    b.d.u.ubuf.offset = 0;
6071
0
    b.d.u.ubuf.maybeSize = size;
6072
0
    b.d.u.ubuf.hasDynamicOffset = true;
6073
0
    return b;
6074
0
}
6075
6076
/*!
6077
    \return a shader resource binding for the given binding number, pipeline
6078
    stages, texture, and sampler specified by \a binding, \a stage, \a tex,
6079
    \a sampler.
6080
6081
    \note This function is equivalent to calling sampledTextures() with a
6082
    \c count of 1.
6083
6084
    \note \a tex and \a sampler can be null. It is valid to create a
6085
    QRhiShaderResourceBindings with unspecified resources, but such an object
6086
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6087
    suitable for creating pipelines. Such a pipeline must then always be used
6088
    together with another, layout compatible QRhiShaderResourceBindings with
6089
    resources present passed to QRhiCommandBuffer::setShaderResources().
6090
6091
    \note A shader may not be able to consume more than 16 textures/samplers,
6092
    depending on the underlying graphics API. This hard limit must be kept in
6093
    mind in renderer design. This does not apply to texture arrays which
6094
    consume a single binding point (shader register) and can contain 256-2048
6095
    textures, depending on the underlying graphics API. Arrays of textures (see
6096
    sampledTextures()) are however no different in this regard than using the
6097
    same number of individual textures.
6098
6099
    \sa sampledTextures()
6100
 */
6101
QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
6102
        int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
6103
0
{
6104
0
    QRhiShaderResourceBinding b;
6105
0
    b.d.binding = binding;
6106
0
    b.d.stage = stage;
6107
0
    b.d.type = SampledTexture;
6108
0
    b.d.u.stex.count = 1;
6109
0
    b.d.u.stex.texSamplers[0] = { tex, sampler };
6110
0
    return b;
6111
0
}
6112
6113
/*!
6114
    \return a shader resource binding for the given binding number, pipeline
6115
    stages, and the array of texture-sampler pairs specified by \a binding, \a
6116
    stage, \a count, and \a texSamplers.
6117
6118
    \note \a count must be at least 1, and not larger than 16.
6119
6120
    \note When \a count is 1, this function is equivalent to sampledTexture().
6121
6122
    This function is relevant when arrays of combined image samplers are
6123
    involved. For example, in GLSL \c{layout(binding = 5) uniform sampler2D
6124
    shadowMaps[8];} declares an array of combined image samplers. The
6125
    application is then expected provide a QRhiShaderResourceBinding for
6126
    binding point 5, set up by calling this function with \a count set to 8 and
6127
    a valid texture and sampler for each element of the array.
6128
6129
    \warning All elements of the array must be specified. With the above
6130
    example, the only valid, portable approach is calling this function with a
6131
    \a count of 8. Additionally, all QRhiTexture and QRhiSampler instances must
6132
    be valid, meaning nullptr is not an accepted value. This is due to some of
6133
    the underlying APIs, such as, Vulkan, that require a valid image and
6134
    sampler object for each element in descriptor arrays. Applications are
6135
    advised to provide "dummy" samplers and textures if some array elements are
6136
    not relevant (due to not being accessed in the shader).
6137
6138
    \note \a texSamplers can be null. It is valid to create a
6139
    QRhiShaderResourceBindings with unspecified resources, but such an object
6140
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6141
    suitable for creating pipelines. Such a pipeline must then always be used
6142
    together with another, layout compatible QRhiShaderResourceBindings with
6143
    resources present passed to QRhiCommandBuffer::setShaderResources().
6144
6145
    \sa sampledTexture()
6146
 */
6147
QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTextures(
6148
        int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers)
6149
0
{
6150
0
    Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
6151
0
    QRhiShaderResourceBinding b;
6152
0
    b.d.binding = binding;
6153
0
    b.d.stage = stage;
6154
0
    b.d.type = SampledTexture;
6155
0
    b.d.u.stex.count = count;
6156
0
    for (int i = 0; i < count; ++i) {
6157
0
        if (texSamplers)
6158
0
            b.d.u.stex.texSamplers[i] = texSamplers[i];
6159
0
        else
6160
0
            b.d.u.stex.texSamplers[i] = { nullptr, nullptr };
6161
0
    }
6162
0
    return b;
6163
0
}
6164
6165
/*!
6166
    \return a shader resource binding for the given binding number, pipeline
6167
    stages, and texture specified by \a binding, \a stage, \a tex.
6168
6169
    \note This function is equivalent to calling textures() with a
6170
    \c count of 1.
6171
6172
    \note \a tex can be null. It is valid to create a
6173
    QRhiShaderResourceBindings with unspecified resources, but such an object
6174
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6175
    suitable for creating pipelines. Such a pipeline must then always be used
6176
    together with another, layout compatible QRhiShaderResourceBindings with
6177
    resources present passed to QRhiCommandBuffer::setShaderResources().
6178
6179
    This creates a binding for a separate texture (image) object, whereas
6180
    sampledTexture() is suitable for combined image samplers. In
6181
    Vulkan-compatible GLSL code separate textures are declared as \c texture2D
6182
    as opposed to \c sampler2D: \c{layout(binding = 1) uniform texture2D tex;}
6183
6184
    \note A shader may not be able to consume more than 16 textures, depending
6185
    on the underlying graphics API. This hard limit must be kept in mind in
6186
    renderer design. This does not apply to texture arrays which consume a
6187
    single binding point (shader register) and can contain 256-2048 textures,
6188
    depending on the underlying graphics API. Arrays of textures (see
6189
    sampledTextures()) are however no different in this regard than using the
6190
    same number of individual textures.
6191
6192
    \sa textures(), sampler()
6193
 */
6194
QRhiShaderResourceBinding QRhiShaderResourceBinding::texture(int binding, StageFlags stage, QRhiTexture *tex)
6195
0
{
6196
0
    QRhiShaderResourceBinding b;
6197
0
    b.d.binding = binding;
6198
0
    b.d.stage = stage;
6199
0
    b.d.type = Texture;
6200
0
    b.d.u.stex.count = 1;
6201
0
    b.d.u.stex.texSamplers[0] = { tex, nullptr };
6202
0
    return b;
6203
0
}
6204
6205
/*!
6206
    \return a shader resource binding for the given binding number, pipeline
6207
    stages, and the array of (separate) textures specified by \a binding, \a
6208
    stage, \a count, and \a tex.
6209
6210
    \note \a count must be at least 1, and not larger than 16.
6211
6212
    \note When \a count is 1, this function is equivalent to texture().
6213
6214
    \warning All elements of the array must be specified.
6215
6216
    \note \a tex can be null. It is valid to create a
6217
    QRhiShaderResourceBindings with unspecified resources, but such an object
6218
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6219
    suitable for creating pipelines. Such a pipeline must then always be used
6220
    together with another, layout compatible QRhiShaderResourceBindings with
6221
    resources present passed to QRhiCommandBuffer::setShaderResources().
6222
6223
    \sa texture(), sampler()
6224
 */
6225
QRhiShaderResourceBinding QRhiShaderResourceBinding::textures(int binding, StageFlags stage, int count, QRhiTexture **tex)
6226
0
{
6227
0
    Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
6228
0
    QRhiShaderResourceBinding b;
6229
0
    b.d.binding = binding;
6230
0
    b.d.stage = stage;
6231
0
    b.d.type = Texture;
6232
0
    b.d.u.stex.count = count;
6233
0
    for (int i = 0; i < count; ++i) {
6234
0
        if (tex)
6235
0
            b.d.u.stex.texSamplers[i] = { tex[i], nullptr };
6236
0
        else
6237
0
            b.d.u.stex.texSamplers[i] = { nullptr, nullptr };
6238
0
    }
6239
0
    return b;
6240
0
}
6241
6242
/*!
6243
    \return a shader resource binding for the given binding number, pipeline
6244
    stages, and sampler specified by \a binding, \a stage, \a sampler.
6245
6246
    \note \a sampler can be null. It is valid to create a
6247
    QRhiShaderResourceBindings with unspecified resources, but such an object
6248
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6249
    suitable for creating pipelines. Such a pipeline must then always be used
6250
    together with another, layout compatible QRhiShaderResourceBindings with
6251
    resources present passed to QRhiCommandBuffer::setShaderResources().
6252
6253
    Arrays of separate samplers are not supported.
6254
6255
    This creates a binding for a separate sampler object, whereas
6256
    sampledTexture() is suitable for combined image samplers. In
6257
    Vulkan-compatible GLSL code separate samplers are declared as \c sampler
6258
    as opposed to \c sampler2D: \c{layout(binding = 2) uniform sampler samp;}
6259
6260
    With both a \c texture2D and \c sampler present, they can be used together
6261
    to sample the texture: \c{fragColor = texture(sampler2D(tex, samp),
6262
    texcoord);}.
6263
6264
    \note A shader may not be able to consume more than 16 samplers, depending
6265
    on the underlying graphics API. This hard limit must be kept in mind in
6266
    renderer design.
6267
6268
    \sa texture()
6269
 */
6270
QRhiShaderResourceBinding QRhiShaderResourceBinding::sampler(int binding, StageFlags stage, QRhiSampler *sampler)
6271
0
{
6272
0
    QRhiShaderResourceBinding b;
6273
0
    b.d.binding = binding;
6274
0
    b.d.stage = stage;
6275
0
    b.d.type = Sampler;
6276
0
    b.d.u.stex.count = 1;
6277
0
    b.d.u.stex.texSamplers[0] = { nullptr, sampler };
6278
0
    return b;
6279
0
}
6280
6281
/*!
6282
   \return a shader resource binding for a read-only storage image with the
6283
   given \a binding number and pipeline \a stage. The image load operations
6284
   will have access to all layers of the specified \a level. (so if the texture
6285
   is a cubemap, the shader must use imageCube instead of image2D)
6286
6287
   \note When \a tex is not null, it must have been created with
6288
   QRhiTexture::UsedWithLoadStore.
6289
6290
   \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6291
   with unspecified resources, but such an object cannot be used with
6292
   QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6293
   pipelines. Such a pipeline must then always be used together with another,
6294
   layout compatible QRhiShaderResourceBindings with resources present passed
6295
   to QRhiCommandBuffer::setShaderResources().
6296
6297
   \note Image load/store is only available within the compute and fragment stages.
6298
 */
6299
QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoad(
6300
        int binding, StageFlags stage, QRhiTexture *tex, int level)
6301
0
{
6302
0
    QRhiShaderResourceBinding b;
6303
0
    b.d.binding = binding;
6304
0
    b.d.stage = stage;
6305
0
    b.d.type = ImageLoad;
6306
0
    b.d.u.simage.tex = tex;
6307
0
    b.d.u.simage.level = level;
6308
0
    return b;
6309
0
}
6310
6311
/*!
6312
   \return a shader resource binding for a write-only storage image with the
6313
   given \a binding number and pipeline \a stage. The image store operations
6314
   will have access to all layers of the specified \a level. (so if the texture
6315
   is a cubemap, the shader must use imageCube instead of image2D)
6316
6317
   \note When \a tex is not null, it must have been created with
6318
   QRhiTexture::UsedWithLoadStore.
6319
6320
   \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6321
   with unspecified resources, but such an object cannot be used with
6322
   QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6323
   pipelines. Such a pipeline must then always be used together with another,
6324
   layout compatible QRhiShaderResourceBindings with resources present passed
6325
   to QRhiCommandBuffer::setShaderResources().
6326
6327
   \note Image load/store is only available within the compute and fragment stages.
6328
 */
6329
QRhiShaderResourceBinding QRhiShaderResourceBinding::imageStore(
6330
        int binding, StageFlags stage, QRhiTexture *tex, int level)
6331
0
{
6332
0
    QRhiShaderResourceBinding b;
6333
0
    b.d.binding = binding;
6334
0
    b.d.stage = stage;
6335
0
    b.d.type = ImageStore;
6336
0
    b.d.u.simage.tex = tex;
6337
0
    b.d.u.simage.level = level;
6338
0
    return b;
6339
0
}
6340
6341
/*!
6342
   \return a shader resource binding for a read/write storage image with the
6343
   given \a binding number and pipeline \a stage. The image load/store operations
6344
   will have access to all layers of the specified \a level. (so if the texture
6345
   is a cubemap, the shader must use imageCube instead of image2D)
6346
6347
   \note When \a tex is not null, it must have been created with
6348
   QRhiTexture::UsedWithLoadStore.
6349
6350
   \note \a tex can be null. It is valid to create a QRhiShaderResourceBindings
6351
   with unspecified resources, but such an object cannot be used with
6352
   QRhiCommandBuffer::setShaderResources(). It is however suitable for creating
6353
   pipelines. Such a pipeline must then always be used together with another,
6354
   layout compatible QRhiShaderResourceBindings with resources present passed
6355
   to QRhiCommandBuffer::setShaderResources().
6356
6357
   \note Image load/store is only available within the compute and fragment stages.
6358
 */
6359
QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoadStore(
6360
        int binding, StageFlags stage, QRhiTexture *tex, int level)
6361
0
{
6362
0
    QRhiShaderResourceBinding b;
6363
0
    b.d.binding = binding;
6364
0
    b.d.stage = stage;
6365
0
    b.d.type = ImageLoadStore;
6366
0
    b.d.u.simage.tex = tex;
6367
0
    b.d.u.simage.level = level;
6368
0
    return b;
6369
0
}
6370
6371
/*!
6372
    \return a shader resource binding for a read-only storage buffer with the
6373
    given \a binding number and pipeline \a stage.
6374
6375
    \note When \a buf is not null, must have been created with
6376
    QRhiBuffer::StorageBuffer.
6377
6378
    \note \a buf can be null. It is valid to create a
6379
    QRhiShaderResourceBindings with unspecified resources, but such an object
6380
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6381
    suitable for creating pipelines. Such a pipeline must then always be used
6382
    together with another, layout compatible QRhiShaderResourceBindings with
6383
    resources present passed to QRhiCommandBuffer::setShaderResources().
6384
6385
    \note Buffer load/store is only guaranteed to be available within a compute
6386
    pipeline. While some backends may support using these resources in a
6387
    graphics pipeline as well, this is not universally supported, and even when
6388
    it is, unexpected problems may arise when it comes to barriers and
6389
    synchronization. Therefore, avoid using such resources with shaders other
6390
    than compute.
6391
 */
6392
QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6393
        int binding, StageFlags stage, QRhiBuffer *buf)
6394
0
{
6395
0
    QRhiShaderResourceBinding b;
6396
0
    b.d.binding = binding;
6397
0
    b.d.stage = stage;
6398
0
    b.d.type = BufferLoad;
6399
0
    b.d.u.sbuf.buf = buf;
6400
0
    b.d.u.sbuf.offset = 0;
6401
0
    b.d.u.sbuf.maybeSize = 0; // entire buffer
6402
0
    return b;
6403
0
}
6404
6405
/*!
6406
    \return a shader resource binding for a read-only storage buffer with the
6407
    given \a binding number and pipeline \a stage. This overload binds a region
6408
    only, as specified by \a offset and \a size.
6409
6410
    \note When \a buf is not null, must have been created with
6411
    QRhiBuffer::StorageBuffer.
6412
6413
    \note \a buf can be null. It is valid to create a
6414
    QRhiShaderResourceBindings with unspecified resources, but such an object
6415
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6416
    suitable for creating pipelines. Such a pipeline must then always be used
6417
    together with another, layout compatible QRhiShaderResourceBindings with
6418
    resources present passed to QRhiCommandBuffer::setShaderResources().
6419
6420
    \note Buffer load/store is only guaranteed to be available within a compute
6421
    pipeline. While some backends may support using these resources in a
6422
    graphics pipeline as well, this is not universally supported, and even when
6423
    it is, unexpected problems may arise when it comes to barriers and
6424
    synchronization. Therefore, avoid using such resources with shaders other
6425
    than compute.
6426
 */
6427
QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
6428
        int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6429
0
{
6430
0
    Q_ASSERT(size > 0);
6431
0
    QRhiShaderResourceBinding b;
6432
0
    b.d.binding = binding;
6433
0
    b.d.stage = stage;
6434
0
    b.d.type = BufferLoad;
6435
0
    b.d.u.sbuf.buf = buf;
6436
0
    b.d.u.sbuf.offset = offset;
6437
0
    b.d.u.sbuf.maybeSize = size;
6438
0
    return b;
6439
0
}
6440
6441
/*!
6442
    \return a shader resource binding for a write-only storage buffer with the
6443
    given \a binding number and pipeline \a stage.
6444
6445
    \note When \a buf is not null, must have been created with
6446
    QRhiBuffer::StorageBuffer.
6447
6448
    \note \a buf can be null. It is valid to create a
6449
    QRhiShaderResourceBindings with unspecified resources, but such an object
6450
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6451
    suitable for creating pipelines. Such a pipeline must then always be used
6452
    together with another, layout compatible QRhiShaderResourceBindings with
6453
    resources present passed to QRhiCommandBuffer::setShaderResources().
6454
6455
    \note Buffer load/store is only guaranteed to be available within a compute
6456
    pipeline. While some backends may support using these resources in a
6457
    graphics pipeline as well, this is not universally supported, and even when
6458
    it is, unexpected problems may arise when it comes to barriers and
6459
    synchronization. Therefore, avoid using such resources with shaders other
6460
    than compute.
6461
 */
6462
QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6463
        int binding, StageFlags stage, QRhiBuffer *buf)
6464
0
{
6465
0
    QRhiShaderResourceBinding b;
6466
0
    b.d.binding = binding;
6467
0
    b.d.stage = stage;
6468
0
    b.d.type = BufferStore;
6469
0
    b.d.u.sbuf.buf = buf;
6470
0
    b.d.u.sbuf.offset = 0;
6471
0
    b.d.u.sbuf.maybeSize = 0; // entire buffer
6472
0
    return b;
6473
0
}
6474
6475
/*!
6476
    \return a shader resource binding for a write-only storage buffer with the
6477
    given \a binding number and pipeline \a stage. This overload binds a region
6478
    only, as specified by \a offset and \a size.
6479
6480
    \note When \a buf is not null, must have been created with
6481
    QRhiBuffer::StorageBuffer.
6482
6483
    \note \a buf can be null. It is valid to create a
6484
    QRhiShaderResourceBindings with unspecified resources, but such an object
6485
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6486
    suitable for creating pipelines. Such a pipeline must then always be used
6487
    together with another, layout compatible QRhiShaderResourceBindings with
6488
    resources present passed to QRhiCommandBuffer::setShaderResources().
6489
6490
    \note Buffer load/store is only guaranteed to be available within a compute
6491
    pipeline. While some backends may support using these resources in a
6492
    graphics pipeline as well, this is not universally supported, and even when
6493
    it is, unexpected problems may arise when it comes to barriers and
6494
    synchronization. Therefore, avoid using such resources with shaders other
6495
    than compute.
6496
 */
6497
QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
6498
        int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6499
0
{
6500
0
    Q_ASSERT(size > 0);
6501
0
    QRhiShaderResourceBinding b;
6502
0
    b.d.binding = binding;
6503
0
    b.d.stage = stage;
6504
0
    b.d.type = BufferStore;
6505
0
    b.d.u.sbuf.buf = buf;
6506
0
    b.d.u.sbuf.offset = offset;
6507
0
    b.d.u.sbuf.maybeSize = size;
6508
0
    return b;
6509
0
}
6510
6511
/*!
6512
    \return a shader resource binding for a read-write storage buffer with the
6513
    given \a binding number and pipeline \a stage.
6514
6515
    \note When \a buf is not null, must have been created with
6516
    QRhiBuffer::StorageBuffer.
6517
6518
    \note \a buf can be null. It is valid to create a
6519
    QRhiShaderResourceBindings with unspecified resources, but such an object
6520
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6521
    suitable for creating pipelines. Such a pipeline must then always be used
6522
    together with another, layout compatible QRhiShaderResourceBindings with
6523
    resources present passed to QRhiCommandBuffer::setShaderResources().
6524
6525
    \note Buffer load/store is only guaranteed to be available within a compute
6526
    pipeline. While some backends may support using these resources in a
6527
    graphics pipeline as well, this is not universally supported, and even when
6528
    it is, unexpected problems may arise when it comes to barriers and
6529
    synchronization. Therefore, avoid using such resources with shaders other
6530
    than compute.
6531
 */
6532
QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6533
        int binding, StageFlags stage, QRhiBuffer *buf)
6534
0
{
6535
0
    QRhiShaderResourceBinding b;
6536
0
    b.d.binding = binding;
6537
0
    b.d.stage = stage;
6538
0
    b.d.type = BufferLoadStore;
6539
0
    b.d.u.sbuf.buf = buf;
6540
0
    b.d.u.sbuf.offset = 0;
6541
0
    b.d.u.sbuf.maybeSize = 0; // entire buffer
6542
0
    return b;
6543
0
}
6544
6545
/*!
6546
    \return a shader resource binding for a read-write storage buffer with the
6547
    given \a binding number and pipeline \a stage. This overload binds a region
6548
    only, as specified by \a offset and \a size.
6549
6550
    \note When \a buf is not null, must have been created with
6551
    QRhiBuffer::StorageBuffer.
6552
6553
    \note \a buf can be null. It is valid to create a
6554
    QRhiShaderResourceBindings with unspecified resources, but such an object
6555
    cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
6556
    suitable for creating pipelines. Such a pipeline must then always be used
6557
    together with another, layout compatible QRhiShaderResourceBindings with
6558
    resources present passed to QRhiCommandBuffer::setShaderResources().
6559
6560
    \note Buffer load/store is only guaranteed to be available within a compute
6561
    pipeline. While some backends may support using these resources in a
6562
    graphics pipeline as well, this is not universally supported, and even when
6563
    it is, unexpected problems may arise when it comes to barriers and
6564
    synchronization. Therefore, avoid using such resources with shaders other
6565
    than compute.
6566
 */
6567
QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
6568
        int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
6569
0
{
6570
0
    Q_ASSERT(size > 0);
6571
0
    QRhiShaderResourceBinding b;
6572
0
    b.d.binding = binding;
6573
0
    b.d.stage = stage;
6574
0
    b.d.type = BufferLoadStore;
6575
0
    b.d.u.sbuf.buf = buf;
6576
0
    b.d.u.sbuf.offset = offset;
6577
0
    b.d.u.sbuf.maybeSize = size;
6578
0
    return b;
6579
0
}
6580
6581
/*!
6582
    \return \c true if the contents of the two QRhiShaderResourceBinding
6583
    objects \a a and \a b are equal. This includes the resources (buffer,
6584
    texture) and related parameters (offset, size) as well. To only compare
6585
    layouts (binding point, pipeline stage, resource type), use
6586
    \l{QRhiShaderResourceBinding::isLayoutCompatible()}{isLayoutCompatible()}
6587
    instead.
6588
6589
    \relates QRhiShaderResourceBinding
6590
 */
6591
bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6592
0
{
6593
0
    const QRhiShaderResourceBinding::Data *da = QRhiImplementation::shaderResourceBindingData(a);
6594
0
    const QRhiShaderResourceBinding::Data *db = QRhiImplementation::shaderResourceBindingData(b);
6595
6596
0
    if (da == db)
6597
0
        return true;
6598
6599
6600
0
    if (da->binding != db->binding
6601
0
            || da->stage != db->stage
6602
0
            || da->type != db->type)
6603
0
    {
6604
0
        return false;
6605
0
    }
6606
6607
0
    switch (da->type) {
6608
0
    case QRhiShaderResourceBinding::UniformBuffer:
6609
0
        if (da->u.ubuf.buf != db->u.ubuf.buf
6610
0
                || da->u.ubuf.offset != db->u.ubuf.offset
6611
0
                || da->u.ubuf.maybeSize != db->u.ubuf.maybeSize)
6612
0
        {
6613
0
            return false;
6614
0
        }
6615
0
        break;
6616
0
    case QRhiShaderResourceBinding::SampledTexture:
6617
0
        if (da->u.stex.count != db->u.stex.count)
6618
0
            return false;
6619
0
        for (int i = 0; i < da->u.stex.count; ++i) {
6620
0
            if (da->u.stex.texSamplers[i].tex != db->u.stex.texSamplers[i].tex
6621
0
                    || da->u.stex.texSamplers[i].sampler != db->u.stex.texSamplers[i].sampler)
6622
0
            {
6623
0
                return false;
6624
0
            }
6625
0
        }
6626
0
        break;
6627
0
    case QRhiShaderResourceBinding::Texture:
6628
0
        if (da->u.stex.count != db->u.stex.count)
6629
0
            return false;
6630
0
        for (int i = 0; i < da->u.stex.count; ++i) {
6631
0
            if (da->u.stex.texSamplers[i].tex != db->u.stex.texSamplers[i].tex)
6632
0
                return false;
6633
0
        }
6634
0
        break;
6635
0
    case QRhiShaderResourceBinding::Sampler:
6636
0
        if (da->u.stex.texSamplers[0].sampler != db->u.stex.texSamplers[0].sampler)
6637
0
            return false;
6638
0
        break;
6639
0
    case QRhiShaderResourceBinding::ImageLoad:
6640
0
    case QRhiShaderResourceBinding::ImageStore:
6641
0
    case QRhiShaderResourceBinding::ImageLoadStore:
6642
0
        if (da->u.simage.tex != db->u.simage.tex
6643
0
                || da->u.simage.level != db->u.simage.level)
6644
0
        {
6645
0
            return false;
6646
0
        }
6647
0
        break;
6648
0
    case QRhiShaderResourceBinding::BufferLoad:
6649
0
    case QRhiShaderResourceBinding::BufferStore:
6650
0
    case QRhiShaderResourceBinding::BufferLoadStore:
6651
0
        if (da->u.sbuf.buf != db->u.sbuf.buf
6652
0
                || da->u.sbuf.offset != db->u.sbuf.offset
6653
0
                || da->u.sbuf.maybeSize != db->u.sbuf.maybeSize)
6654
0
        {
6655
0
            return false;
6656
0
        }
6657
0
        break;
6658
0
    default:
6659
0
        Q_UNREACHABLE_RETURN(false);
6660
0
    }
6661
6662
0
    return true;
6663
0
}
6664
6665
/*!
6666
    \return \c false if all the bindings in the two QRhiShaderResourceBinding
6667
    objects \a a and \a b are equal; otherwise returns \c true.
6668
6669
    \relates QRhiShaderResourceBinding
6670
 */
6671
bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
6672
0
{
6673
0
    return !(a == b);
6674
0
}
6675
6676
/*!
6677
    \fn size_t qHash(const QRhiShaderResourceBinding &key, size_t seed)
6678
    \qhashold{QRhiShaderResourceBinding}
6679
 */
6680
size_t qHash(const QRhiShaderResourceBinding &b, size_t seed) noexcept
6681
0
{
6682
0
    const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6683
0
    QtPrivate::QHashCombineWithSeed hash(seed);
6684
0
    seed = hash(seed, d->binding);
6685
0
    seed = hash(seed, d->stage);
6686
0
    seed = hash(seed, d->type);
6687
0
    switch (d->type) {
6688
0
    case QRhiShaderResourceBinding::UniformBuffer:
6689
0
        seed = hash(seed, reinterpret_cast<quintptr>(d->u.ubuf.buf));
6690
0
        break;
6691
0
    case QRhiShaderResourceBinding::SampledTexture:
6692
0
        seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].tex));
6693
0
        seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].sampler));
6694
0
        break;
6695
0
    case QRhiShaderResourceBinding::Texture:
6696
0
        seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].tex));
6697
0
        break;
6698
0
    case QRhiShaderResourceBinding::Sampler:
6699
0
        seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].sampler));
6700
0
        break;
6701
0
    case QRhiShaderResourceBinding::ImageLoad:
6702
0
    case QRhiShaderResourceBinding::ImageStore:
6703
0
    case QRhiShaderResourceBinding::ImageLoadStore:
6704
0
        seed = hash(seed, reinterpret_cast<quintptr>(d->u.simage.tex));
6705
0
        break;
6706
0
    case QRhiShaderResourceBinding::BufferLoad:
6707
0
    case QRhiShaderResourceBinding::BufferStore:
6708
0
    case QRhiShaderResourceBinding::BufferLoadStore:
6709
0
        seed = hash(seed, reinterpret_cast<quintptr>(d->u.sbuf.buf));
6710
0
        break;
6711
0
    }
6712
0
    return seed;
6713
0
}
6714
6715
#ifndef QT_NO_DEBUG_STREAM
6716
QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
6717
0
{
6718
0
    QDebugStateSaver saver(dbg);
6719
0
    const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
6720
0
    dbg.nospace() << "QRhiShaderResourceBinding("
6721
0
                  << "binding=" << d->binding
6722
0
                  << " stage=" << d->stage
6723
0
                  << " type=" << d->type;
6724
0
    switch (d->type) {
6725
0
    case QRhiShaderResourceBinding::UniformBuffer:
6726
0
        dbg.nospace() << " UniformBuffer("
6727
0
                      << "buffer=" << d->u.ubuf.buf
6728
0
                      << " offset=" << d->u.ubuf.offset
6729
0
                      << " maybeSize=" << d->u.ubuf.maybeSize
6730
0
                      << ')';
6731
0
        break;
6732
0
    case QRhiShaderResourceBinding::SampledTexture:
6733
0
        dbg.nospace() << " SampledTextures("
6734
0
                      << "count=" << d->u.stex.count;
6735
0
        for (int i = 0; i < d->u.stex.count; ++i) {
6736
0
            dbg.nospace() << " texture=" << d->u.stex.texSamplers[i].tex
6737
0
                          << " sampler=" << d->u.stex.texSamplers[i].sampler;
6738
0
        }
6739
0
        dbg.nospace() << ')';
6740
0
        break;
6741
0
    case QRhiShaderResourceBinding::Texture:
6742
0
        dbg.nospace() << " Textures("
6743
0
                      << "count=" << d->u.stex.count;
6744
0
        for (int i = 0; i < d->u.stex.count; ++i)
6745
0
            dbg.nospace() << " texture=" << d->u.stex.texSamplers[i].tex;
6746
0
        dbg.nospace() << ')';
6747
0
        break;
6748
0
    case QRhiShaderResourceBinding::Sampler:
6749
0
        dbg.nospace() << " Sampler("
6750
0
                      << " sampler=" << d->u.stex.texSamplers[0].sampler
6751
0
                      << ')';
6752
0
        break;
6753
0
    case QRhiShaderResourceBinding::ImageLoad:
6754
0
        dbg.nospace() << " ImageLoad("
6755
0
                      << "texture=" << d->u.simage.tex
6756
0
                      << " level=" << d->u.simage.level
6757
0
                      << ')';
6758
0
        break;
6759
0
    case QRhiShaderResourceBinding::ImageStore:
6760
0
        dbg.nospace() << " ImageStore("
6761
0
                      << "texture=" << d->u.simage.tex
6762
0
                      << " level=" << d->u.simage.level
6763
0
                      << ')';
6764
0
        break;
6765
0
    case QRhiShaderResourceBinding::ImageLoadStore:
6766
0
        dbg.nospace() << " ImageLoadStore("
6767
0
                      << "texture=" << d->u.simage.tex
6768
0
                      << " level=" << d->u.simage.level
6769
0
                      << ')';
6770
0
        break;
6771
0
    case QRhiShaderResourceBinding::BufferLoad:
6772
0
        dbg.nospace() << " BufferLoad("
6773
0
                      << "buffer=" << d->u.sbuf.buf
6774
0
                      << " offset=" << d->u.sbuf.offset
6775
0
                      << " maybeSize=" << d->u.sbuf.maybeSize
6776
0
                      << ')';
6777
0
        break;
6778
0
    case QRhiShaderResourceBinding::BufferStore:
6779
0
        dbg.nospace() << " BufferStore("
6780
0
                      << "buffer=" << d->u.sbuf.buf
6781
0
                      << " offset=" << d->u.sbuf.offset
6782
0
                      << " maybeSize=" << d->u.sbuf.maybeSize
6783
0
                      << ')';
6784
0
        break;
6785
0
    case QRhiShaderResourceBinding::BufferLoadStore:
6786
0
        dbg.nospace() << " BufferLoadStore("
6787
0
                      << "buffer=" << d->u.sbuf.buf
6788
0
                      << " offset=" << d->u.sbuf.offset
6789
0
                      << " maybeSize=" << d->u.sbuf.maybeSize
6790
0
                      << ')';
6791
0
        break;
6792
0
    default:
6793
0
        dbg.nospace() << " UNKNOWN()";
6794
0
        break;
6795
0
    }
6796
0
    dbg.nospace() << ')';
6797
0
    return dbg;
6798
0
}
6799
#endif
6800
6801
#ifndef QT_NO_DEBUG_STREAM
6802
QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
6803
0
{
6804
0
    QDebugStateSaver saver(dbg);
6805
0
    dbg.nospace() << "QRhiShaderResourceBindings("
6806
0
                  << srb.m_bindings
6807
0
                  << ')';
6808
0
    return dbg;
6809
0
}
6810
#endif
6811
6812
/*!
6813
    \class QRhiGraphicsPipeline
6814
    \inmodule QtGuiPrivate
6815
    \inheaderfile rhi/qrhi.h
6816
    \since 6.6
6817
    \brief Graphics pipeline state resource.
6818
6819
    Represents a graphics pipeline. What exactly this map to in the underlying
6820
    native graphics API, varies. Where there is a concept of pipeline objects,
6821
    for example with Vulkan, the QRhi backend will create such an object upon
6822
    calling create(). Elsewhere, for example with OpenGL, the
6823
    QRhiGraphicsPipeline may merely collect the various state, and create()'s
6824
    main task is to set up the corresponding shader program, but deferring
6825
    looking at any of the requested state to a later point.
6826
6827
    As with all QRhiResource subclasses, the two-phased initialization pattern
6828
    applies: setting any values via the setters, for example setDepthTest(), is
6829
    only effective after calling create(). Avoid changing any values once the
6830
    QRhiGraphicsPipeline has been initialized via create(). To change some
6831
    state, set the new value and call create() again. However, that will
6832
    effectively release all underlying native resources and create new ones. As
6833
    a result, it may be a heavy, expensive operation. Rather, prefer creating
6834
    multiple pipelines with the different states, and
6835
    \l{QRhiCommandBuffer::setGraphicsPipeline()}{switch between them} when
6836
    recording the render pass.
6837
6838
    \note Setting the shader stages is mandatory. There must be at least one
6839
    stage, and there must be a vertex stage.
6840
6841
    \note Setting the shader resource bindings is mandatory. The referenced
6842
    QRhiShaderResourceBindings must already have create() called on it by the
6843
    time create() is called. Associating with a QRhiShaderResourceBindings that
6844
    has no bindings is also valid, as long as no shader in any stage expects any
6845
    resources. Using a QRhiShaderResourceBindings object that does not specify
6846
    any actual resources (i.e., the buffers, textures, etc. for the binding
6847
    points are set to \nullptr) is valid as well, as long as a
6848
    \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
6849
    QRhiShaderResourceBindings, that specifies resources for all the bindings,
6850
    is going to be set via
6851
    \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} when
6852
    recording the render pass.
6853
6854
    \note Setting the render pass descriptor is mandatory. To obtain a
6855
    QRhiRenderPassDescriptor that can be passed to setRenderPassDescriptor(),
6856
    use either QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() or
6857
    QRhiSwapChain::newCompatibleRenderPassDescriptor().
6858
6859
    \note Setting the vertex input layout is mandatory.
6860
6861
    \note sampleCount() defaults to 1 and must match the sample count of the
6862
    render target's color and depth stencil attachments.
6863
6864
    \note The depth test, depth write, and stencil test are disabled by
6865
    default. The face culling mode defaults to no culling.
6866
6867
    \note stencilReadMask() and stencilWriteMask() apply to both faces. They
6868
    both default to 0xFF.
6869
6870
    \section2 Example usage
6871
6872
    All settings of a graphics pipeline have defaults which might be suitable
6873
    to many applications. Therefore a minimal example of creating a graphics
6874
    pipeline could be the following. This assumes that the vertex shader takes
6875
    a single \c{vec3 position} input at the input location 0. With the
6876
    QRhiShaderResourceBindings and QRhiRenderPassDescriptor objects, plus the
6877
    QShader collections for the vertex and fragment stages, a pipeline could be
6878
    created like this:
6879
6880
    \code
6881
        QRhiShaderResourceBindings *srb;
6882
        QRhiRenderPassDescriptor *rpDesc;
6883
        QShader vs, fs;
6884
        // ...
6885
6886
        QRhiVertexInputLayout inputLayout;
6887
        inputLayout.setBindings({ { 3 * sizeof(float) } });
6888
        inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float3, 0 } });
6889
6890
        QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
6891
        ps->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
6892
        ps->setVertexInputLayout(inputLayout);
6893
        ps->setShaderResourceBindings(srb);
6894
        ps->setRenderPassDescriptor(rpDesc);
6895
        if (!ps->create()) { error(); }
6896
    \endcode
6897
6898
    The above code creates a pipeline object that uses the defaults for many
6899
    settings and states. For example, it will use a \l Triangles topology, no
6900
    backface culling, blending is disabled but color write is enabled for all
6901
    four channels, depth test/write are disabled, stencil operations are
6902
    disabled.
6903
6904
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
6905
    for details.
6906
6907
    \sa QRhiCommandBuffer, QRhi
6908
 */
6909
6910
/*!
6911
    \enum QRhiGraphicsPipeline::Flag
6912
6913
    Flag values for describing the dynamic state of the pipeline, and other
6914
    options. The viewport is always dynamic.
6915
6916
    \value UsesBlendConstants Indicates that a blend color constant will be set
6917
    via QRhiCommandBuffer::setBlendConstants()
6918
6919
    \value UsesStencilRef Indicates that a stencil reference value will be set
6920
    via QRhiCommandBuffer::setStencilRef()
6921
6922
    \value UsesScissor Indicates that a scissor rectangle will be set via
6923
    QRhiCommandBuffer::setScissor()
6924
6925
    \value CompileShadersWithDebugInfo Requests compiling shaders with debug
6926
    information enabled. This is relevant only when runtime shader compilation
6927
    from source code is involved, and only when the underlying infrastructure
6928
    supports this. With concrete examples, this is not relevant with Vulkan and
6929
    SPIR-V, because the GLSL-to-SPIR-V compilation does not happen at run
6930
    time. On the other hand, consider Direct3D and HLSL, where there are
6931
    multiple options: when the QShader packages ship with pre-compiled bytecode
6932
    (\c DXBC), debug information is to be requested through the tool that
6933
    generates the \c{.qsb} file, similarly to the case of Vulkan and
6934
    SPIR-V. However, when having HLSL source code in the pre- or
6935
    runtime-generated QShader packages, the first phase of compilation (HLSL
6936
    source to intermediate format) happens at run time too, with this flag taken
6937
    into account. Debug information is relevant in particular with tools like
6938
    RenderDoc since it allows seeing the original source code when investigating
6939
    the pipeline and when performing vertex or fragment shader debugging.
6940
6941
    \value UsesShadingRate Indicates that a per-draw (per-pipeline) shading rate
6942
    value will be set via QRhiCommandBuffer::setShadingRate(). Not specifying
6943
    this flag and still calling setShadingRate() may lead to varying, unexpected
6944
    results depending on the underlying graphics API.
6945
6946
    \value [since 6.12] UsesIndirectDraws Indicates that this pipeline will be used with
6947
    indirect draw calls (QRhiCommandBuffer::drawIndirect() or
6948
    QRhiCommandBuffer::drawIndexedIndirect()). Setting this flag allows the
6949
    Metal backend to use Indirect Command Buffers (ICB) for GPU-driven
6950
    rendering, which significantly reduces CPU overhead for large draw counts.
6951
    Not setting this flag when using indirect draws is still functional but may
6952
    result in less optimal performance on Metal. This flag has no effect on
6953
    other backends.
6954
 */
6955
6956
/*!
6957
    \enum QRhiGraphicsPipeline::Topology
6958
    Specifies the primitive topology
6959
6960
    \value Triangles (default)
6961
    \value TriangleStrip
6962
    \value TriangleFan (only available if QRhi::TriangleFanTopology is supported)
6963
    \value Lines
6964
    \value LineStrip
6965
    \value Points
6966
6967
    \value Patches (only available if QRhi::Tessellation is supported, and
6968
    requires the tessellation stages to be present in the pipeline)
6969
 */
6970
6971
/*!
6972
    \enum QRhiGraphicsPipeline::CullMode
6973
    Specifies the culling mode
6974
6975
    \value None No culling (default)
6976
    \value Front Cull front faces
6977
    \value Back Cull back faces
6978
 */
6979
6980
/*!
6981
    \enum QRhiGraphicsPipeline::FrontFace
6982
    Specifies the front face winding order
6983
6984
    \value CCW Counter clockwise (default)
6985
    \value CW Clockwise
6986
 */
6987
6988
/*!
6989
    \enum QRhiGraphicsPipeline::ColorMaskComponent
6990
    Flag values for specifying the color write mask
6991
6992
    \value R
6993
    \value G
6994
    \value B
6995
    \value A
6996
 */
6997
6998
/*!
6999
    \enum QRhiGraphicsPipeline::BlendFactor
7000
    Specifies the blend factor
7001
7002
    \value Zero
7003
    \value One
7004
    \value SrcColor
7005
    \value OneMinusSrcColor
7006
    \value DstColor
7007
    \value OneMinusDstColor
7008
    \value SrcAlpha
7009
    \value OneMinusSrcAlpha
7010
    \value DstAlpha
7011
    \value OneMinusDstAlpha
7012
    \value ConstantColor
7013
    \value OneMinusConstantColor
7014
    \value ConstantAlpha
7015
    \value OneMinusConstantAlpha
7016
    \value SrcAlphaSaturate
7017
    \value Src1Color
7018
    \value OneMinusSrc1Color
7019
    \value Src1Alpha
7020
    \value OneMinusSrc1Alpha
7021
 */
7022
7023
/*!
7024
    \enum QRhiGraphicsPipeline::BlendOp
7025
    Specifies the blend operation
7026
7027
    \value Add
7028
    \value Subtract
7029
    \value ReverseSubtract
7030
    \value Min
7031
    \value Max
7032
 */
7033
7034
/*!
7035
    \enum QRhiGraphicsPipeline::CompareOp
7036
    Specifies the depth or stencil comparison function
7037
7038
    \value Never
7039
    \value Less (default for depth)
7040
    \value Equal
7041
    \value LessOrEqual
7042
    \value Greater
7043
    \value NotEqual
7044
    \value GreaterOrEqual
7045
    \value Always (default for stencil)
7046
 */
7047
7048
/*!
7049
    \enum QRhiGraphicsPipeline::StencilOp
7050
    Specifies the stencil operation
7051
7052
    \value StencilZero
7053
    \value Keep (default)
7054
    \value Replace
7055
    \value IncrementAndClamp
7056
    \value DecrementAndClamp
7057
    \value Invert
7058
    \value IncrementAndWrap
7059
    \value DecrementAndWrap
7060
 */
7061
7062
/*!
7063
    \enum QRhiGraphicsPipeline::PolygonMode
7064
    \brief Specifies the polygon rasterization mode
7065
7066
    Polygon Mode (Triangle Fill Mode in Metal, Fill Mode in D3D) specifies
7067
    the fill mode used when rasterizing polygons.  Polygons may be drawn as
7068
    solids (Fill), or as a wire mesh (Line).
7069
7070
    Support for non-fill polygon modes is optional and is indicated by the
7071
    QRhi::NonFillPolygonMode feature. With OpenGL ES and some Vulkan
7072
    implementations the feature will likely be reported as unsupported, which
7073
    then means values other than Fill cannot be used.
7074
7075
    \value Fill The interior of the polygon is filled (default)
7076
    \value Line Boundary edges of the polygon are drawn as line segments.
7077
 */
7078
7079
/*!
7080
    \struct QRhiGraphicsPipeline::TargetBlend
7081
    \inmodule QtGuiPrivate
7082
    \inheaderfile rhi/qrhi.h
7083
    \since 6.6
7084
    \brief Describes the blend state for one color attachment.
7085
7086
    Defaults to color write enabled, blending disabled. The blend values are
7087
    set up for pre-multiplied alpha (One, OneMinusSrcAlpha, One,
7088
    OneMinusSrcAlpha) by default. This means that to get the alpha blending
7089
    mode Qt Quick uses, it is enough to set the \c enable flag to true while
7090
    leaving other values at their defaults.
7091
7092
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7093
    for details.
7094
 */
7095
7096
/*!
7097
    \variable QRhiGraphicsPipeline::TargetBlend::colorWrite
7098
 */
7099
7100
/*!
7101
    \variable QRhiGraphicsPipeline::TargetBlend::enable
7102
 */
7103
7104
/*!
7105
    \variable QRhiGraphicsPipeline::TargetBlend::srcColor
7106
 */
7107
7108
/*!
7109
    \variable QRhiGraphicsPipeline::TargetBlend::dstColor
7110
 */
7111
7112
/*!
7113
    \variable QRhiGraphicsPipeline::TargetBlend::opColor
7114
 */
7115
7116
/*!
7117
    \variable QRhiGraphicsPipeline::TargetBlend::srcAlpha
7118
 */
7119
7120
/*!
7121
    \variable QRhiGraphicsPipeline::TargetBlend::dstAlpha
7122
 */
7123
7124
/*!
7125
    \variable QRhiGraphicsPipeline::TargetBlend::opAlpha
7126
 */
7127
7128
/*!
7129
    \struct QRhiGraphicsPipeline::StencilOpState
7130
    \inmodule QtGuiPrivate
7131
    \inheaderfile rhi/qrhi.h
7132
    \since 6.6
7133
    \brief Describes the stencil operation state.
7134
7135
    The default-constructed StencilOpState has the following set:
7136
    \list
7137
    \li failOp - \l Keep
7138
    \li depthFailOp - \l Keep
7139
    \li passOp - \l Keep
7140
    \li compareOp \l Always
7141
    \endlist
7142
7143
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7144
    for details.
7145
 */
7146
7147
/*!
7148
    \variable QRhiGraphicsPipeline::StencilOpState::failOp
7149
 */
7150
7151
/*!
7152
    \variable QRhiGraphicsPipeline::StencilOpState::depthFailOp
7153
 */
7154
7155
/*!
7156
    \variable QRhiGraphicsPipeline::StencilOpState::passOp
7157
 */
7158
7159
/*!
7160
    \variable QRhiGraphicsPipeline::StencilOpState::compareOp
7161
 */
7162
7163
/*!
7164
    \internal
7165
 */
7166
QRhiGraphicsPipeline::QRhiGraphicsPipeline(QRhiImplementation *rhi)
7167
0
    : QRhiResource(rhi)
7168
0
{
7169
0
}
7170
7171
/*!
7172
    \return the resource type.
7173
 */
7174
QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
7175
0
{
7176
0
    return GraphicsPipeline;
7177
0
}
7178
7179
/*!
7180
    \fn virtual bool QRhiGraphicsPipeline::create() = 0
7181
7182
    Creates the corresponding native graphics resources. If there are already
7183
    resources present due to an earlier create() with no corresponding
7184
    destroy(), then destroy() is called implicitly first.
7185
7186
    \return \c true when successful, \c false when a graphics operation failed.
7187
    Regardless of the return value, calling destroy() is always safe.
7188
7189
    \note This may be, depending on the underlying graphics API, an expensive
7190
    operation, especially when shaders get compiled/optimized from source or
7191
    from an intermediate bytecode format to the GPU's own instruction set.
7192
    Where applicable, the QRhi backend automatically sets up the relevant
7193
    non-persistent facilities to accelerate this, for example the Vulkan
7194
    backend automatically creates a \c VkPipelineCache to improve data reuse
7195
    during the lifetime of the application.
7196
7197
    \note Drivers may also employ various persistent (disk-based) caching
7198
    strategies for shader and pipeline data, which is hidden to and is outside
7199
    of Qt's control. In some cases, depending on the graphics API and the QRhi
7200
    backend, there are facilities within QRhi for manually managing such a
7201
    cache, allowing the retrieval of a serializable blob that can then be
7202
    reloaded in the future runs of the application to ensure faster pipeline
7203
    creation times. See QRhi::pipelineCacheData() and
7204
    QRhi::setPipelineCacheData() for details. Note also that when working with
7205
    a QRhi instance managed by a higher level Qt framework, such as Qt Quick,
7206
    it is possible that such disk-based caching is taken care of automatically,
7207
    for example QQuickWindow uses a disk-based pipeline cache by default (which
7208
    comes in addition to any driver-level caching).
7209
 */
7210
7211
/*!
7212
    \fn QRhiGraphicsPipeline::Flags QRhiGraphicsPipeline::flags() const
7213
    \return the currently set flags.
7214
 */
7215
7216
/*!
7217
    \fn void QRhiGraphicsPipeline::setFlags(Flags f)
7218
    Sets the flags \a f.
7219
 */
7220
7221
/*!
7222
    \fn QRhiGraphicsPipeline::Topology QRhiGraphicsPipeline::topology() const
7223
    \return the currently set primitive topology.
7224
 */
7225
7226
/*!
7227
    \fn void QRhiGraphicsPipeline::setTopology(Topology t)
7228
    Sets the primitive topology \a t.
7229
 */
7230
7231
/*!
7232
    \fn QRhiGraphicsPipeline::CullMode QRhiGraphicsPipeline::cullMode() const
7233
    \return the currently set face culling mode.
7234
 */
7235
7236
/*!
7237
    \fn void QRhiGraphicsPipeline::setCullMode(CullMode mode)
7238
    Sets the specified face culling \a mode.
7239
 */
7240
7241
/*!
7242
    \fn QRhiGraphicsPipeline::FrontFace QRhiGraphicsPipeline::frontFace() const
7243
    \return the currently set front face mode.
7244
 */
7245
7246
/*!
7247
    \fn void QRhiGraphicsPipeline::setFrontFace(FrontFace f)
7248
    Sets the front face mode \a f.
7249
 */
7250
7251
/*!
7252
    \fn void QRhiGraphicsPipeline::setTargetBlends(std::initializer_list<TargetBlend> list)
7253
7254
    Sets the \a list of render target blend settings. This is a list because
7255
    when multiple render targets are used (i.e., a QRhiTextureRenderTarget with
7256
    more than one QRhiColorAttachment), there needs to be a TargetBlend
7257
    structure per render target (color attachment).
7258
7259
    By default there is one default-constructed TargetBlend set.
7260
7261
    \sa QRhi::MaxColorAttachments
7262
 */
7263
7264
/*!
7265
    \fn template<typename InputIterator> void QRhiGraphicsPipeline::setTargetBlends(InputIterator first, InputIterator last)
7266
    Sets the list of render target blend settings from the iterators \a first and \a last.
7267
 */
7268
7269
/*!
7270
    \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cbeginTargetBlends() const
7271
    \return a const iterator pointing to the first item in the render target blend setting list.
7272
 */
7273
7274
/*!
7275
    \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cendTargetBlends() const
7276
    \return a const iterator pointing just after the last item in the render target blend setting list.
7277
 */
7278
7279
/*!
7280
    \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::targetBlendAt(qsizetype index) const
7281
    \return the render target blend setting at the specified \a index.
7282
 */
7283
7284
/*!
7285
    \fn qsizetype QRhiGraphicsPipeline::targetBlendCount() const
7286
    \return the number of render target blend settings.
7287
 */
7288
7289
/*!
7290
    \fn bool QRhiGraphicsPipeline::hasDepthTest() const
7291
    \return true if depth testing is enabled.
7292
 */
7293
7294
/*!
7295
    \fn void QRhiGraphicsPipeline::setDepthTest(bool enable)
7296
7297
    Enables or disables depth testing based on \a enable. Both depth test and
7298
    the writing out of depth data are disabled by default.
7299
7300
    \sa setDepthWrite()
7301
 */
7302
7303
/*!
7304
    \fn bool QRhiGraphicsPipeline::hasDepthWrite() const
7305
    \return true if depth write is enabled.
7306
 */
7307
7308
/*!
7309
    \fn void QRhiGraphicsPipeline::setDepthWrite(bool enable)
7310
7311
    Controls the writing out of depth data into the depth buffer based on
7312
    \a enable. By default this is disabled. Depth write is typically enabled
7313
    together with the depth test.
7314
7315
    \note Enabling depth write without having depth testing enabled may not
7316
    lead to the desired result, and should be avoided.
7317
7318
    \sa setDepthTest()
7319
 */
7320
7321
/*!
7322
    \fn bool QRhiGraphicsPipeline::hasDepthClamp() const
7323
    \return true if depth clamp is enabled.
7324
7325
    \since 6.11
7326
 */
7327
7328
/*!
7329
    \fn void QRhiGraphicsPipeline::setDepthClamp(bool enable)
7330
7331
    Enables depth clamping when \a enable is true. When depth clamping is
7332
    enabled, primitives that would otherwise be clipped by the near or far
7333
    clip plane are rasterized and their depth values are clamped to the
7334
    depth range. When disabled (the default), such primitives are clipped.
7335
7336
    \note This setting is ignored when the QRhi::DepthClamp feature is
7337
    reported as unsupported.
7338
7339
    \since 6.11
7340
 */
7341
7342
/*!
7343
    \fn QRhiGraphicsPipeline::CompareOp QRhiGraphicsPipeline::depthOp() const
7344
    \return the depth comparison function.
7345
 */
7346
7347
/*!
7348
    \fn void QRhiGraphicsPipeline::setDepthOp(CompareOp op)
7349
    Sets the depth comparison function \a op.
7350
 */
7351
7352
/*!
7353
    \fn bool QRhiGraphicsPipeline::hasStencilTest() const
7354
    \return true if stencil testing is enabled.
7355
 */
7356
7357
/*!
7358
    \fn void QRhiGraphicsPipeline::setStencilTest(bool enable)
7359
    Enables or disables stencil tests based on \a enable.
7360
    By default this is disabled.
7361
 */
7362
7363
/*!
7364
    \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilFront() const
7365
    \return the current stencil test state for front faces.
7366
 */
7367
7368
/*!
7369
    \fn void QRhiGraphicsPipeline::setStencilFront(const StencilOpState &state)
7370
    Sets the stencil test \a state for front faces.
7371
 */
7372
7373
/*!
7374
    \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilBack() const
7375
    \return the current stencil test state for back faces.
7376
 */
7377
7378
/*!
7379
    \fn void QRhiGraphicsPipeline::setStencilBack(const StencilOpState &state)
7380
    Sets the stencil test \a state for back faces.
7381
 */
7382
7383
/*!
7384
    \fn quint32 QRhiGraphicsPipeline::stencilReadMask() const
7385
    \return the currrent stencil read mask.
7386
 */
7387
7388
/*!
7389
    \fn void QRhiGraphicsPipeline::setStencilReadMask(quint32 mask)
7390
    Sets the stencil read \a mask. The default value is 0xFF.
7391
 */
7392
7393
/*!
7394
    \fn quint32 QRhiGraphicsPipeline::stencilWriteMask() const
7395
    \return the current stencil write mask.
7396
 */
7397
7398
/*!
7399
    \fn void QRhiGraphicsPipeline::setStencilWriteMask(quint32 mask)
7400
    Sets the stencil write \a mask. The default value is 0xFF.
7401
 */
7402
7403
/*!
7404
    \fn int QRhiGraphicsPipeline::sampleCount() const
7405
    \return the currently set sample count. 1 means no multisample antialiasing.
7406
 */
7407
7408
/*!
7409
    \fn void QRhiGraphicsPipeline::setSampleCount(int s)
7410
7411
    Sets the sample count. Typical values for \a s are 1, 4, or 8. The pipeline
7412
    must always be compatible with the render target, i.e. the sample counts
7413
    must match.
7414
7415
    \sa QRhi::supportedSampleCounts()
7416
 */
7417
7418
/*!
7419
    \fn float QRhiGraphicsPipeline::lineWidth() const
7420
    \return the currently set line width. The default is 1.0f.
7421
 */
7422
7423
/*!
7424
    \fn void QRhiGraphicsPipeline::setLineWidth(float width)
7425
7426
    Sets the line \a width. If the QRhi::WideLines feature is reported as
7427
    unsupported at runtime, values other than 1.0f are ignored.
7428
 */
7429
7430
/*!
7431
    \fn int QRhiGraphicsPipeline::depthBias() const
7432
    \return the currently set depth bias.
7433
 */
7434
7435
/*!
7436
    \fn void QRhiGraphicsPipeline::setDepthBias(int bias)
7437
    Sets the depth \a bias. The default value is 0.
7438
 */
7439
7440
/*!
7441
    \fn float QRhiGraphicsPipeline::slopeScaledDepthBias() const
7442
    \return the currently set slope scaled depth bias.
7443
 */
7444
7445
/*!
7446
    \fn void QRhiGraphicsPipeline::setSlopeScaledDepthBias(float bias)
7447
    Sets the slope scaled depth \a bias. The default value is 0.
7448
 */
7449
7450
/*!
7451
    \fn void QRhiGraphicsPipeline::setShaderStages(std::initializer_list<QRhiShaderStage> list)
7452
    Sets the \a list of shader stages.
7453
 */
7454
7455
/*!
7456
    \fn template<typename InputIterator> void QRhiGraphicsPipeline::setShaderStages(InputIterator first, InputIterator last)
7457
    Sets the list of shader stages from the iterators \a first and \a last.
7458
 */
7459
7460
/*!
7461
    \fn const QRhiShaderStage *QRhiGraphicsPipeline::cbeginShaderStages() const
7462
    \return a const iterator pointing to the first item in the shader stage list.
7463
 */
7464
7465
/*!
7466
    \fn const QRhiShaderStage *QRhiGraphicsPipeline::cendShaderStages() const
7467
    \return a const iterator pointing just after the last item in the shader stage list.
7468
 */
7469
7470
/*!
7471
    \fn const QRhiShaderStage *QRhiGraphicsPipeline::shaderStageAt(qsizetype index) const
7472
    \return the shader stage at the specified \a index.
7473
 */
7474
7475
/*!
7476
    \fn qsizetype QRhiGraphicsPipeline::shaderStageCount() const
7477
    \return the number of shader stages in this pipeline.
7478
 */
7479
7480
/*!
7481
    \fn QRhiVertexInputLayout QRhiGraphicsPipeline::vertexInputLayout() const
7482
    \return the currently set vertex input layout specification.
7483
 */
7484
7485
/*!
7486
    \fn void QRhiGraphicsPipeline::setVertexInputLayout(const QRhiVertexInputLayout &layout)
7487
    Specifies the vertex input \a layout.
7488
 */
7489
7490
/*!
7491
    \fn QRhiShaderResourceBindings *QRhiGraphicsPipeline::shaderResourceBindings() const
7492
    \return the currently associated QRhiShaderResourceBindings object.
7493
 */
7494
7495
/*!
7496
    \fn void QRhiGraphicsPipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
7497
7498
    Associates with \a srb describing the resource binding layout and the
7499
    resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional,
7500
    because only the layout matters during pipeline creation. Therefore, the \a
7501
    srb passed in here can leave the actual buffer or texture objects
7502
    unspecified (\nullptr) as long as there is another,
7503
    \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
7504
    QRhiShaderResourceBindings bound via
7505
    \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
7506
    recording the draw calls.
7507
 */
7508
7509
/*!
7510
    \fn QRhiRenderPassDescriptor *QRhiGraphicsPipeline::renderPassDescriptor() const
7511
    \return the currently set QRhiRenderPassDescriptor.
7512
 */
7513
7514
/*!
7515
    \fn void QRhiGraphicsPipeline::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
7516
    Associates with the specified QRhiRenderPassDescriptor \a desc.
7517
 */
7518
7519
/*!
7520
    \fn int QRhiGraphicsPipeline::patchControlPointCount() const
7521
    \return the currently set patch control point count.
7522
 */
7523
7524
/*!
7525
    \fn void QRhiGraphicsPipeline::setPatchControlPointCount(int count)
7526
7527
    Sets the number of patch control points to \a count. The default value is
7528
    3. This is used only when the topology is set to \l Patches.
7529
 */
7530
7531
/*!
7532
    \fn QRhiGraphicsPipeline::PolygonMode QRhiGraphicsPipeline::polygonMode() const
7533
    \return the polygon mode.
7534
 */
7535
7536
/*!
7537
    \fn void QRhiGraphicsPipeline::setPolygonMode(PolygonMode mode)
7538
    Sets the polygon \a mode. The default is Fill.
7539
7540
    \sa QRhi::NonFillPolygonMode
7541
 */
7542
7543
/*!
7544
    \fn int QRhiGraphicsPipeline::multiViewCount() const
7545
    \return the view count. The default is 0, indicating no multiview rendering.
7546
    \since 6.7
7547
 */
7548
7549
/*!
7550
    \fn void QRhiGraphicsPipeline::setMultiViewCount(int count)
7551
    Sets the view \a count for multiview rendering. The default is 0,
7552
    indicating no multiview rendering.
7553
    \a count must be 2 or larger to trigger multiview rendering.
7554
7555
    Multiview is only available when the \l{QRhi::MultiView}{MultiView feature}
7556
    is reported as supported. The render target must be a 2D texture array, and
7557
    the color attachment for the render target must have the same \a count set.
7558
7559
    See QRhiColorAttachment::setMultiViewCount() for further details on
7560
    multiview rendering.
7561
7562
    \since 6.7
7563
    \sa QRhi::MultiView, QRhiColorAttachment::setMultiViewCount()
7564
 */
7565
7566
/*!
7567
    \class QRhiSwapChain
7568
    \inmodule QtGuiPrivate
7569
    \inheaderfile rhi/qrhi.h
7570
    \since 6.6
7571
    \brief Swapchain resource.
7572
7573
    A swapchain enables presenting rendering results to a surface. A swapchain
7574
    is typically backed by a set of color buffers. Of these, one is displayed
7575
    at a time.
7576
7577
    Below is a typical pattern for creating and managing a swapchain and some
7578
    associated resources in order to render onto a QWindow:
7579
7580
    \code
7581
      void init()
7582
      {
7583
          sc = rhi->newSwapChain();
7584
          ds = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
7585
                                    QSize(), // no need to set the size here due to UsedWithSwapChainOnly
7586
                                    1,
7587
                                    QRhiRenderBuffer::UsedWithSwapChainOnly);
7588
          sc->setWindow(window);
7589
          sc->setDepthStencil(ds);
7590
          rp = sc->newCompatibleRenderPassDescriptor();
7591
          sc->setRenderPassDescriptor(rp);
7592
          resizeSwapChain();
7593
      }
7594
7595
      void resizeSwapChain()
7596
      {
7597
          hasSwapChain = sc->createOrResize();
7598
      }
7599
7600
      void render()
7601
      {
7602
          if (!hasSwapChain || notExposed)
7603
              return;
7604
7605
          if (sc->currentPixelSize() != sc->surfacePixelSize() || newlyExposed) {
7606
              resizeSwapChain();
7607
              if (!hasSwapChain)
7608
                  return;
7609
              newlyExposed = false;
7610
          }
7611
7612
          rhi->beginFrame(sc);
7613
          // ...
7614
          rhi->endFrame(sc);
7615
      }
7616
    \endcode
7617
7618
    Avoid relying on QWindow resize events to resize swapchains, especially
7619
    considering that surface sizes may not always fully match the QWindow
7620
    reported dimensions. The safe, cross-platform approach is to do the check
7621
    via surfacePixelSize() whenever starting a new frame.
7622
7623
    Releasing the swapchain must happen while the QWindow and the underlying
7624
    native window is fully up and running. Building on the previous example:
7625
7626
    \code
7627
        void releaseSwapChain()
7628
        {
7629
            if (hasSwapChain) {
7630
                sc->destroy();
7631
                hasSwapChain = false;
7632
            }
7633
        }
7634
7635
        // assuming Window is our QWindow subclass
7636
        bool Window::event(QEvent *e)
7637
        {
7638
            switch (e->type()) {
7639
            case QEvent::UpdateRequest: // for QWindow::requestUpdate()
7640
                render();
7641
                break;
7642
            case QEvent::PlatformSurface:
7643
                if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
7644
                    releaseSwapChain();
7645
                break;
7646
            default:
7647
                break;
7648
            }
7649
            return QWindow::event(e);
7650
        }
7651
    \endcode
7652
7653
    Initializing the swapchain and starting to render the first frame cannot
7654
    start at any time. The safe, cross-platform approach is to rely on expose
7655
    events. QExposeEvent is a loosely specified event that is sent whenever a
7656
    window gets mapped, obscured, and resized, depending on the platform.
7657
7658
    \code
7659
        void Window::exposeEvent(QExposeEvent *)
7660
        {
7661
            // initialize and start rendering when the window becomes usable for graphics purposes
7662
            if (isExposed() && !running) {
7663
                running = true;
7664
                init();
7665
            }
7666
7667
            // stop pushing frames when not exposed or size becomes 0
7668
            if ((!isExposed() || (hasSwapChain && sc->surfacePixelSize().isEmpty())) && running)
7669
                notExposed = true;
7670
7671
            // continue when exposed again and the surface has a valid size
7672
            if (isExposed() && running && notExposed && !sc->surfacePixelSize().isEmpty()) {
7673
                notExposed = false;
7674
                newlyExposed = true;
7675
            }
7676
7677
            if (isExposed() && !sc->surfacePixelSize().isEmpty())
7678
                render();
7679
        }
7680
    \endcode
7681
7682
    Once the rendering has started, a simple way to request a new frame is
7683
    QWindow::requestUpdate(). While on some platforms this is merely a small
7684
    timer, on others it has a specific implementation: for instance on macOS or
7685
    iOS it may be backed by
7686
    \l{https://developer.apple.com/documentation/corevideo/cvdisplaylink?language=objc}{CVDisplayLink}.
7687
    The example above is already prepared for update requests by handling
7688
    QEvent::UpdateRequest.
7689
7690
    While acting as a QRhiRenderTarget, QRhiSwapChain also manages a
7691
    QRhiCommandBuffer. Calling QRhi::endFrame() submits the recorded commands
7692
    and also enqueues a \c present request. The default behavior is to do this
7693
    with a swap interval of 1, meaning synchronizing to the display's vertical
7694
    refresh is enabled. Thus the rendering thread calling beginFrame() and
7695
    endFrame() will get throttled to vsync. On some backends this can be
7696
    disabled by passing QRhiSwapChain:NoVSync in flags().
7697
7698
    Multisampling (MSAA) is handled transparently to the applications when
7699
    requested via setSampleCount(). Where applicable, QRhiSwapChain will take
7700
    care of creating additional color buffers and issuing a multisample resolve
7701
    command at the end of a frame. For OpenGL, it is necessary to request the
7702
    appropriate sample count also via QSurfaceFormat, by calling
7703
    QSurfaceFormat::setDefaultFormat() before initializing the QRhi.
7704
7705
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
7706
    for details.
7707
 */
7708
7709
/*!
7710
    \enum QRhiSwapChain::Flag
7711
    Flag values to describe swapchain properties
7712
7713
    \value SurfaceHasPreMulAlpha Indicates that the target surface has
7714
    transparency with premultiplied alpha. For example, this is what Qt Quick
7715
    uses when the alpha channel is enabled on the target QWindow, because the
7716
    scenegraph rendrerer always outputs fragments with alpha multiplied into
7717
    the red, green, and blue values. To ensure identical behavior across
7718
    platforms, always set QSurfaceFormat::alphaBufferSize() to a non-zero value
7719
    on the target QWindow whenever this flag is set on the swapchain.
7720
7721
    \value SurfaceHasNonPreMulAlpha Indicates the target surface has
7722
    transparency with non-premultiplied alpha. Be aware that this may not be
7723
    supported on some systems, if the system compositor always expects content
7724
    with premultiplied alpha. In that case the behavior with this flag set is
7725
    expected to be equivalent to SurfaceHasPreMulAlpha.
7726
7727
    \value sRGB Requests to pick an sRGB format for the swapchain's color
7728
    buffers and/or render target views, where applicable. Note that this
7729
    implies that sRGB framebuffer update and blending will get enabled for all
7730
    content targeting this swapchain, and opting out is not possible. For
7731
    OpenGL, set \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the
7732
    QSurfaceFormat of the QWindow in addition. Applicable only when the
7733
    swapchain format is set to QRhiSwapChain::SDR.
7734
7735
    \value UsedAsTransferSource Indicates the swapchain will be used as the
7736
    source of a readback in QRhiResourceUpdateBatch::readBackTexture().
7737
7738
    \value NoVSync Requests disabling waiting for vertical sync, also avoiding
7739
    throttling the rendering thread. The behavior is backend specific and
7740
    applicable only where it is possible to control this. Some may ignore the
7741
    request altogether. For OpenGL, try instead setting the swap interval to 0
7742
    on the QWindow via QSurfaceFormat::setSwapInterval().
7743
7744
    \value MinimalBufferCount Requests creating the swapchain with the minimum
7745
    number of buffers, which is in practice 2, unless the graphics
7746
    implementation has a higher minimum number than that. Only applicable with
7747
    backends where such control is available via the graphics API, for example,
7748
    Vulkan. By default it is up to the backend to decide what number of buffers
7749
    it requests (in practice this is almost always either 2 or 3), and it is
7750
    not the applications' concern. However, on Vulkan for instance the backend
7751
    will likely prefer the higher number (3), for example to avoid odd
7752
    performance issues with some Vulkan implementations on mobile devices. It
7753
    could be that on some platforms it can prove to be beneficial to force the
7754
    lower buffer count (2), so this flag allows forcing that. Note that all
7755
    this has no effect on the number of frames kept in flight, so the CPU
7756
    (QRhi) will still prepare frames at most \c{N - 1} frames ahead of the GPU,
7757
    even when the swapchain image buffer count larger than \c N. (\c{N} =
7758
    QRhi::FramesInFlight and typically 2).
7759
 */
7760
7761
/*!
7762
    \enum QRhiSwapChain::Format
7763
    Describes the swapchain format. The default format is SDR.
7764
7765
    This enum is used with
7766
    \l{QRhiSwapChain::isFormatSupported()}{isFormatSupported()} to check
7767
    upfront if creating the swapchain with the given format is supported by the
7768
    platform and the window's associated screen, and with
7769
    \l{QRhiSwapChain::setFormat()}{setFormat()}
7770
    to set the requested format in the swapchain before calling
7771
    \l{QRhiSwapChain::createOrResize()}{createOrResize()} for the first time.
7772
7773
    \value SDR 8-bit RGBA or BGRA, depending on the backend and platform. With
7774
    OpenGL ES in particular, it could happen that the platform provides less
7775
    than 8 bits (e.g. due to EGL and the QSurfaceFormat choosing a 565 or 444
7776
    format - this is outside the control of QRhi). Standard dynamic range. May
7777
    be combined with setting the QRhiSwapChain::sRGB flag.
7778
7779
    \value HDRExtendedSrgbLinear 16-bit float RGBA, high dynamic range,
7780
    extended linear sRGB (scRGB) color space. This involves Rec. 709 primaries
7781
    (same as SDR/sRGB) and linear colors. Conversion to the display's native
7782
    color space (such as, HDR10) is performed by the windowing system. On
7783
    Windows this is the canonical color space of the system compositor, and is
7784
    the recommended format for HDR swapchains in general on desktop platforms.
7785
7786
    \value HDR10 10-bit unsigned int RGB or BGR with 2 bit alpha, high dynamic
7787
    range, HDR10 (Rec. 2020) color space with an ST2084 PQ transfer function.
7788
7789
    \value HDRExtendedDisplayP3Linear 16-bit float RGBA, high dynamic range,
7790
    extended linear Display P3 color space. The primary choice for HDR on
7791
    platforms such as iOS and VisionOS.
7792
 */
7793
7794
/*!
7795
    \internal
7796
 */
7797
QRhiSwapChain::QRhiSwapChain(QRhiImplementation *rhi)
7798
0
    : QRhiResource(rhi)
7799
0
{
7800
0
}
7801
7802
/*!
7803
    \return the resource type.
7804
 */
7805
QRhiResource::Type QRhiSwapChain::resourceType() const
7806
0
{
7807
0
    return SwapChain;
7808
0
}
7809
7810
/*!
7811
    \fn QSize QRhiSwapChain::currentPixelSize() const
7812
7813
    \return the size with which the swapchain was last successfully built. Use
7814
    this to decide if createOrResize() needs to be called again: if
7815
    \c{currentPixelSize() != surfacePixelSize()} then the swapchain needs to be
7816
    resized.
7817
7818
    \note Typical rendering logic will call this function to get the output
7819
    size when starting to prepare a new frame, and base dependent calculations
7820
    (such as, the viewport) on the size returned from this function.
7821
7822
    While in many cases the value is the same as \c{QWindow::size() *
7823
    QWindow::devicePixelRatio()}, relying on the QWindow-reported size is not
7824
    guaranteed to be correct on all platforms and graphics API implementations.
7825
    Using this function is therefore strongly recommended whenever there is a
7826
    need to identify the dimensions, in pixels, of the output layer or surface.
7827
7828
    This also has the added benefit of avoiding potential data races when QRhi
7829
    is used on a dedicated rendering thread, because the need to call QWindow
7830
    functions, that may then access data updated on the main thread, is
7831
    avoided.
7832
7833
    \sa surfacePixelSize()
7834
  */
7835
7836
/*!
7837
    \fn virtual QSize QRhiSwapChain::surfacePixelSize() = 0
7838
7839
    \return The size of the window's associated surface or layer.
7840
7841
    \warning Do not assume this is the same as \c{QWindow::size() *
7842
    QWindow::devicePixelRatio()}. With some graphics APIs and windowing system
7843
    interfaces (for example, Vulkan) there is a theoretical possibility for a
7844
    surface to assume a size different from the associated window. To support
7845
    these cases, \b{rendering logic must always base size-derived calculations
7846
    (such as, viewports) on the size reported from QRhiSwapChain, and never on
7847
    the size queried from QWindow}.
7848
7849
    \note \b{Can also be called before createOrResize(), if at least window() is
7850
    already set. This in combination with currentPixelSize() allows to detect
7851
    when a swapchain needs to be resized.} However, watch out for the fact that
7852
    the size of the underlying native object (surface, layer, or similar) is
7853
    "live", so whenever this function is called, it returns the latest value
7854
    reported by the underlying implementation, without any atomicity guarantee.
7855
    Therefore, using this function to determine pixel sizes for graphics
7856
    resources that are used in a frame is strongly discouraged. Rely on
7857
    currentPixelSize() instead which returns a size that is atomic and will not
7858
    change between createOrResize() invocations.
7859
7860
    \note For depth-stencil buffers used in combination with the swapchain's
7861
    color buffers, it is strongly recommended to rely on the automatic sizing
7862
    and rebuilding behavior provided by the
7863
    QRhiRenderBuffer:UsedWithSwapChainOnly flag. Avoid querying the surface
7864
    size via this function just to get a size that can be passed to
7865
    QRhiRenderBuffer::setPixelSize() as that would suffer from the lack of
7866
    atomicity as described above.
7867
7868
    \sa currentPixelSize()
7869
  */
7870
7871
/*!
7872
    \fn virtual bool QRhiSwapChain::isFormatSupported(Format f) = 0
7873
7874
    \return true if the given swapchain format \a f is supported. SDR is always
7875
    supported.
7876
7877
    \note Can be called independently of createOrResize(), but window() must
7878
    already be set. Calling without the window set may lead to unexpected
7879
    results depending on the backend and platform (most likely false for any
7880
    HDR format), because HDR format support is usually tied to the output
7881
    (screen) to which the swapchain's associated window belongs at any given
7882
    time. If the result is true for a HDR format, then creating the swapchain
7883
    with that format is expected to succeed as long as the window is not moved
7884
    to another screen in the meantime.
7885
7886
    The main use of this function is to call it before the first
7887
    createOrResize() after the window is already set. This allow the QRhi
7888
    backends to perform platform or windowing system specific queries to
7889
    determine if the window (and the screen it is on) is capable of true HDR
7890
    output with the specified format.
7891
7892
    When the format is reported as supported, call setFormat() to set the
7893
    requested format and call createOrResize(). Be aware of the consequences
7894
    however: successfully requesting a HDR format will involve having to deal
7895
    with a different color space, possibly doing white level correction for
7896
    non-HDR-aware content, adjusting tonemapping methods, adjusting offscreen
7897
    render target settings, etc.
7898
7899
    \sa setFormat()
7900
 */
7901
7902
/*!
7903
    \fn virtual QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer() = 0
7904
7905
    \return a command buffer on which rendering commands and resource updates
7906
    can be recorded within a \l{QRhi::beginFrame()}{beginFrame} -
7907
    \l{QRhi::endFrame()}{endFrame} block, assuming beginFrame() was called with
7908
    this swapchain.
7909
7910
    \note The returned object is valid also after endFrame(), up until the next
7911
    beginFrame(), but the returned command buffer should not be used to record
7912
    any commands then. Rather, it can be used to query data collected during
7913
    the frame (or previous frames), for example by calling
7914
    \l{QRhiCommandBuffer::lastCompletedGpuTime()}{lastCompletedGpuTime()}.
7915
7916
    \note The value must not be cached and reused between frames. The caller
7917
    should not hold on to the returned object once
7918
    \l{QRhi::beginFrame()}{beginFrame()} is called again. Instead, the command
7919
    buffer object should be queried again by calling this function.
7920
*/
7921
7922
/*!
7923
    \fn virtual QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget() = 0
7924
7925
    \return a render target that can used with beginPass() in order to render
7926
    the swapchain's current backbuffer. Only valid within a
7927
    QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called
7928
    with this swapchain.
7929
7930
    \note the value must not be cached and reused between frames
7931
 */
7932
7933
/*!
7934
    \enum QRhiSwapChain::StereoTargetBuffer
7935
    Selects the backbuffer to use with a stereoscopic swapchain.
7936
7937
    \value LeftBuffer
7938
    \value RightBuffer
7939
 */
7940
7941
/*!
7942
    \return a render target that can be used with beginPass() in order to
7943
    render to the swapchain's left or right backbuffer. This overload should be
7944
    used only with stereoscopic rendering, that is, when the associated QWindow
7945
    is backed by two color buffers, one for each eye, instead of just one.
7946
7947
    When stereoscopic rendering is not supported, the return value will be
7948
    the default target. It is supported by all hardware backends except for Metal, in
7949
    combination with \l QSurfaceFormat::StereoBuffers, assuming it is supported
7950
    by the graphics and display driver stack at run time. Metal and Null backends
7951
    are going to return the default render target from this overload.
7952
7953
    \note the value must not be cached and reused between frames
7954
 */
7955
QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
7956
0
{
7957
0
    Q_UNUSED(targetBuffer);
7958
0
    return currentFrameRenderTarget();
7959
0
}
7960
7961
/*!
7962
    \fn virtual bool QRhiSwapChain::createOrResize() = 0
7963
7964
    Creates the swapchain if not already done and resizes the swapchain buffers
7965
    to match the current size of the targeted surface. Call this whenever the
7966
    size of the target surface is different than before.
7967
7968
    \note call destroy() only when the swapchain needs to be released
7969
    completely, typically upon
7970
    QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed. To perform resizing, just
7971
    call createOrResize().
7972
7973
    \return \c true when successful, \c false when a graphics operation failed.
7974
    Regardless of the return value, calling destroy() is always safe.
7975
 */
7976
7977
/*!
7978
    \fn QWindow *QRhiSwapChain::window() const
7979
    \return the currently set window.
7980
 */
7981
7982
/*!
7983
    \fn void QRhiSwapChain::setWindow(QWindow *window)
7984
    Sets the \a window.
7985
 */
7986
7987
/*!
7988
    \fn QRhiSwapChainProxyData QRhiSwapChain::proxyData() const
7989
    \return the currently set proxy data.
7990
 */
7991
7992
/*!
7993
    \fn void QRhiSwapChain::setProxyData(const QRhiSwapChainProxyData &d)
7994
    Sets the proxy data \a d.
7995
7996
    \sa QRhi::updateSwapChainProxyData()
7997
 */
7998
7999
/*!
8000
    \fn QRhiSwapChain::Flags QRhiSwapChain::flags() const
8001
    \return the currently set flags.
8002
 */
8003
8004
/*!
8005
    \fn void QRhiSwapChain::setFlags(Flags f)
8006
    Sets the flags \a f.
8007
 */
8008
8009
/*!
8010
    \fn QRhiSwapChain::Format QRhiSwapChain::format() const
8011
    \return the currently set format.
8012
 */
8013
8014
/*!
8015
    \fn void QRhiSwapChain::setFormat(Format f)
8016
    Sets the format \a f.
8017
8018
    Avoid setting formats that are reported as unsupported from
8019
    isFormatSupported(). Note that support for a given format may depend on the
8020
    screen the swapchain's associated window is opened on. On some platforms,
8021
    such as Windows and macOS, for HDR output to work it is necessary to have
8022
    HDR output enabled in the display settings.
8023
8024
    See isFormatSupported(), \l QRhiSwapChainHdrInfo, and \l Format for more
8025
    information on high dynamic range output.
8026
 */
8027
8028
/*!
8029
    \fn QRhiRenderBuffer *QRhiSwapChain::depthStencil() const
8030
    \return the currently associated renderbuffer for depth-stencil.
8031
 */
8032
8033
/*!
8034
    \fn void QRhiSwapChain::setDepthStencil(QRhiRenderBuffer *ds)
8035
    Sets the renderbuffer \a ds for use as a depth-stencil buffer.
8036
 */
8037
8038
/*!
8039
    \fn int QRhiSwapChain::sampleCount() const
8040
    \return the currently set sample count. 1 means no multisample antialiasing.
8041
 */
8042
8043
/*!
8044
    \fn void QRhiSwapChain::setSampleCount(int samples)
8045
8046
    Sets the sample count. Common values for \a samples are 1 (no MSAA), 4 (4x
8047
    MSAA), or 8 (8x MSAA).
8048
8049
    \sa QRhi::supportedSampleCounts()
8050
 */
8051
8052
/*!
8053
    \fn QRhiRenderPassDescriptor *QRhiSwapChain::renderPassDescriptor() const
8054
    \return the currently associated QRhiRenderPassDescriptor object.
8055
 */
8056
8057
/*!
8058
    \fn void QRhiSwapChain::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
8059
    Associates with the QRhiRenderPassDescriptor \a desc.
8060
 */
8061
8062
/*!
8063
    \fn virtual QRhiRenderPassDescriptor *QRhiSwapChain::newCompatibleRenderPassDescriptor() = 0;
8064
8065
    \return a new QRhiRenderPassDescriptor that is compatible with this swapchain.
8066
8067
    The returned value is used in two ways: it can be passed to
8068
    setRenderPassDescriptor() and
8069
    QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
8070
    describes the attachments (color, depth/stencil) and the load/store
8071
    behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
8072
    be used in combination with a swapchain that has a
8073
    \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
8074
    QRhiRenderPassDescriptor set.
8075
8076
    \sa createOrResize()
8077
 */
8078
8079
/*!
8080
    \fn QRhiShadingRateMap *QRhiSwapChain::shadingRateMap() const
8081
    \return the currently set QRhiShadingRateMap. By default this is \nullptr.
8082
    \since 6.9
8083
 */
8084
8085
/*!
8086
    \fn void QRhiSwapChain::setShadingRateMap(QRhiShadingRateMap *map)
8087
8088
    Associates with the specified QRhiShadingRateMap \a map. This is functional
8089
    only when the \l QRhi::VariableRateShadingMap feature is reported as
8090
    supported.
8091
8092
    When QRhiCommandBuffer::setShadingRate() is also called, the higher of the
8093
    two shading rates is used for each tile. There is currently no control
8094
    offered over the combiner behavior.
8095
8096
    \note Setting a shading rate map implies that a different, new
8097
    QRhiRenderPassDescriptor is needed and some of the native swapchain objects
8098
    must be rebuilt. Therefore, if the swapchain is already set up, call
8099
    newCompatibleRenderPassDescriptor() and setRenderPassDescriptor() right
8100
    after setShadingRateMap(). Then, createOrResize() must also be called again.
8101
    This has rolling consequences, for example for graphics pipelines: those
8102
    also need to be associated with the new QRhiRenderPassDescriptor and then
8103
    rebuilt. See \l QRhiRenderPassDescriptor::serializedFormat() for some
8104
    suggestions on how to deal with this. Remember to set the
8105
    QRhiGraphicsPipeline::UsesShadingRate flag for them as well.
8106
8107
    \since 6.9
8108
 */
8109
8110
/*!
8111
    \struct QRhiSwapChainHdrInfo
8112
    \inmodule QtGuiPrivate
8113
    \inheaderfile rhi/qrhi.h
8114
    \since 6.6
8115
8116
    \brief Describes the high dynamic range related information of the
8117
    swapchain's associated output.
8118
8119
    To perform HDR-compatible tonemapping, where the target range is not [0,1],
8120
    one often needs to know the maximum luminance of the display the
8121
    swapchain's window is associated with. While this is often made
8122
    user-configurable (think brightness, gamma and similar settings in games),
8123
    it can be highly useful to set defaults based on the values reported by the
8124
    display itself, thus providing a decent starting point.
8125
8126
    There are some problems however: the information is exposed in different
8127
    forms on different platforms, whereas with cross-platform graphics APIs
8128
    there is often no associated solution at all, because managing such
8129
    information is not in the scope of the API (and may rather be retrievable
8130
    via other platform-specific means, if any).
8131
8132
    With Metal on macOS/iOS, there is no luminance values exposed in the
8133
    platform APIs. Instead, the maximum color component value, that would be
8134
    1.0 in a non-HDR setup, is provided. The \c limitsType field indicates what
8135
    kind of information is available. It is then up to the clients of QRhi to
8136
    access the correct data from the \c limits union and use it as they see
8137
    fit.
8138
8139
    With an API like Vulkan, where there is no way to get such information, the
8140
    values are always the built-in defaults.
8141
8142
    Therefore, the struct returned from QRhiSwapChain::hdrInfo() contains
8143
    either some hard-coded defaults or real values received from an API such as
8144
    DXGI (IDXGIOutput6) or Cocoa (NSScreen). When no platform queries are
8145
    available (or needs using platform facilities out of scope for QRhi), the
8146
    hard-coded defaults are a maximum luminance of 1000 nits and an SDR white
8147
    level of 200.
8148
8149
    The struct also exposes the presumed luminance behavior of the platform and
8150
    its compositor, to indicate what a color component value of 1.0 is treated
8151
    as in a HDR color buffer. In some cases it will be necessary to perform
8152
    color correction of non-HDR content composited with HDR content. To enable
8153
    this, the SDR white level is queried from the system on some platforms
8154
    (Windows) and exposed here.
8155
8156
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8157
    for details.
8158
8159
    \sa QRhiSwapChain::hdrInfo()
8160
 */
8161
8162
/*!
8163
    \enum QRhiSwapChainHdrInfo::LimitsType
8164
8165
    \value LuminanceInNits Indicates that the \l limits union has its
8166
    \c luminanceInNits struct set
8167
8168
    \value ColorComponentValue Indicates that the \l limits union has its
8169
    \c colorComponentValue struct set
8170
*/
8171
8172
/*!
8173
    \enum QRhiSwapChainHdrInfo::LuminanceBehavior
8174
8175
    \value SceneReferred Indicates that the color value of 1.0 is interpreted
8176
    as 80 nits. This is the behavior of HDR-enabled windows with the Windows
8177
    compositor. See
8178
    \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range}{this
8179
    page} for more information on HDR on Windows.
8180
8181
    \value DisplayReferred Indicates that the color value of 1.0 is interpreted
8182
    as the value of the SDR white. (which can be e.g. 200 nits, but will vary
8183
    depending on screen brightness) This is the behavior of HDR-enabled windows
8184
    on Apple platforms. See
8185
    \l{https://developer.apple.com/documentation/metal/hdr_content/displaying_hdr_content_in_a_metal_layer}{this
8186
    page} for more information on Apple's EDR system.
8187
*/
8188
8189
/*!
8190
    \variable QRhiSwapChainHdrInfo::limitsType
8191
8192
    With Metal on macOS/iOS, there is no luminance values exposed in the
8193
    platform APIs. Instead, the maximum color component value, that would be
8194
    1.0 in a non-HDR setup, is provided. This value indicates what kind of
8195
    information is available in \l limits.
8196
8197
    \sa QRhiSwapChain::hdrInfo()
8198
*/
8199
8200
/*!
8201
    \variable QRhiSwapChainHdrInfo::limits
8202
8203
    Contains the actual values queried from the graphics API or the platform.
8204
    The type of data is indicated by \l limitsType. This is therefore a union.
8205
    There are currently two options:
8206
8207
    Luminance values in nits:
8208
8209
    \code
8210
        struct {
8211
            float minLuminance;
8212
            float maxLuminance;
8213
        } luminanceInNits;
8214
    \endcode
8215
8216
    On Windows the minimum and maximum luminance depends on the screen
8217
    brightness. While not relevant for desktops, on laptops the screen
8218
    brightness may change at any time. Increasing brightness implies decreased
8219
    maximum luminance. In addition, the results may also be dependent on the
8220
    HDR Content Brightness set in Windows Settings' System/Display/HDR view,
8221
    if there is such a setting.
8222
8223
    Note however that the changes made to the laptop screen's brightness or in
8224
    the system settings while the application is running are not necessarily
8225
    reflected in the returned values, meaning calling hdrInfo() again may still
8226
    return the same luminance range as before for the rest of the process'
8227
    lifetime. The exact behavior is up to DXGI and Qt has no control over it.
8228
8229
    \note The Windows compositor works in scene-referred mode for HDR content.
8230
    A color component value of 1.0 corresponds to a luminance of 80 nits. When
8231
    rendering non-HDR content (e.g. 2D UI elements), the correction of the
8232
    white level is often necessary. (e.g., outputting the fragment color (1, 1,
8233
    1) will likely lead to showing a shade of white that is too dim on-screen)
8234
    See \l sdrWhiteLevel.
8235
8236
    For macOS/iOS, the current maximum and potential maximum color
8237
    component values are provided:
8238
8239
    \code
8240
        struct {
8241
            float maxColorComponentValue;
8242
            float maxPotentialColorComponentValue;
8243
        } colorComponentValue;
8244
    \endcode
8245
8246
    The value may depend on the screen brightness, which on laptops means that
8247
    the result may change in the next call to hdrInfo() if the brightness was
8248
    changed in the meantime. The maximum screen brightness implies a maximum
8249
    color value of 1.0.
8250
8251
    \note Apple's EDR is display-referred. 1.0 corresponds to a luminance level
8252
    of SDR white (e.g. 200 nits), the value of which varies based on the screen
8253
    brightness and possibly other settings. The exact luminance value for that,
8254
    or the maximum luminance of the display, are not exposed to the
8255
    applications.
8256
8257
    \note It has been observed that the color component values are not set to
8258
    the correct larger-than-1 value right away on startup on some macOS
8259
    systems, but the values tend to change during or after the first frame.
8260
8261
    \sa QRhiSwapChain::hdrInfo()
8262
*/
8263
8264
/*!
8265
    \variable QRhiSwapChainHdrInfo::luminanceBehavior
8266
8267
    Describes the platform's presumed behavior with regards to color values.
8268
8269
    \sa sdrWhiteLevel
8270
 */
8271
8272
/*!
8273
    \variable QRhiSwapChainHdrInfo::sdrWhiteLevel
8274
8275
    On Windows this is the dynamic SDR white level in nits. The value is
8276
    dependent on the screen brightness (on laptops), and the SDR or HDR Content
8277
    Brightness settings in the Windows settings' System/Display/HDR view.
8278
8279
    To perform white level correction for non-HDR (SDR) content, such as 2D UI
8280
    elemenents, multiply the final color with sdrWhiteLevel / 80.0 whenever
8281
    \l luminanceBehavior is SceneReferred. (assuming Windows and a linear
8282
    extended sRGB (scRGB) color space)
8283
8284
    On other platforms the value is always a pre-defined value, 200. This may
8285
    not match the system's actual SDR white level, but the value of this
8286
    variable is not relevant in practice when the \l luminanceBehavior is
8287
    DisplayReferred, because then the color component value of 1.0 refers to
8288
    the SDR white by default.
8289
8290
    \sa luminanceBehavior
8291
*/
8292
8293
/*!
8294
    \return the HDR information for the associated display.
8295
8296
    Do not assume that this is a cheap operation. Depending on the platform,
8297
    this function makes various platform queries which may have a performance
8298
    impact.
8299
8300
    \note Can be called before createOrResize() as long as the window is
8301
    \l{setWindow()}{set}.
8302
8303
    \note What happens when moving a window with an initialized swapchain
8304
    between displays (HDR to HDR with different characteristics, HDR to SDR,
8305
    etc.) is not currently well-defined and depends heavily on the windowing
8306
    system and compositor, with potentially varying behavior between platforms.
8307
    Currently QRhi only guarantees that hdrInfo() returns valid data, if
8308
    available, for the display to which the swapchain's associated window
8309
    belonged at the time of createOrResize().
8310
8311
    \sa QRhiSwapChainHdrInfo
8312
 */
8313
QRhiSwapChainHdrInfo QRhiSwapChain::hdrInfo()
8314
0
{
8315
0
    QRhiSwapChainHdrInfo info;
8316
0
    info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
8317
0
    info.limits.luminanceInNits.minLuminance = 0.0f;
8318
0
    info.limits.luminanceInNits.maxLuminance = 1000.0f;
8319
0
    info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
8320
0
    info.sdrWhiteLevel = 200.0f;
8321
0
    return info;
8322
0
}
8323
8324
#ifndef QT_NO_DEBUG_STREAM
8325
QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
8326
0
{
8327
0
    QDebugStateSaver saver(dbg);
8328
0
    dbg.nospace() << "QRhiSwapChainHdrInfo(";
8329
0
    switch (info.limitsType) {
8330
0
    case QRhiSwapChainHdrInfo::LuminanceInNits:
8331
0
        dbg.nospace() << " minLuminance=" << info.limits.luminanceInNits.minLuminance
8332
0
                      << " maxLuminance=" << info.limits.luminanceInNits.maxLuminance;
8333
0
        break;
8334
0
    case QRhiSwapChainHdrInfo::ColorComponentValue:
8335
0
        dbg.nospace() << " maxColorComponentValue=" << info.limits.colorComponentValue.maxColorComponentValue;
8336
0
        dbg.nospace() << " maxPotentialColorComponentValue=" << info.limits.colorComponentValue.maxPotentialColorComponentValue;
8337
0
        break;
8338
0
    }
8339
0
    switch (info.luminanceBehavior) {
8340
0
    case QRhiSwapChainHdrInfo::SceneReferred:
8341
0
        dbg.nospace() << " scene-referred, SDR white level=" << info.sdrWhiteLevel;
8342
0
        break;
8343
0
    case QRhiSwapChainHdrInfo::DisplayReferred:
8344
0
        dbg.nospace() << " display-referred";
8345
0
        break;
8346
0
    }
8347
0
    dbg.nospace() << ')';
8348
0
    return dbg;
8349
0
}
8350
#endif
8351
8352
/*!
8353
    \class QRhiComputePipeline
8354
    \inmodule QtGuiPrivate
8355
    \inheaderfile rhi/qrhi.h
8356
    \since 6.6
8357
    \brief Compute pipeline state resource.
8358
8359
    \note Setting the shader resource bindings is mandatory. The referenced
8360
    QRhiShaderResourceBindings must already have created() called on it by the
8361
    time create() is called.
8362
8363
    \note Setting the shader is mandatory.
8364
8365
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8366
    for details.
8367
 */
8368
8369
/*!
8370
    \enum QRhiComputePipeline::Flag
8371
8372
    Flag values for describing pipeline options.
8373
8374
    \value CompileShadersWithDebugInfo Requests compiling shaders with debug
8375
    information enabled, when applicable. See
8376
    QRhiGraphicsPipeline::CompileShadersWithDebugInfo for more information.
8377
 */
8378
8379
/*!
8380
    \return the resource type.
8381
 */
8382
QRhiResource::Type QRhiComputePipeline::resourceType() const
8383
0
{
8384
0
    return ComputePipeline;
8385
0
}
8386
8387
/*!
8388
    \internal
8389
 */
8390
QRhiComputePipeline::QRhiComputePipeline(QRhiImplementation *rhi)
8391
0
    : QRhiResource(rhi)
8392
0
{
8393
0
}
8394
8395
/*!
8396
    \fn QRhiComputePipeline::Flags QRhiComputePipeline::flags() const
8397
    \return the currently set flags.
8398
 */
8399
8400
/*!
8401
    \fn void QRhiComputePipeline::setFlags(Flags f)
8402
    Sets the flags \a f.
8403
 */
8404
8405
/*!
8406
    \fn QRhiShaderStage QRhiComputePipeline::shaderStage() const
8407
    \return the currently set shader.
8408
 */
8409
8410
/*!
8411
    \fn void QRhiComputePipeline::setShaderStage(const QRhiShaderStage &stage)
8412
8413
    Sets the shader to use. \a stage can only refer to the
8414
    \l{QRhiShaderStage::Compute}{compute stage}.
8415
 */
8416
8417
/*!
8418
    \fn QRhiShaderResourceBindings *QRhiComputePipeline::shaderResourceBindings() const
8419
    \return the currently associated QRhiShaderResourceBindings object.
8420
 */
8421
8422
/*!
8423
    \fn void QRhiComputePipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
8424
8425
    Associates with \a srb describing the resource binding layout and the
8426
    resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional. As
8427
    with graphics pipelines, the \a srb passed in here can leave the actual
8428
    buffer or texture objects unspecified (\nullptr) as long as there is
8429
    another,
8430
    \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
8431
    QRhiShaderResourceBindings bound via
8432
    \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
8433
    recording the dispatch call.
8434
 */
8435
8436
/*!
8437
    \struct QRhiIndirectDrawCommand
8438
    \inmodule QtGuiPrivate
8439
    \inheaderfile rhi/qrhi.h
8440
    \since 6.12
8441
    \brief Draw command.
8442
8443
    A draw command that can be uploaded to a QRhiBuffer of usage
8444
    QRhiBuffer::UsageFlag::IndirectBuffer.
8445
8446
    \sa QRhiCommandBuffer::drawIndirect()
8447
8448
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8449
    for details.
8450
 */
8451
8452
/*!
8453
    \variable QRhiIndirectDrawCommand::vertexCount
8454
*/
8455
8456
/*!
8457
    \variable QRhiIndirectDrawCommand::instanceCount
8458
*/
8459
8460
/*!
8461
    \variable QRhiIndirectDrawCommand::firstVertex
8462
*/
8463
8464
/*!
8465
    \variable QRhiIndirectDrawCommand::firstInstance
8466
*/
8467
8468
/*!
8469
    \struct QRhiIndexedIndirectDrawCommand
8470
    \inmodule QtGuiPrivate
8471
    \inheaderfile rhi/qrhi.h
8472
    \since 6.12
8473
    \brief Indexed draw command.
8474
8475
    An indexed draw command that can be uploaded to a QRhiBuffer of usage
8476
    QRhiBuffer::UsageFlag::IndirectBuffer.
8477
8478
    \sa QRhiCommandBuffer::drawIndexedIndirect()
8479
8480
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8481
    for details.
8482
 */
8483
8484
/*!
8485
    \variable QRhiIndexedIndirectDrawCommand::indexCount
8486
*/
8487
8488
/*!
8489
    \variable QRhiIndexedIndirectDrawCommand::instanceCount
8490
*/
8491
8492
/*!
8493
    \variable QRhiIndexedIndirectDrawCommand::firstIndex
8494
*/
8495
8496
/*!
8497
    \variable QRhiIndexedIndirectDrawCommand::vertexOffset
8498
*/
8499
8500
/*!
8501
    \variable QRhiIndexedIndirectDrawCommand::firstInstance
8502
*/
8503
8504
/*!
8505
    \class QRhiCommandBuffer
8506
    \inmodule QtGuiPrivate
8507
    \inheaderfile rhi/qrhi.h
8508
    \since 6.6
8509
    \brief Command buffer resource.
8510
8511
    Not creatable by applications at the moment. The only ways to obtain a
8512
    valid QRhiCommandBuffer are to get it from the targeted swapchain via
8513
    QRhiSwapChain::currentFrameCommandBuffer(), or, in case of rendering
8514
    completely offscreen, initializing one via QRhi::beginOffscreenFrame().
8515
8516
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
8517
    for details.
8518
 */
8519
8520
/*!
8521
    \enum QRhiCommandBuffer::IndexFormat
8522
    Specifies the index data type
8523
8524
    \value IndexUInt16 Unsigned 16-bit (quint16)
8525
    \value IndexUInt32 Unsigned 32-bit (quint32)
8526
 */
8527
8528
/*!
8529
    \enum QRhiCommandBuffer::BeginPassFlag
8530
    Flag values for QRhi::beginPass()
8531
8532
    \value ExternalContent Specifies that there will be a call to
8533
    QRhiCommandBuffer::beginExternal() in this pass. Some backends, Vulkan in
8534
    particular, will fail if this flag is not set and beginExternal() is still
8535
    called.
8536
8537
    \value DoNotTrackResourcesForCompute Specifies that there is no need to
8538
    track resources used in this pass if the only purpose of such tracking is
8539
    to generate barriers for compute. Implies that there are no compute passes
8540
    in the frame. This is an optimization hint that may be taken into account
8541
    by certain backends, OpenGL in particular, allowing them to skip certain
8542
    operations. When this flag is set for a render pass in a frame, calling
8543
    \l{QRhiCommandBuffer::beginComputePass()}{beginComputePass()} in that frame
8544
    may lead to unexpected behavior, depending on the resource dependencies
8545
    between the render and compute passes.
8546
 */
8547
8548
/*!
8549
    \typedef QRhiCommandBuffer::DynamicOffset
8550
8551
    Synonym for std::pair<int, quint32>. The first entry is the binding, the second
8552
    is the offset in the buffer.
8553
*/
8554
8555
/*!
8556
    \typedef QRhiCommandBuffer::VertexInput
8557
8558
    Synonym for std::pair<QRhiBuffer *, quint32>. The second entry is an offset in
8559
    the buffer specified by the first.
8560
*/
8561
8562
/*!
8563
    \internal
8564
 */
8565
QRhiCommandBuffer::QRhiCommandBuffer(QRhiImplementation *rhi)
8566
0
    : QRhiResource(rhi)
8567
0
{
8568
0
}
8569
8570
/*!
8571
    \return the resource type.
8572
 */
8573
QRhiResource::Type QRhiCommandBuffer::resourceType() const
8574
0
{
8575
0
    return CommandBuffer;
8576
0
}
8577
8578
static const char *resourceTypeStr(const QRhiResource *res)
8579
0
{
8580
0
    switch (res->resourceType()) {
8581
0
    case QRhiResource::Buffer:
8582
0
        return "Buffer";
8583
0
    case QRhiResource::Texture:
8584
0
        return "Texture";
8585
0
    case QRhiResource::Sampler:
8586
0
        return "Sampler";
8587
0
    case QRhiResource::RenderBuffer:
8588
0
        return "RenderBuffer";
8589
0
    case QRhiResource::RenderPassDescriptor:
8590
0
        return "RenderPassDescriptor";
8591
0
    case QRhiResource::SwapChainRenderTarget:
8592
0
        return "SwapChainRenderTarget";
8593
0
    case QRhiResource::TextureRenderTarget:
8594
0
        return "TextureRenderTarget";
8595
0
    case QRhiResource::ShaderResourceBindings:
8596
0
        return "ShaderResourceBindings";
8597
0
    case QRhiResource::GraphicsPipeline:
8598
0
        return "GraphicsPipeline";
8599
0
    case QRhiResource::SwapChain:
8600
0
        return "SwapChain";
8601
0
    case QRhiResource::ComputePipeline:
8602
0
        return "ComputePipeline";
8603
0
    case QRhiResource::CommandBuffer:
8604
0
        return "CommandBuffer";
8605
0
    case QRhiResource::ShadingRateMap:
8606
0
        return "ShadingRateMap";
8607
0
    }
8608
8609
0
    Q_UNREACHABLE_RETURN("");
8610
0
}
8611
8612
QRhiImplementation::~QRhiImplementation()
8613
0
{
8614
0
    qDeleteAll(resUpdPool);
8615
8616
    // Be nice and show something about leaked stuff. Though we may not get
8617
    // this far with some backends where the allocator or the api may check
8618
    // and freak out for unfreed graphics objects in the derived dtor already.
8619
0
#ifndef QT_NO_DEBUG
8620
    // debug builds: just do it always
8621
0
    static bool leakCheck = true;
8622
#else
8623
    // release builds: opt-in
8624
    static bool leakCheck = qEnvironmentVariableIntValue("QT_RHI_LEAK_CHECK");
8625
#endif
8626
0
    if (!resources.isEmpty()) {
8627
0
        if (leakCheck) {
8628
0
            qWarning("QRhi %p going down with %d unreleased resources that own native graphics objects. This is not nice.",
8629
0
                     q, int(resources.size()));
8630
0
        }
8631
0
        for (auto it = resources.cbegin(), end = resources.cend(); it != end; ++it) {
8632
0
            QRhiResource *res = it.key();
8633
0
            const bool ownsNativeResources = it.value();
8634
0
            if (leakCheck && ownsNativeResources)
8635
0
                qWarning("  %s resource %p (%s)", resourceTypeStr(res), res, res->m_objectName.constData());
8636
8637
            // Null out the resource's rhi pointer. This is why it makes sense to do null
8638
            // checks in the destroy() implementations of the various resource types. It
8639
            // allows to survive in bad applications that somehow manage to destroy a
8640
            // resource of a QRhi after the QRhi itself.
8641
0
            res->m_rhi = nullptr;
8642
0
        }
8643
0
    }
8644
0
}
8645
8646
bool QRhiImplementation::isCompressedFormat(QRhiTexture::Format format) const
8647
0
{
8648
0
    return (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
8649
0
            || (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
8650
0
            || (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12);
8651
0
}
8652
8653
bool QRhiImplementation::compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
8654
                                              quint32 *bpl, quint32 *byteSize,
8655
                                              QSize *blockDim) const
8656
0
{
8657
0
    int xdim = 4;
8658
0
    int ydim = 4;
8659
0
    quint32 blockSize = 0;
8660
8661
0
    switch (format) {
8662
0
    case QRhiTexture::BC1:
8663
0
        blockSize = 8;
8664
0
        break;
8665
0
    case QRhiTexture::BC2:
8666
0
        blockSize = 16;
8667
0
        break;
8668
0
    case QRhiTexture::BC3:
8669
0
        blockSize = 16;
8670
0
        break;
8671
0
    case QRhiTexture::BC4:
8672
0
        blockSize = 8;
8673
0
        break;
8674
0
    case QRhiTexture::BC5:
8675
0
        blockSize = 16;
8676
0
        break;
8677
0
    case QRhiTexture::BC6H:
8678
0
        blockSize = 16;
8679
0
        break;
8680
0
    case QRhiTexture::BC7:
8681
0
        blockSize = 16;
8682
0
        break;
8683
8684
0
    case QRhiTexture::ETC2_RGB8:
8685
0
        blockSize = 8;
8686
0
        break;
8687
0
    case QRhiTexture::ETC2_RGB8A1:
8688
0
        blockSize = 8;
8689
0
        break;
8690
0
    case QRhiTexture::ETC2_RGBA8:
8691
0
        blockSize = 16;
8692
0
        break;
8693
8694
0
    case QRhiTexture::ASTC_4x4:
8695
0
        blockSize = 16;
8696
0
        break;
8697
0
    case QRhiTexture::ASTC_5x4:
8698
0
        blockSize = 16;
8699
0
        xdim = 5;
8700
0
        break;
8701
0
    case QRhiTexture::ASTC_5x5:
8702
0
        blockSize = 16;
8703
0
        xdim = ydim = 5;
8704
0
        break;
8705
0
    case QRhiTexture::ASTC_6x5:
8706
0
        blockSize = 16;
8707
0
        xdim = 6;
8708
0
        ydim = 5;
8709
0
        break;
8710
0
    case QRhiTexture::ASTC_6x6:
8711
0
        blockSize = 16;
8712
0
        xdim = ydim = 6;
8713
0
        break;
8714
0
    case QRhiTexture::ASTC_8x5:
8715
0
        blockSize = 16;
8716
0
        xdim = 8;
8717
0
        ydim = 5;
8718
0
        break;
8719
0
    case QRhiTexture::ASTC_8x6:
8720
0
        blockSize = 16;
8721
0
        xdim = 8;
8722
0
        ydim = 6;
8723
0
        break;
8724
0
    case QRhiTexture::ASTC_8x8:
8725
0
        blockSize = 16;
8726
0
        xdim = ydim = 8;
8727
0
        break;
8728
0
    case QRhiTexture::ASTC_10x5:
8729
0
        blockSize = 16;
8730
0
        xdim = 10;
8731
0
        ydim = 5;
8732
0
        break;
8733
0
    case QRhiTexture::ASTC_10x6:
8734
0
        blockSize = 16;
8735
0
        xdim = 10;
8736
0
        ydim = 6;
8737
0
        break;
8738
0
    case QRhiTexture::ASTC_10x8:
8739
0
        blockSize = 16;
8740
0
        xdim = 10;
8741
0
        ydim = 8;
8742
0
        break;
8743
0
    case QRhiTexture::ASTC_10x10:
8744
0
        blockSize = 16;
8745
0
        xdim = ydim = 10;
8746
0
        break;
8747
0
    case QRhiTexture::ASTC_12x10:
8748
0
        blockSize = 16;
8749
0
        xdim = 12;
8750
0
        ydim = 10;
8751
0
        break;
8752
0
    case QRhiTexture::ASTC_12x12:
8753
0
        blockSize = 16;
8754
0
        xdim = ydim = 12;
8755
0
        break;
8756
8757
0
    default:
8758
0
        Q_UNREACHABLE();
8759
0
        break;
8760
0
    }
8761
8762
0
    const quint32 wblocks = quint32((qint64(qMax(0, size.width())) + xdim - 1) / xdim);
8763
0
    const quint32 hblocks = quint32((qint64(qMax(0, size.height())) + ydim - 1) / ydim);
8764
8765
0
    if (blockDim)
8766
0
        *blockDim = QSize(xdim, ydim);
8767
8768
    // Compute in 64-bit, as safety for extreme geometry that would not fit.
8769
    // wblocks and hblocks are at most 2^29 and blockSize at most 16.
8770
0
    const quint64 bytesPerLine = quint64(wblocks) * quint64(blockSize);
8771
0
    const quint64 totalSize = quint64(wblocks) * quint64(hblocks) * quint64(blockSize);
8772
0
    if (bytesPerLine > std::numeric_limits<quint32>::max()
8773
0
        || totalSize > std::numeric_limits<quint32>::max())
8774
0
    {
8775
0
        qWarning("Compressed texture of size %dx%d with format %d has a byte size of %llu "
8776
0
                 "which is too large to be handled",
8777
0
                 size.width(), size.height(), int(format), totalSize);
8778
0
        if (bpl)
8779
0
            *bpl = 0;
8780
0
        if (byteSize)
8781
0
            *byteSize = 0;
8782
0
        return false;
8783
0
    }
8784
8785
0
    if (bpl)
8786
0
        *bpl = quint32(bytesPerLine);
8787
0
    if (byteSize)
8788
0
        *byteSize = quint32(totalSize);
8789
8790
0
    return true;
8791
0
}
8792
8793
bool QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSize &size,
8794
                                           quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const
8795
0
{
8796
0
    if (isCompressedFormat(format))
8797
0
        return compressedFormatInfo(format, size, bpl, byteSize, nullptr);
8798
8799
0
    quint32 bpc = 0;
8800
0
    switch (format) {
8801
0
    case QRhiTexture::RGBA8:
8802
0
        bpc = 4;
8803
0
        break;
8804
0
    case QRhiTexture::BGRA8:
8805
0
        bpc = 4;
8806
0
        break;
8807
0
    case QRhiTexture::R8:
8808
0
        bpc = 1;
8809
0
        break;
8810
0
    case QRhiTexture::RG8:
8811
0
        bpc = 2;
8812
0
        break;
8813
0
    case QRhiTexture::R16:
8814
0
        bpc = 2;
8815
0
        break;
8816
0
    case QRhiTexture::RG16:
8817
0
        bpc = 4;
8818
0
        break;
8819
0
    case QRhiTexture::RED_OR_ALPHA8:
8820
0
        bpc = 1;
8821
0
        break;
8822
8823
0
    case QRhiTexture::RGBA16F:
8824
0
        bpc = 8;
8825
0
        break;
8826
0
    case QRhiTexture::RGBA32F:
8827
0
        bpc = 16;
8828
0
        break;
8829
0
    case QRhiTexture::R16F:
8830
0
        bpc = 2;
8831
0
        break;
8832
0
    case QRhiTexture::R32F:
8833
0
        bpc = 4;
8834
0
        break;
8835
8836
0
    case QRhiTexture::RGB10A2:
8837
0
        bpc = 4;
8838
0
        break;
8839
8840
0
    case QRhiTexture::D16:
8841
0
        bpc = 2;
8842
0
        break;
8843
0
    case QRhiTexture::D24:
8844
0
    case QRhiTexture::D24S8:
8845
0
    case QRhiTexture::D32F:
8846
0
        bpc = 4;
8847
0
        break;
8848
8849
0
    case QRhiTexture::D32FS8:
8850
0
        bpc = 8;
8851
0
        break;
8852
8853
0
    case QRhiTexture::R8SI:
8854
0
    case QRhiTexture::R8UI:
8855
0
        bpc = 1;
8856
0
        break;
8857
0
    case QRhiTexture::R32SI:
8858
0
    case QRhiTexture::R32UI:
8859
0
        bpc = 4;
8860
0
        break;
8861
0
    case QRhiTexture::RG32SI:
8862
0
    case QRhiTexture::RG32UI:
8863
0
        bpc = 8;
8864
0
        break;
8865
0
    case QRhiTexture::RGBA32SI:
8866
0
    case QRhiTexture::RGBA32UI:
8867
0
        bpc = 16;
8868
0
        break;
8869
8870
0
    default:
8871
0
        Q_UNREACHABLE();
8872
0
        break;
8873
0
    }
8874
8875
0
    const quint32 width = uint(qMax(0, size.width()));
8876
0
    const quint32 height = uint(qMax(0, size.height()));
8877
8878
0
    if (bytesPerPixel)
8879
0
        *bytesPerPixel = bpc;
8880
8881
    // Compute in 64-bit, as safety for extreme geometry that would not fit.
8882
0
    const quint64 bytesPerLine = quint64(width) * quint64(bpc);
8883
0
    const quint64 pixelCount = quint64(width) * quint64(height);
8884
0
    if (bytesPerLine > std::numeric_limits<quint32>::max()
8885
0
        || pixelCount > std::numeric_limits<quint32>::max() / bpc)
8886
0
    {
8887
0
        qWarning("Texture of size %dx%d with format %d has a byte size "
8888
0
                 "which is too large to be handled",
8889
0
                 size.width(), size.height(), int(format));
8890
0
        if (bpl)
8891
0
            *bpl = 0;
8892
0
        if (byteSize)
8893
0
            *byteSize = 0;
8894
0
        return false;
8895
0
    }
8896
8897
0
    if (bpl)
8898
0
        *bpl = quint32(bytesPerLine);
8899
0
    if (byteSize)
8900
0
        *byteSize = quint32(pixelCount * quint64(bpc));
8901
8902
0
    return true;
8903
0
}
8904
8905
bool QRhiImplementation::isStencilSupportingFormat(QRhiTexture::Format format) const
8906
0
{
8907
0
    switch (format) {
8908
0
    case QRhiTexture::D24S8:
8909
0
    case QRhiTexture::D32FS8:
8910
0
        return true;
8911
0
    default:
8912
0
        break;
8913
0
    }
8914
0
    return false;
8915
0
}
8916
8917
bool QRhiImplementation::sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps)
8918
0
{
8919
0
    if (ps->cbeginShaderStages() == ps->cendShaderStages()) {
8920
0
        qWarning("Cannot build a graphics pipeline without any stages");
8921
0
        return false;
8922
0
    }
8923
8924
0
    bool hasVertexStage = false;
8925
0
    for (auto it = ps->cbeginShaderStages(), itEnd = ps->cendShaderStages(); it != itEnd; ++it) {
8926
0
        if (!it->shader().isValid()) {
8927
0
            qWarning("Empty shader passed to graphics pipeline");
8928
0
            return false;
8929
0
        }
8930
0
        if (it->type() == QRhiShaderStage::Vertex)
8931
0
            hasVertexStage = true;
8932
0
    }
8933
0
    if (!hasVertexStage) {
8934
0
        qWarning("Cannot build a graphics pipeline without a vertex stage");
8935
0
        return false;
8936
0
    }
8937
8938
0
    if (!ps->renderPassDescriptor()) {
8939
0
        qWarning("Cannot build a graphics pipeline without a QRhiRenderPassDescriptor");
8940
0
        return false;
8941
0
    }
8942
8943
0
    if (!ps->shaderResourceBindings()) {
8944
0
        qWarning("Cannot build a graphics pipeline without QRhiShaderResourceBindings");
8945
0
        return false;
8946
0
    }
8947
8948
0
    return true;
8949
0
}
8950
8951
bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb)
8952
0
{
8953
0
#ifndef QT_NO_DEBUG
8954
0
    bool bindingsOk = true;
8955
0
    const int CHECKED_BINDINGS_COUNT = 64;
8956
0
    bool bindingSeen[CHECKED_BINDINGS_COUNT] = {};
8957
0
    for (auto it = srb->cbeginBindings(), end = srb->cendBindings(); it != end; ++it) {
8958
0
        const int binding = shaderResourceBindingData(*it)->binding;
8959
0
        if (binding >= CHECKED_BINDINGS_COUNT)
8960
0
            continue;
8961
0
        if (binding < 0) {
8962
0
            qWarning("Invalid binding number %d", binding);
8963
0
            bindingsOk = false;
8964
0
            continue;
8965
0
        }
8966
0
        switch (shaderResourceBindingData(*it)->type) {
8967
0
        case QRhiShaderResourceBinding::UniformBuffer:
8968
0
            if (!bindingSeen[binding]) {
8969
0
                bindingSeen[binding] = true;
8970
0
            } else {
8971
0
                qWarning("Uniform buffer duplicates an existing binding number %d", binding);
8972
0
                bindingsOk = false;
8973
0
            }
8974
0
            break;
8975
0
        case QRhiShaderResourceBinding::SampledTexture:
8976
0
            if (!bindingSeen[binding]) {
8977
0
                bindingSeen[binding] = true;
8978
0
            } else {
8979
0
                qWarning("Combined image sampler duplicates an existing binding number %d", binding);
8980
0
                bindingsOk = false;
8981
0
            }
8982
0
            break;
8983
0
        case QRhiShaderResourceBinding::Texture:
8984
0
            if (!bindingSeen[binding]) {
8985
0
                bindingSeen[binding] = true;
8986
0
            } else {
8987
0
                qWarning("Texture duplicates an existing binding number %d", binding);
8988
0
                bindingsOk = false;
8989
0
            }
8990
0
            break;
8991
0
        case QRhiShaderResourceBinding::Sampler:
8992
0
            if (!bindingSeen[binding]) {
8993
0
                bindingSeen[binding] = true;
8994
0
            } else {
8995
0
                qWarning("Sampler duplicates an existing binding number %d", binding);
8996
0
                bindingsOk = false;
8997
0
            }
8998
0
            break;
8999
0
        case QRhiShaderResourceBinding::ImageLoad:
9000
0
        case QRhiShaderResourceBinding::ImageStore:
9001
0
        case QRhiShaderResourceBinding::ImageLoadStore:
9002
0
            if (!bindingSeen[binding]) {
9003
0
                bindingSeen[binding] = true;
9004
0
            } else {
9005
0
                qWarning("Image duplicates an existing binding number %d", binding);
9006
0
                bindingsOk = false;
9007
0
            }
9008
0
            break;
9009
0
        case QRhiShaderResourceBinding::BufferLoad:
9010
0
        case QRhiShaderResourceBinding::BufferStore:
9011
0
        case QRhiShaderResourceBinding::BufferLoadStore:
9012
0
            if (!bindingSeen[binding]) {
9013
0
                bindingSeen[binding] = true;
9014
0
            } else {
9015
0
                qWarning("Buffer duplicates an existing binding number %d", binding);
9016
0
                bindingsOk = false;
9017
0
            }
9018
0
            break;
9019
0
        default:
9020
0
            qWarning("Unknown binding type %d", int(shaderResourceBindingData(*it)->type));
9021
0
            bindingsOk = false;
9022
0
            break;
9023
0
        }
9024
0
    }
9025
9026
0
    if (!bindingsOk) {
9027
0
        qWarning() << *srb;
9028
0
        return false;
9029
0
    }
9030
#else
9031
    Q_UNUSED(srb);
9032
#endif
9033
0
    return true;
9034
0
}
9035
9036
bool QRhiImplementation::sanityCheckResourceOwnership(QRhiResource *maybeResource)
9037
0
{
9038
0
    if (maybeResource == nullptr || maybeResource->m_rhi == nullptr)
9039
0
        return true;
9040
9041
0
    if (maybeResource->m_rhi->q != q) {
9042
0
        qWarning("%s %p (%s) belongs to QRhi %p, but client code attempted to use it with QRhi %p. This is wrong.",
9043
0
                  resourceTypeStr(maybeResource),
9044
0
                  maybeResource,
9045
0
                  maybeResource->m_objectName.constData(),
9046
0
                  maybeResource->m_rhi->q,
9047
0
                  q);
9048
0
        return false;
9049
0
    }
9050
9051
0
    return true;
9052
0
}
9053
9054
int QRhiImplementation::effectiveSampleCount(int sampleCount) const
9055
0
{
9056
    // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
9057
0
    const int s = qBound(1, sampleCount, 64);
9058
0
    const QList<int> supported = supportedSampleCounts();
9059
0
    int result = 1;
9060
9061
    // Stay compatible with Qt 5 in that requesting an unsupported sample count
9062
    // is not an error (although we still do a categorized debug print about
9063
    // this), and rather a supported value, preferably a close one, not just 1,
9064
    // is used instead. This is actually deviating from Qt 5 as that performs a
9065
    // clamping only and does not handle cases such as when sample count 2 is
9066
    // not supported but 4 is. (OpenGL handles things like that gracefully,
9067
    // other APIs may not, so improve this by picking the next largest, or in
9068
    // absence of that, the largest value; this with the goal to not reduce
9069
    // quality by rather picking a larger-than-requested value than a smaller one)
9070
9071
0
    for (int i = 0, ie = supported.count(); i != ie; ++i) {
9072
        // assumes the 'supported' list is sorted
9073
0
        if (supported[i] >= s) {
9074
0
            result = supported[i];
9075
0
            break;
9076
0
        }
9077
0
    }
9078
9079
0
    if (result != s) {
9080
0
        if (result == 1 && !supported.isEmpty())
9081
0
            result = supported.last();
9082
0
        qCDebug(QRHI_LOG_INFO, "Attempted to set unsupported sample count %d, using %d instead",
9083
0
                sampleCount, result);
9084
0
    }
9085
9086
0
    return result;
9087
0
}
9088
9089
/*!
9090
    \internal
9091
 */
9092
QRhi::QRhi()
9093
0
{
9094
0
}
9095
9096
/*!
9097
    Destructor. Destroys the backend and releases resources.
9098
 */
9099
QRhi::~QRhi()
9100
0
{
9101
0
    if (!d)
9102
0
        return;
9103
9104
0
    d->runCleanup();
9105
9106
0
    qDeleteAll(d->pendingDeleteResources);
9107
0
    d->pendingDeleteResources.clear();
9108
9109
0
    d->destroy();
9110
0
    delete d;
9111
0
}
9112
9113
QRhiImplementation *QRhiImplementation::newInstance(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *importDevice)
9114
0
{
9115
0
    QRhiImplementation *d = nullptr;
9116
9117
0
    switch (impl) {
9118
0
    case QRhi::Null:
9119
0
        d = new QRhiNull(static_cast<QRhiNullInitParams *>(params));
9120
0
        break;
9121
0
    case QRhi::Vulkan:
9122
#if QT_CONFIG(vulkan)
9123
        d = new QRhiVulkan(static_cast<QRhiVulkanInitParams *>(params),
9124
                           static_cast<QRhiVulkanNativeHandles *>(importDevice));
9125
        break;
9126
#else
9127
0
        Q_UNUSED(importDevice);
9128
0
        qWarning("This build of Qt has no Vulkan support");
9129
0
        break;
9130
0
#endif
9131
0
    case QRhi::OpenGLES2:
9132
#ifndef QT_NO_OPENGL
9133
        d = new QRhiGles2(static_cast<QRhiGles2InitParams *>(params),
9134
                          static_cast<QRhiGles2NativeHandles *>(importDevice));
9135
        break;
9136
#else
9137
0
        qWarning("This build of Qt has no OpenGL support");
9138
0
        break;
9139
0
#endif
9140
0
    case QRhi::D3D11:
9141
#ifdef Q_OS_WIN
9142
        d = new QRhiD3D11(static_cast<QRhiD3D11InitParams *>(params),
9143
                          static_cast<QRhiD3D11NativeHandles *>(importDevice));
9144
        break;
9145
#else
9146
0
        qWarning("This platform has no Direct3D 11 support");
9147
0
        break;
9148
0
#endif
9149
0
    case QRhi::Metal:
9150
#if QT_CONFIG(metal)
9151
        d = new QRhiMetal(static_cast<QRhiMetalInitParams *>(params),
9152
                          static_cast<QRhiMetalNativeHandles *>(importDevice));
9153
        break;
9154
#else
9155
0
        qWarning("This platform has no Metal support");
9156
0
        break;
9157
0
#endif
9158
0
    case QRhi::D3D12:
9159
#ifdef Q_OS_WIN
9160
#ifdef QRHI_D3D12_AVAILABLE
9161
        d = new QRhiD3D12(static_cast<QRhiD3D12InitParams *>(params),
9162
                          static_cast<QRhiD3D12NativeHandles *>(importDevice));
9163
        break;
9164
#else
9165
        qWarning("Qt was built without Direct3D 12 support. "
9166
                 "This is likely due to having ancient SDK headers (such as d3d12.h) in the Qt build environment. "
9167
                 "Rebuild Qt with an SDK supporting D3D12 features introduced in Windows 10 version 1703, "
9168
                 "or use an MSVC build as those typically are built with more up-to-date SDKs.");
9169
        break;
9170
#endif
9171
#else
9172
0
        qWarning("This platform has no Direct3D 12 support");
9173
0
        break;
9174
0
#endif
9175
0
    }
9176
9177
0
    return d;
9178
0
}
9179
9180
void QRhiImplementation::prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags, QRhiAdapter *adapter)
9181
0
{
9182
0
    q = rhi;
9183
9184
0
    debugMarkers = flags.testFlag(QRhi::EnableDebugMarkers);
9185
9186
0
    implType = impl;
9187
0
    implThread = QThread::currentThread();
9188
9189
0
    requestedRhiAdapter = adapter;
9190
0
}
9191
9192
QRhi::AdapterList QRhiImplementation::enumerateAdaptersBeforeCreate(QRhiNativeHandles *) const
9193
0
{
9194
0
    return {};
9195
0
}
9196
9197
/*!
9198
    \overload
9199
9200
    Equivalent to create(\a impl, \a params, \a flags, \a importDevice, \c nullptr).
9201
 */
9202
QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice)
9203
0
{
9204
0
    return create(impl, params, flags, importDevice, nullptr);
9205
0
}
9206
9207
/*!
9208
    \return a new QRhi instance with a backend for the graphics API specified
9209
    by \a impl with the specified \a flags. \return \c nullptr if the
9210
    function fails.
9211
9212
    \a params must point to an instance of one of the backend-specific
9213
    subclasses of QRhiInitParams, such as, QRhiVulkanInitParams,
9214
    QRhiMetalInitParams, QRhiD3D11InitParams, QRhiD3D12InitParams,
9215
    QRhiGles2InitParams. See these classes for examples on creating a QRhi.
9216
9217
    QRhi by design does not implement any fallback logic: if the specified API
9218
    cannot be initialized, create() will fail, with warnings printed on the
9219
    debug output by the backends. The clients of QRhi, for example Qt Quick,
9220
    may however provide additional logic that allow falling back to an API
9221
    different than what was requested, depending on the platform. If the
9222
    intention is just to test if initialization would succeed when calling
9223
    create() at later point, it is preferable to use probe() instead of
9224
    create(), because with some backends probing can be implemented in a more
9225
    lightweight manner as opposed to create(), which performs full
9226
    initialization of the infrastructure and is wasteful if that QRhi instance
9227
    is then thrown immediately away.
9228
9229
    \a importDevice allows using an already existing graphics device, without
9230
    QRhi creating its own. When not null, this parameter must point to an
9231
    instance of one of the subclasses of QRhiNativeHandles:
9232
    QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles,
9233
    QRhiMetalNativeHandles, QRhiGles2NativeHandles. The exact details and
9234
    semantics depend on the backand and the underlying graphics API.
9235
9236
    Specifying a QRhiAdapter in \a adapter offers a transparent, cross-API
9237
    alternative to passing in a \c VkPhysicalDevice via QRhiVulkanNativeHandles,
9238
    or an adapter LUID via QRhiD3D12NativeHandles. The ownership of \a adapter
9239
    is not taken. See enumerateAdapters() for more information on this approach.
9240
9241
    \note \a importDevice and \a adapter cannot be both specified.
9242
9243
    \sa probe()
9244
 */
9245
QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice, QRhiAdapter *adapter)
9246
0
{
9247
0
    if (adapter && importDevice)
9248
0
        qWarning("adapter and importDevice should not both be non-null in QRhi::create()");
9249
9250
0
    std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, importDevice));
9251
0
    if (!rd)
9252
0
        return nullptr;
9253
9254
0
    std::unique_ptr<QRhi> r(new QRhi);
9255
0
    r->d = rd.release();
9256
0
    r->d->prepareForCreate(r.get(), impl, flags, adapter);
9257
0
    if (!r->d->create(flags))
9258
0
        return nullptr;
9259
9260
0
    return r.release();
9261
0
}
9262
9263
/*!
9264
    \return true if create() can be expected to succeed when called the given
9265
    \a impl and \a params.
9266
9267
    For some backends this is equivalent to calling create(), checking its
9268
    return value, and then destroying the resulting QRhi.
9269
9270
    For others, in particular with Metal, there may be a specific probing
9271
    implementation, which allows testing in a more lightweight manner without
9272
    polluting the debug output with warnings upon failures.
9273
9274
    \sa create()
9275
 */
9276
bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)
9277
0
{
9278
0
    bool ok = false;
9279
9280
    // The only place currently where this makes sense is Metal, where the API
9281
    // is simple enough so that a special probing function - doing nothing but
9282
    // a MTLCreateSystemDefaultDevice - is reasonable. Elsewhere, just call
9283
    // create() and then drop the result.
9284
9285
0
    if (impl == Metal) {
9286
#if QT_CONFIG(metal)
9287
        ok = QRhiMetal::probe(static_cast<QRhiMetalInitParams *>(params));
9288
#endif
9289
0
    } else {
9290
0
        QRhi *rhi = create(impl, params);
9291
0
        ok = rhi != nullptr;
9292
0
        delete rhi;
9293
0
    }
9294
0
    return ok;
9295
0
}
9296
9297
/*!
9298
    \typedef QRhi::AdapterList
9299
    \relates QRhi
9300
    \since 6.10
9301
9302
    Synonym for QVector<QRhiAdapter *>.
9303
*/
9304
9305
/*!
9306
    \return the list of adapters (physical devices) present, or an empty list
9307
    when such control is not available with a given graphics API.
9308
9309
    Backends where such level of control is not available, the returned list is
9310
    always empty. Thus an empty list does not indicate there are no graphics
9311
    devices in the system, but that fine-grained control over selecting which
9312
    one to use is not available.
9313
9314
    Backends for Direct 3D 11, Direct 3D 12, and Vulkan can be expected to fully
9315
    support enumerating adapters. Others may not. The backend is specified by \a
9316
    impl. A QRhiAdapter returned from this function must only be used in a
9317
    create() call with the same \a impl. Some underlying APIs may present
9318
    further limitations, with Vulkan in particular the QRhiAdapter is specified
9319
    to the QVulkanInstance (\c VkInstance).
9320
9321
    The caller is expected to destroy the QRhiAdapter objects in the list. Apart
9322
    from querying \l{QRhiAdapter::}{info()}, the only purpose of these objects is
9323
    to be passed on to create(), or the corresponding functions in higher layers
9324
    such as Qt Quick.
9325
9326
    The following snippet, written specifically for Vulkan, shows how to
9327
    enumerate the available physical devices and request to create a QRhi for
9328
    the chosen one. This in practice is equivalent to passing in a \c
9329
    VkPhysicalDevice via a QRhiVulkanNativeHandles to create(), but it involves
9330
    less API-specific code on the application side:
9331
9332
    \code
9333
      QRhiVulkanInitParams initParams;
9334
      initParams.inst = &vulkanInstance;
9335
      QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::Vulkan, &initParams);
9336
      QRhiAdapter *chosenAdapter = nullptr;
9337
      for (QRhiAdapter *adapter : adapters) {
9338
          if (looksGood(adapter->info())) {
9339
              chosenAdapter = adapter;
9340
              break;
9341
          }
9342
      }
9343
      QRhi *rhi = QRhi::create(QRhi::Vulkan, &initParams, {}, nullptr, chosenAdapter);
9344
      qDeleteAll(adapters);
9345
    \endcode
9346
9347
    Passing in \a params is required due to some of the underlying graphics
9348
    APIs' design. With Vulkan in particular, the QVulkanInstance must be
9349
    provided, since enumerating is not possible without it. Other fields in the
9350
    backend-specific \a params will not actually be used by this function.
9351
9352
    \a nativeHandles is optional. When specified, it must be a valid
9353
    QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, or QRhiVulkanNativeHandles,
9354
    similarly to create(). However, unlike create(), only the physical device
9355
    (in case of Vulkan) or the adapter LUID (in case of D3D) fields are used,
9356
    all other fields are ignored. This can be used the restrict the results to a
9357
    given adapter. The returned list will contain 1 or 0 elements in this case.
9358
9359
    Note how in the previous code snippet the looksGood() function
9360
    implementation cannot perform any platform-specific filtering based on the
9361
    true adapter / physical device identity, such as the adapter LUID on Windows
9362
    or the VkPhysicalDevice with Vulkan. This is because QRhiDriverInfo does not
9363
    contain platform-specific data. Instead, use \a nativeHandles to get the
9364
    results filtered already inside enumerateAdapters().
9365
9366
    The following two snippets, using Direct 3D 12 as an example, are equivalent
9367
    in practice:
9368
9369
    \code
9370
      // enumerateAdapters-based approach from Qt 6.10 on
9371
      QRhiD3D12InitParams initParams;
9372
      QRhiD3D12NativeHandles nativeHandles;
9373
      nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
9374
      nativeHandles.adapterLuidHigh = luid.HighPart;
9375
      QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::D3D12, &initParams, &nativeHandles);
9376
      if (adapters.isEmpty()) { qWarning("Requested adapter was not found"); }
9377
      QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, nullptr, adapters[0]);
9378
      qDeleteAll(adapters);
9379
    \endcode
9380
9381
    \code
9382
      // traditional approach, more lightweight
9383
      QRhiD3D12InitParams initParams;
9384
      QRhiD3D12NativeHandles nativeHandles;
9385
      nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
9386
      nativeHandles.adapterLuidHigh = luid.HighPart;
9387
      QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, &nativeHandles, nullptr);
9388
    \endcode
9389
9390
    \since 6.10
9391
    \sa create()
9392
 */
9393
QRhi::AdapterList QRhi::enumerateAdapters(Implementation impl, QRhiInitParams *params, QRhiNativeHandles *nativeHandles)
9394
0
{
9395
0
    std::unique_ptr<QRhiImplementation> rd(QRhiImplementation::newInstance(impl, params, nullptr));
9396
0
    if (!rd)
9397
0
        return {};
9398
9399
0
    return rd->enumerateAdaptersBeforeCreate(nativeHandles);
9400
0
}
9401
9402
/*!
9403
    \struct QRhiSwapChainProxyData
9404
    \inmodule QtGuiPrivate
9405
    \inheaderfile rhi/qrhi.h
9406
    \since 6.6
9407
9408
    \brief Opaque data describing native objects needed to set up a swapchain.
9409
9410
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9411
    for details.
9412
9413
    \sa QRhi::updateSwapChainProxyData()
9414
 */
9415
9416
/*!
9417
    Generates and returns a QRhiSwapChainProxyData struct containing opaque
9418
    data specific to the backend and graphics API specified by \a impl. \a
9419
    window is the QWindow a swapchain is targeting.
9420
9421
    The returned struct can be passed to QRhiSwapChain::setProxyData(). This
9422
    makes sense in threaded rendering systems: this static function is expected
9423
    to be called on the \b{main (gui) thread}, unlike all QRhi operations, then
9424
    transferred to the thread working with the QRhi and QRhiSwapChain and passed
9425
    on to the swapchain. This allows doing native platform queries that are
9426
    only safe to be called on the main thread, for example to query the
9427
    CAMetalLayer from a NSView, and then passing on the data to the
9428
    QRhiSwapChain living on the rendering thread. With the Metal example, doing
9429
    the view.layer access on a dedicated rendering thread causes a warning in
9430
    the Xcode Thread Checker. With the data proxy mechanism, this is avoided.
9431
9432
    When threads are not involved, generating and passing on the
9433
    QRhiSwapChainProxyData is not required: backends are guaranteed to be able
9434
    to query whatever is needed on their own, and if everything lives on the
9435
    main (gui) thread, that should be sufficient.
9436
9437
    \note \a impl should match what the QRhi is created with. For example,
9438
    calling with QRhi::Metal on a non-Apple platform will not generate any
9439
    useful data.
9440
 */
9441
QRhiSwapChainProxyData QRhi::updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)
9442
0
{
9443
#if QT_CONFIG(metal)
9444
    if (impl == Metal)
9445
        return QRhiMetal::updateSwapChainProxyData(window);
9446
#else
9447
0
    Q_UNUSED(impl);
9448
0
    Q_UNUSED(window);
9449
0
#endif
9450
0
    return {};
9451
0
}
9452
9453
/*!
9454
    \return the backend type for this QRhi.
9455
 */
9456
QRhi::Implementation QRhi::backend() const
9457
0
{
9458
0
    return d->implType;
9459
0
}
9460
9461
/*!
9462
    \return a friendly name for the backend \a impl, usually the name of the 3D
9463
    API in use.
9464
 */
9465
const char *QRhi::backendName(Implementation impl)
9466
0
{
9467
0
    switch (impl) {
9468
0
    case QRhi::Null:
9469
0
        return "Null";
9470
0
    case QRhi::Vulkan:
9471
0
        return "Vulkan";
9472
0
    case QRhi::OpenGLES2:
9473
0
        return "OpenGL";
9474
0
    case QRhi::D3D11:
9475
0
        return "D3D11";
9476
0
    case QRhi::Metal:
9477
0
        return "Metal";
9478
0
    case QRhi::D3D12:
9479
0
        return "D3D12";
9480
0
    }
9481
9482
0
    Q_UNREACHABLE_RETURN("Unknown");
9483
0
}
9484
9485
/*!
9486
    \return the backend type as string for this QRhi.
9487
 */
9488
const char *QRhi::backendName() const
9489
0
{
9490
0
    return backendName(d->implType);
9491
0
}
9492
9493
/*!
9494
    \enum QRhiDriverInfo::DeviceType
9495
    Specifies the graphics device's type, when the information is available.
9496
9497
    In practice this is only applicable with Vulkan and Metal. With Direct 3D
9498
    11 and 12, using an adapter with the software flag set leads to the value
9499
    \c CpuDevice. Otherwise, and with OpenGL, the value is always UnknownDevice.
9500
9501
    \value UnknownDevice
9502
    \value IntegratedDevice
9503
    \value DiscreteDevice
9504
    \value ExternalDevice
9505
    \value VirtualDevice
9506
    \value CpuDevice
9507
*/
9508
9509
/*!
9510
    \struct QRhiDriverInfo
9511
    \inmodule QtGuiPrivate
9512
    \inheaderfile rhi/qrhi.h
9513
    \since 6.6
9514
9515
    \brief Describes the physical device, adapter, or graphics API
9516
    implementation that is used by an initialized QRhi.
9517
9518
    Graphics APIs offer different levels and kinds of information. The only
9519
    value that is available across all APIs is the deviceName, which is a
9520
    freetext description of the physical device, adapter, or is a combination
9521
    of the strings reported for \c{GL_VENDOR} + \c{GL_RENDERER} +
9522
    \c{GL_VERSION}. The deviceId is always 0 for OpenGL. vendorId is always 0
9523
    for OpenGL and Metal. deviceType is always UnknownDevice for OpenGL and
9524
    Direct 3D.
9525
9526
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9527
    for details.
9528
 */
9529
9530
/*!
9531
    \variable QRhiDriverInfo::deviceName
9532
9533
    \sa QRhi::driverInfo()
9534
*/
9535
9536
/*!
9537
    \variable QRhiDriverInfo::deviceId
9538
9539
    \sa QRhi::driverInfo()
9540
*/
9541
9542
/*!
9543
    \variable QRhiDriverInfo::vendorId
9544
9545
    \sa QRhi::driverInfo()
9546
*/
9547
9548
/*!
9549
    \variable QRhiDriverInfo::deviceType
9550
9551
    \sa QRhi::driverInfo(), QRhiDriverInfo::DeviceType
9552
*/
9553
9554
#ifndef QT_NO_DEBUG_STREAM
9555
static inline const char *deviceTypeStr(QRhiDriverInfo::DeviceType type)
9556
0
{
9557
0
    switch (type) {
9558
0
    case QRhiDriverInfo::UnknownDevice:
9559
0
        return "Unknown";
9560
0
    case QRhiDriverInfo::IntegratedDevice:
9561
0
        return "Integrated";
9562
0
    case QRhiDriverInfo::DiscreteDevice:
9563
0
        return "Discrete";
9564
0
    case QRhiDriverInfo::ExternalDevice:
9565
0
        return "External";
9566
0
    case QRhiDriverInfo::VirtualDevice:
9567
0
        return "Virtual";
9568
0
    case QRhiDriverInfo::CpuDevice:
9569
0
        return "Cpu";
9570
0
    }
9571
9572
0
    Q_UNREACHABLE_RETURN(nullptr);
9573
0
}
9574
QDebug operator<<(QDebug dbg, const QRhiDriverInfo &info)
9575
0
{
9576
0
    QDebugStateSaver saver(dbg);
9577
0
    dbg.nospace() << "QRhiDriverInfo(deviceName=" << info.deviceName
9578
0
                  << " deviceId=0x" << Qt::hex << info.deviceId
9579
0
                  << " vendorId=0x" << info.vendorId
9580
0
                  << " deviceType=" << deviceTypeStr(info.deviceType)
9581
0
                  << ')';
9582
0
    return dbg;
9583
0
}
9584
#endif
9585
9586
/*!
9587
    \return metadata for the graphics device used by this successfully
9588
    initialized QRhi instance.
9589
 */
9590
QRhiDriverInfo QRhi::driverInfo() const
9591
0
{
9592
0
    return d->driverInfo();
9593
0
}
9594
9595
/*!
9596
    \class QRhiAdapter
9597
    \inmodule QtGuiPrivate
9598
    \inheaderfile rhi/qrhi.h
9599
    \since 6.10
9600
9601
    \brief Represents a physical graphics device.
9602
9603
    Some QRhi backends target graphics APIs that expose the concept of \c
9604
    adapters or \c{physical devices}. Call the static \l
9605
    {QRhi::}{enumerateAdapters()} function to retrieve a list of the adapters
9606
    present in the system. Pass one of the returned QRhiAdapter objects to \l
9607
    {QRhi::}{create()} in order to request using the adapter or physical device
9608
    the QRhiAdapter corresponds to. Other than exposing the QRhiDriverInfo,
9609
    QRhiAdapter is to be treated as an opaque handle.
9610
9611
    \note With Vulkan, the QRhiAdapter is valid only as long as the
9612
    QVulkanInstance that was used for \l{QRhi::}{enumerateAdapters()} is valid.
9613
    This also means that a QRhiAdapter is tied to the Vulkan instance
9614
    (QVulkanInstance, \c VkInstance) and cannot be used in the context of
9615
    another Vulkan instance.
9616
9617
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9618
    for details.
9619
 */
9620
9621
/*!
9622
    \fn virtual QRhiDriverInfo QRhiAdapter::info() const = 0
9623
9624
    \return the corresponding QRhiDriverInfo.
9625
 */
9626
9627
/*!
9628
    \internal
9629
 */
9630
QRhiAdapter::~QRhiAdapter()
9631
0
{
9632
0
}
9633
9634
/*!
9635
    \return the thread on which the QRhi was \l{QRhi::create()}{initialized}.
9636
 */
9637
QThread *QRhi::thread() const
9638
0
{
9639
0
    return d->implThread;
9640
0
}
9641
9642
/*!
9643
    Registers a \a callback that is invoked when the QRhi is destroyed.
9644
9645
    The callback will run with the graphics resource still available, so this
9646
    provides an opportunity for the application to cleanly release QRhiResource
9647
    instances belonging to the QRhi. This is particularly useful for managing
9648
    the lifetime of resources stored in \c cache type of objects, where the
9649
    cache holds QRhiResources or objects containing QRhiResources.
9650
9651
    \sa ~QRhi()
9652
 */
9653
void QRhi::addCleanupCallback(const CleanupCallback &callback)
9654
0
{
9655
0
    d->addCleanupCallback(callback);
9656
0
}
9657
9658
/*!
9659
    \overload
9660
9661
    Registers \a callback to be invoked when the QRhi is destroyed. This
9662
    overload takes an opaque pointer, \a key, that is used to ensure that a
9663
    given callback is registered (and so called) only once.
9664
9665
    \sa removeCleanupCallback()
9666
 */
9667
void QRhi::addCleanupCallback(const void *key, const CleanupCallback &callback)
9668
0
{
9669
0
    d->addCleanupCallback(key, callback);
9670
0
}
9671
9672
/*!
9673
    Deregisters the callback with \a key. If no cleanup callback was registered
9674
    with \a key, the function does nothing. Callbacks registered without a key
9675
    cannot be removed.
9676
9677
    \sa addCleanupCallback()
9678
 */
9679
void QRhi::removeCleanupCallback(const void *key)
9680
0
{
9681
0
    d->removeCleanupCallback(key);
9682
0
}
9683
9684
void QRhiImplementation::runCleanup()
9685
0
{
9686
0
    for (const QRhi::CleanupCallback &f : std::as_const(cleanupCallbacks))
9687
0
        f(q);
9688
9689
0
    cleanupCallbacks.clear();
9690
9691
0
    for (auto it = keyedCleanupCallbacks.cbegin(), end = keyedCleanupCallbacks.cend(); it != end; ++it)
9692
0
        it.value()(q);
9693
9694
0
    keyedCleanupCallbacks.clear();
9695
0
}
9696
9697
/*!
9698
    \class QRhiResourceUpdateBatch
9699
    \inmodule QtGuiPrivate
9700
    \inheaderfile rhi/qrhi.h
9701
    \since 6.6
9702
    \brief Records upload and copy type of operations.
9703
9704
    With QRhi it is no longer possible to perform copy type of operations at
9705
    arbitrary times. Instead, all such operations are recorded into batches
9706
    that are then passed, most commonly, to QRhiCommandBuffer::beginPass().
9707
    What then happens under the hood is hidden from the application: the
9708
    underlying implementations can defer and implement these operations in
9709
    various different ways.
9710
9711
    A resource update batch owns no graphics resources and does not perform any
9712
    actual operations on its own. It should rather be viewed as a command
9713
    buffer for update, upload, and copy type of commands.
9714
9715
    To get an available, empty batch from the pool, call
9716
    QRhi::nextResourceUpdateBatch().
9717
9718
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
9719
    for details.
9720
 */
9721
9722
/*!
9723
    \internal
9724
 */
9725
QRhiResourceUpdateBatch::QRhiResourceUpdateBatch(QRhiImplementation *rhi)
9726
0
    : d(new QRhiResourceUpdateBatchPrivate)
9727
0
{
9728
0
    d->q = this;
9729
0
    d->rhi = rhi;
9730
0
}
9731
9732
QRhiResourceUpdateBatch::~QRhiResourceUpdateBatch()
9733
0
{
9734
0
    delete d;
9735
0
}
9736
9737
/*!
9738
    \return the batch to the pool. This should only be used when the batch is
9739
    not passed to one of QRhiCommandBuffer::beginPass(),
9740
    QRhiCommandBuffer::endPass(), or QRhiCommandBuffer::resourceUpdate()
9741
    because these implicitly call destroy().
9742
9743
    \note QRhiResourceUpdateBatch instances must never by \c deleted by
9744
    applications.
9745
 */
9746
void QRhiResourceUpdateBatch::release()
9747
0
{
9748
0
    d->free();
9749
0
}
9750
9751
/*!
9752
    Copies all queued operations from the \a other batch into this one.
9753
9754
    \note \a other may no longer contain valid data after the merge operation,
9755
    and must not be submitted, but it will still need to be released by calling
9756
    release().
9757
9758
    This allows for a convenient pattern where resource updates that are
9759
    already known during the initialization step are collected into a batch
9760
    that is then merged into another when starting to first render pass later
9761
    on:
9762
9763
    \code
9764
        void init()
9765
        {
9766
            initialUpdates = rhi->nextResourceUpdateBatch();
9767
            initialUpdates->uploadStaticBuffer(vbuf, vertexData);
9768
            initialUpdates->uploadStaticBuffer(ibuf, indexData);
9769
            // ...
9770
        }
9771
9772
        void render()
9773
        {
9774
            QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
9775
            if (initialUpdates) {
9776
                resUpdates->merge(initialUpdates);
9777
                initialUpdates->release();
9778
                initialUpdates = nullptr;
9779
            }
9780
            // resUpdates->updateDynamicBuffer(...);
9781
            cb->beginPass(rt, clearCol, clearDs, resUpdates);
9782
        }
9783
    \endcode
9784
 */
9785
void QRhiResourceUpdateBatch::merge(QRhiResourceUpdateBatch *other)
9786
0
{
9787
0
    d->merge(other->d);
9788
0
}
9789
9790
/*!
9791
    \return true until the number of buffer and texture operations enqueued
9792
    onto this batch is below a reasonable limit.
9793
9794
    The return value is false when the number of buffer and/or texture
9795
    operations added to this batch have reached, or are about to reach, a
9796
    certain limit. The batch is fully functional afterwards as well, but may
9797
    need to allocate additional memory. Therefore, a renderer that collects
9798
    lots of buffer and texture updates in a single batch when preparing a frame
9799
    may want to consider \l{QRhiCommandBuffer::resourceUpdate()}{submitting the
9800
    batch} and \l{QRhi::nextResourceUpdateBatch()}{starting a new one} when
9801
    this function returns false.
9802
 */
9803
bool QRhiResourceUpdateBatch::hasOptimalCapacity() const
9804
0
{
9805
0
    return d->hasOptimalCapacity();
9806
0
}
9807
9808
/*!
9809
    Enqueues updating a region of a QRhiBuffer \a buf created with the type
9810
    QRhiBuffer::Dynamic.
9811
9812
    The region is specified \a offset and \a size. The actual bytes to write
9813
    are specified by \a data which must have at least \a size bytes available.
9814
9815
    \a data is copied and can safely be destroyed or changed once this function
9816
    returns.
9817
9818
    \note If host writes are involved, which is the case with
9819
    updateDynamicBuffer() typically as such buffers are backed by host visible
9820
    memory with most backends, they may accumulate within a frame. Thus pass 1
9821
    reading a region changed by a batch passed to pass 2 may see the changes
9822
    specified in pass 2's update batch.
9823
9824
    \note QRhi transparently manages double buffering in order to prevent
9825
    stalling the graphics pipeline. The fact that a QRhiBuffer may have
9826
    multiple native buffer objects underneath can be safely ignored when using
9827
    the QRhi and QRhiResourceUpdateBatch.
9828
 */
9829
void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
9830
0
{
9831
0
    if (size > 0) {
9832
0
        const int idx = d->activeBufferOpCount++;
9833
0
        const int opListSize = d->bufferOps.size();
9834
0
        if (idx < opListSize)
9835
0
            QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, size, data);
9836
0
        else
9837
0
            d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, size, data));
9838
0
    }
9839
0
}
9840
9841
/*!
9842
    \overload
9843
    \since 6.10
9844
9845
    Enqueues updating a region of a QRhiBuffer \a buf created with the type
9846
    QRhiBuffer::Dynamic.
9847
9848
    \a data is moved into the batch instead of copied with this overload.
9849
 */
9850
void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
9851
0
{
9852
0
    if (!data.isEmpty()) {
9853
0
        const int idx = d->activeBufferOpCount++;
9854
0
        const int opListSize = d->bufferOps.size();
9855
0
        if (idx < opListSize)
9856
0
            QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, std::move(data));
9857
0
        else
9858
0
            d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, std::move(data)));
9859
0
    }
9860
0
}
9861
9862
/*!
9863
    Enqueues updating a region of a QRhiBuffer \a buf created with the type
9864
    QRhiBuffer::Immutable or QRhiBuffer::Static.
9865
9866
    The region is specified \a offset and \a size. The actual bytes to write
9867
    are specified by \a data which must have at least \a size bytes available.
9868
9869
    \a data is copied and can safely be destroyed or changed once this function
9870
    returns.
9871
 */
9872
void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
9873
0
{
9874
0
    if (size > 0) {
9875
0
        const int idx = d->activeBufferOpCount++;
9876
0
        if (idx < d->bufferOps.size())
9877
0
            QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, size, data);
9878
0
        else
9879
0
            d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, size, data));
9880
0
    }
9881
0
}
9882
9883
/*!
9884
    \overload
9885
    \since 6.10
9886
9887
    Enqueues updating a region of a QRhiBuffer \a buf created with the type
9888
    QRhiBuffer::Immutable or QRhiBuffer::Static.
9889
9890
    \a data is moved into the batch instead of copied with this overload.
9891
 */
9892
void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, QByteArray data)
9893
0
{
9894
0
    if (!data.isEmpty()) {
9895
0
        const int idx = d->activeBufferOpCount++;
9896
0
        if (idx < d->bufferOps.size())
9897
0
            QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, std::move(data));
9898
0
        else
9899
0
            d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, std::move(data)));
9900
0
    }
9901
0
}
9902
9903
/*!
9904
    \overload
9905
9906
    Enqueues updating the entire QRhiBuffer \a buf created with the type
9907
    QRhiBuffer::Immutable or QRhiBuffer::Static.
9908
 */
9909
void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *data)
9910
0
{
9911
0
    if (buf->size() > 0) {
9912
0
        const int idx = d->activeBufferOpCount++;
9913
0
        if (idx < d->bufferOps.size())
9914
0
            QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, 0, data);
9915
0
        else
9916
0
            d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, 0, data));
9917
0
    }
9918
0
}
9919
9920
/*!
9921
    \overload
9922
    \since 6.10
9923
9924
    Enqueues updating the entire QRhiBuffer \a buf created with the type
9925
    QRhiBuffer::Immutable or QRhiBuffer::Static.
9926
9927
    \a data is moved into the batch instead of copied with this overload.
9928
9929
    \a data size must equal the size of \a buf.
9930
 */
9931
void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, QByteArray data)
9932
0
{
9933
0
    if (buf->size() > 0 && quint32(data.size()) == buf->size()) {
9934
0
        const int idx = d->activeBufferOpCount++;
9935
0
        if (idx < d->bufferOps.size())
9936
0
            QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, std::move(data));
9937
0
        else
9938
0
            d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, std::move(data)));
9939
0
    }
9940
0
}
9941
9942
/*!
9943
    Enqueues reading back a region of the QRhiBuffer \a buf. The size of the
9944
    region is specified by \a size in bytes, \a offset is the offset in bytes
9945
    to start reading from.
9946
9947
    A readback is asynchronous. \a result contains a callback that is invoked
9948
    when the operation has completed. The data is provided in
9949
    QRhiReadbackResult::data. Upon successful completion that QByteArray
9950
    will have a size equal to \a size. On failure the QByteArray will be empty.
9951
9952
    \note Reading buffers with a usage different than QRhiBuffer::UniformBuffer
9953
    is supported only when the QRhi::ReadBackNonUniformBuffer feature is
9954
    reported as supported.
9955
9956
   \note The asynchronous readback is guaranteed to have completed when one of
9957
   the following conditions is met: \l{QRhi::finish()}{finish()} has been
9958
   called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
9959
   including the frame that issued the readback operation, and the
9960
   \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
9961
   N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
9962
   QRhi::MaxAsyncReadbackFrames.
9963
9964
   \sa readBackTexture(), QRhi::isFeatureSupported(), QRhi::resourceLimit()
9965
 */
9966
void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
9967
0
{
9968
0
    const int idx = d->activeBufferOpCount++;
9969
0
    if (idx < d->bufferOps.size())
9970
0
        d->bufferOps[idx] = QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result);
9971
0
    else
9972
0
        d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result));
9973
0
}
9974
9975
/*!
9976
    Enqueues uploading the image data for one or more mip levels in one or more
9977
    layers of the texture \a tex.
9978
9979
    The details of the copy (source QImage or compressed texture data, regions,
9980
    target layers and levels) are described in \a desc.
9981
 */
9982
void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
9983
0
{
9984
0
    if (desc.cbeginEntries() != desc.cendEntries()) {
9985
0
        const int idx = d->activeTextureOpCount++;
9986
0
        if (idx < d->textureOps.size())
9987
0
            d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc);
9988
0
        else
9989
0
            d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc));
9990
0
    }
9991
0
}
9992
9993
/*!
9994
    Enqueues uploading the image data for mip level 0 of layer 0 of the texture
9995
    \a tex.
9996
9997
    \a tex must have an uncompressed format. Its format must also be compatible
9998
    with the QImage::format() of \a image. The source data is given in \a
9999
    image.
10000
 */
10001
void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &image)
10002
0
{
10003
0
    uploadTexture(tex,
10004
0
                  QRhiTextureUploadEntry(0, 0, QRhiTextureSubresourceUploadDescription(image)));
10005
0
}
10006
10007
/*!
10008
   Enqueues a texture-to-texture copy operation from \a src into \a dst as
10009
   described by \a desc.
10010
10011
   \note The source texture \a src must be created with
10012
   QRhiTexture::UsedAsTransferSource.
10013
10014
   \note The format of the textures must match. With most graphics
10015
   APIs the data is copied as-is without any format conversions. If
10016
   \a dst and \a src are created with different formats, unspecified
10017
   issues may arise.
10018
 */
10019
void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
10020
0
{
10021
0
    const int idx = d->activeTextureOpCount++;
10022
0
    if (idx < d->textureOps.size())
10023
0
        d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc);
10024
0
    else
10025
0
        d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc));
10026
0
}
10027
10028
/*!
10029
   Enqueues a texture-to-host copy operation as described by \a rb.
10030
10031
   Normally \a rb will specify a QRhiTexture as the source. However, when the
10032
   swapchain in the current frame was created with
10033
   QRhiSwapChain::UsedAsTransferSource, it can also be the source of the
10034
   readback. For this, leave the texture set to null in \a rb.
10035
10036
   Unlike other operations, the results here need to be processed by the
10037
   application. Therefore, \a result provides not just the data but also a
10038
   callback as operations on the batch are asynchronous by nature:
10039
10040
   \code
10041
      rhi->beginFrame(swapchain);
10042
      cb->beginPass(swapchain->currentFrameRenderTarget(), colorClear, dsClear);
10043
      // ...
10044
      QRhiReadbackResult *rbResult = new QRhiReadbackResult;
10045
      rbResult->completed = [rbResult] {
10046
          {
10047
              const QImage::Format fmt = QImage::Format_RGBA8888_Premultiplied; // fits QRhiTexture::RGBA8
10048
              const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
10049
              QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
10050
              image.save("result.png");
10051
          }
10052
          delete rbResult;
10053
      };
10054
      QRhiResourceUpdateBatch *u = nextResourceUpdateBatch();
10055
      QRhiReadbackDescription rb; // no texture -> uses the current backbuffer of sc
10056
      u->readBackTexture(rb, rbResult);
10057
      cb->endPass(u);
10058
      rhi->endFrame(swapchain);
10059
   \endcode
10060
10061
   \note The texture must be created with QRhiTexture::UsedAsTransferSource.
10062
10063
   \note Multisample textures cannot be read back.
10064
10065
   \note The readback returns raw byte data, in order to allow the applications
10066
   to interpret it in any way they see fit. Be aware of the blending settings
10067
   of rendering code: if the blending is set up to rely on premultiplied alpha,
10068
   the results of the readback must also be interpreted as Premultiplied.
10069
10070
   \note When interpreting the resulting raw data, be aware that the readback
10071
   happens with a byte ordered format. A \l{QRhiTexture::RGBA8}{RGBA8} texture
10072
   maps therefore to byte ordered QImage formats, such as,
10073
   QImage::Format_RGBA8888.
10074
10075
   \note The asynchronous readback is guaranteed to have completed when one of
10076
   the following conditions is met: \l{QRhi::finish()}{finish()} has been
10077
   called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
10078
   including the frame that issued the readback operation, and the
10079
   \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
10080
   N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
10081
   QRhi::MaxAsyncReadbackFrames.
10082
10083
   A single readback operation copies one mip level of one layer (cubemap face
10084
   or 3D slice or texture array element) at a time. The level and layer are
10085
   specified by the respective fields in \a rb.
10086
10087
   \sa readBackBuffer(), QRhi::resourceLimit()
10088
 */
10089
void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
10090
0
{
10091
0
    const int idx = d->activeTextureOpCount++;
10092
0
    if (idx < d->textureOps.size())
10093
0
        d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result);
10094
0
    else
10095
0
        d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result));
10096
0
}
10097
10098
/*!
10099
   Enqueues a mipmap generation operation for the specified texture \a tex.
10100
10101
   2D and cube textures are supported. 1D and 3D textures are supported when
10102
   the QRhi::OneDimensionalTextureMipmaps or QRhi::ThreeDimensionalTextureMipmaps
10103
   feature is reported as supported, respectively.
10104
10105
   \note The texture must be created with QRhiTexture::MipMapped and
10106
   QRhiTexture::UsedWithGenerateMips.
10107
10108
   \warning QRhi cannot guarantee that mipmaps can be generated for all
10109
   supported texture formats. For example, QRhiTexture::RGBA32F is not a \c
10110
   filterable format in OpenGL ES 3.0 and Metal on iOS, and therefore the
10111
   mipmap generation request may fail. RGBA8 and RGBA16F are typically
10112
   filterable, so it is recommended to use these formats when mipmap generation
10113
   is desired.
10114
 */
10115
void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex)
10116
0
{
10117
0
    const int idx = d->activeTextureOpCount++;
10118
0
    if (idx < d->textureOps.size())
10119
0
        d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex);
10120
0
    else
10121
0
        d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex));
10122
0
}
10123
10124
/*!
10125
   \return an available, empty batch to which copy type of operations can be
10126
   recorded.
10127
10128
   \note the return value is not owned by the caller and must never be
10129
   destroyed. Instead, the batch is returned the pool for reuse by passing
10130
   it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or
10131
   QRhiCommandBuffer::resourceUpdate(), or by calling
10132
   QRhiResourceUpdateBatch::release() on it.
10133
10134
   \note Can be called outside beginFrame() - endFrame() as well since a batch
10135
   instance just collects data on its own, it does not perform any operations.
10136
10137
   Due to not being tied to a frame being recorded, the following sequence is
10138
   valid for example:
10139
10140
   \code
10141
      rhi->beginFrame(swapchain);
10142
      QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
10143
      u->uploadStaticBuffer(buf, data);
10144
      // ... do not commit the batch
10145
      rhi->endFrame();
10146
      // u stays valid (assuming buf stays valid as well)
10147
      rhi->beginFrame(swapchain);
10148
      swapchain->currentFrameCommandBuffer()->resourceUpdate(u);
10149
      // ... draw with buf
10150
      rhi->endFrame();
10151
   \endcode
10152
10153
   \warning The maximum number of batches per QRhi is 64. When this limit is
10154
   reached, the function will return null until a batch is returned to the
10155
   pool.
10156
 */
10157
QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
10158
0
{
10159
    // By default we prefer spreading out the utilization of the worst case 64
10160
    // (but typically 4) batches as much as possible, meaning we won't pick the
10161
    // first one even if it's free, but prefer picking one after the last picked
10162
    // one. Relevant due to implicit sharing (the backend may hold on to the
10163
    // QRhiBufferData until frame no. current+FramesInFlight-1, but
10164
    // implementations may vary), combined with the desire to reuse container
10165
    // and QRhiBufferData allocations in bufferOps instead of flooding every
10166
    // frame with allocs. See free(). In typical Qt Quick scenes this leads to
10167
    // eventually seeding all 4 (or more) resource batches with buffer operation
10168
    // data allocations which may (*) then be reused in subsequent frames. This
10169
    // comes at the expense of using more memory, but has proven good results
10170
    // when (CPU) profiling typical Quick/Quick3D apps.
10171
    //
10172
    // (*) Due to implicit sharing(ish), the exact behavior is unpredictable. If
10173
    // a backend holds on to the QRhiBufferData for, e.g., a dynamic buffer
10174
    // update, and then there is a new assign() for that same QRhiBufferData
10175
    // while the refcount is still 2, it will "detach" (without contents) and
10176
    // there is no reuse of the alloc. This is mitigated by the 'choose the one
10177
    // afer the last picked one' logic when handing out batches.
10178
10179
0
    auto nextFreeBatch = [this]() -> QRhiResourceUpdateBatch * {
10180
0
        auto isFree = [this](int i) -> QRhiResourceUpdateBatch * {
10181
0
            const quint64 mask = 1ULL << quint64(i);
10182
0
            if (!(d->resUpdPoolMap & mask)) {
10183
0
                d->resUpdPoolMap |= mask;
10184
0
                QRhiResourceUpdateBatch *u = d->resUpdPool[i];
10185
0
                QRhiResourceUpdateBatchPrivate::get(u)->poolIndex = i;
10186
0
                d->lastResUpdIdx = i;
10187
0
                return u;
10188
0
            }
10189
0
            return nullptr;
10190
0
        };
10191
0
        const int poolSize = d->resUpdPool.size();
10192
0
        for (int i = d->lastResUpdIdx + 1; i < poolSize; ++i) {
10193
0
            if (QRhiResourceUpdateBatch *u = isFree(i))
10194
0
                return u;
10195
0
        }
10196
0
        for (int i = 0; i <= d->lastResUpdIdx; ++i) {
10197
0
            if (QRhiResourceUpdateBatch *u = isFree(i))
10198
0
                return u;
10199
0
        }
10200
0
        return nullptr;
10201
0
    };
10202
10203
0
    QRhiResourceUpdateBatch *u = nextFreeBatch();
10204
0
    if (!u) {
10205
0
        const int oldSize = d->resUpdPool.size();
10206
        // 4, 8, 12, ..., up to 64
10207
0
        const int newSize = oldSize + qMin(4, qMax(0, 64 - oldSize));
10208
0
        d->resUpdPool.resize(newSize);
10209
0
        for (int i = oldSize; i < newSize; ++i)
10210
0
            d->resUpdPool[i] = new QRhiResourceUpdateBatch(d);
10211
0
        u = nextFreeBatch();
10212
0
        if (!u)
10213
0
            qWarning("Resource update batch pool exhausted (max is 64)");
10214
0
    }
10215
10216
0
    return u;
10217
0
}
10218
10219
void QRhiResourceUpdateBatchPrivate::free()
10220
0
{
10221
0
    Q_ASSERT(poolIndex >= 0 && rhi->resUpdPool[poolIndex] == q);
10222
10223
0
    quint32 bufferDataTotal = 0;
10224
0
    quint32 bufferLargeAllocTotal = 0;
10225
0
    for (const BufferOp &op : std::as_const(bufferOps)) {
10226
0
        bufferDataTotal += op.data.size();
10227
0
        bufferLargeAllocTotal += op.data.largeAlloc(); // alloc when > 1 KB
10228
0
    }
10229
10230
0
    if (QRHI_LOG_RUB().isDebugEnabled()) {
10231
0
        qDebug() << "[rub] release to pool upd.batch #" << poolIndex
10232
0
                << "/ bufferOps active" << activeBufferOpCount
10233
0
                << "of" << bufferOps.count()
10234
0
                << "data" << bufferDataTotal
10235
0
                << "largeAlloc" << bufferLargeAllocTotal
10236
0
                << "textureOps active" << activeTextureOpCount
10237
0
                << "of" << textureOps.count();
10238
0
    }
10239
10240
0
    activeBufferOpCount = 0;
10241
0
    activeTextureOpCount = 0;
10242
10243
0
    const quint64 mask = 1ULL << quint64(poolIndex);
10244
0
    rhi->resUpdPoolMap &= ~mask;
10245
0
    poolIndex = -1;
10246
10247
    // textureOps is cleared, to not keep the potentially large image pixel
10248
    // data alive, but it is expected that the container keeps the list alloc
10249
    // at least. Only trimOpList() goes for the more aggressive route with squeeze.
10250
0
    textureOps.clear();
10251
10252
    // bufferOps is not touched in many cases, to allow reusing allocations
10253
    // (incl. in the elements' QRhiBufferData) as much as possible when this
10254
    // batch is used again in the future, which is important for performance, in
10255
    // particular with Qt Quick where it is easy for scenes to produce lots of,
10256
    // typically small buffer changes on every frame.
10257
    //
10258
    // However, ensure that even in the unlikely case of having the max number
10259
    // of batches (64) created in resUpdPool, no more than 64 MB in total is
10260
    // used up by buffer data just to help future reuse. For simplicity, if
10261
    // there is more than 1 MB data -> clear. Applications with frequent, huge
10262
    // buffer updates probably have other bottlenecks anyway.
10263
0
    if (bufferLargeAllocTotal > 1024 * 1024)
10264
0
        bufferOps.clear();
10265
0
}
10266
10267
void QRhiResourceUpdateBatchPrivate::merge(QRhiResourceUpdateBatchPrivate *other)
10268
0
{
10269
0
    int combinedSize = activeBufferOpCount + other->activeBufferOpCount;
10270
0
    if (bufferOps.size() < combinedSize)
10271
0
        bufferOps.resize(combinedSize);
10272
0
    for (int i = activeBufferOpCount; i < combinedSize; ++i)
10273
0
        bufferOps[i] = std::move(other->bufferOps[i - activeBufferOpCount]);
10274
0
    activeBufferOpCount += other->activeBufferOpCount;
10275
10276
0
    combinedSize = activeTextureOpCount + other->activeTextureOpCount;
10277
0
    if (textureOps.size() < combinedSize)
10278
0
        textureOps.resize(combinedSize);
10279
0
    for (int i = activeTextureOpCount; i < combinedSize; ++i)
10280
0
        textureOps[i] = std::move(other->textureOps[i - activeTextureOpCount]);
10281
0
    activeTextureOpCount += other->activeTextureOpCount;
10282
0
}
10283
10284
bool QRhiResourceUpdateBatchPrivate::hasOptimalCapacity() const
10285
0
{
10286
0
    return activeBufferOpCount < BUFFER_OPS_STATIC_ALLOC - 4
10287
0
            && activeTextureOpCount < TEXTURE_OPS_STATIC_ALLOC - 4;
10288
0
}
10289
10290
void QRhiResourceUpdateBatchPrivate::trimOpLists()
10291
0
{
10292
    // Unlike free(), this is expected to aggressively deallocate all memory
10293
    // used by both the buffer and texture operation lists. (i.e. using
10294
    // squeeze() to only keep the stack prealloc of the QVLAs)
10295
    //
10296
    // This (e.g. just the destruction of bufferOps elements) may have a
10297
    // non-negligible performance impact e.g. with Qt Quick with scenes where
10298
    // there are lots of buffer operations per frame.
10299
10300
0
    activeBufferOpCount = 0;
10301
0
    bufferOps.clear();
10302
0
    bufferOps.squeeze();
10303
10304
0
    activeTextureOpCount = 0;
10305
0
    textureOps.clear();
10306
0
    textureOps.squeeze();
10307
0
}
10308
10309
/*!
10310
    Sometimes committing resource updates is necessary or just more convenient
10311
    without starting a render pass. Calling this function with \a
10312
    resourceUpdates is an alternative to passing \a resourceUpdates to a
10313
    beginPass() call (or endPass(), which would be typical in case of readbacks).
10314
10315
    \note Cannot be called inside a pass.
10316
 */
10317
void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
10318
0
{
10319
0
    if (resourceUpdates)
10320
0
        m_rhi->resourceUpdate(this, resourceUpdates);
10321
0
}
10322
10323
/*!
10324
    Records starting a new render pass targeting the render target \a rt.
10325
10326
    \a resourceUpdates, when not null, specifies a resource update batch that
10327
    is to be committed and then released.
10328
10329
    The color and depth/stencil buffers of the render target are normally
10330
    cleared. The clear values are specified in \a colorClearValue and \a
10331
    depthStencilClearValue. The exception is when the render target was created
10332
    with QRhiTextureRenderTarget::PreserveColorContents and/or
10333
    QRhiTextureRenderTarget::PreserveDepthStencilContents. The clear values are
10334
    ignored then.
10335
10336
    \note Enabling preserved color or depth contents leads to decreased
10337
    performance depending on the underlying hardware. Mobile GPUs with tiled
10338
    architecture benefit from not having to reload the previous contents into
10339
    the tile buffer. Similarly, a QRhiTextureRenderTarget with a QRhiTexture as
10340
    the depth buffer is less efficient than a QRhiRenderBuffer since using a
10341
    depth texture triggers requiring writing the data out to it, while with
10342
    renderbuffers this is not needed (as the API does not allow sampling or
10343
    reading from a renderbuffer).
10344
10345
    \note Do not assume that any state or resource bindings persist between
10346
    passes.
10347
10348
    \note The QRhiCommandBuffer's \c set and \c draw functions can only be
10349
    called inside a pass. Also, with the exception of setGraphicsPipeline(),
10350
    they expect to have a pipeline set already on the command buffer.
10351
    Unspecified issues may arise otherwise, depending on the backend.
10352
10353
    If \a rt is a QRhiTextureRenderTarget, beginPass() performs a check to see
10354
    if the texture and renderbuffer objects referenced from the render target
10355
    are up-to-date. This is similar to what setShaderResources() does for
10356
    QRhiShaderResourceBindings. If any of the attachments had been rebuilt
10357
    since QRhiTextureRenderTarget::create(), an implicit call to create() is
10358
    made on \a rt. Therefore, if \a rt has a QRhiTexture color attachment \c
10359
    texture, and one needs to make the texture a different size, the following
10360
    is then valid:
10361
    \code
10362
      QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ { texture } });
10363
      rt->create();
10364
      // ...
10365
      texture->setPixelSize(new_size);
10366
      texture->create();
10367
      cb->beginPass(rt, colorClear, dsClear); // this is ok, no explicit rt->create() is required before
10368
    \endcode
10369
10370
    \a flags allow controlling certain advanced functionality. One commonly used
10371
    flag is \c ExternalContents. This should be specified whenever
10372
    beginExternal() will be called within the pass started by this function.
10373
10374
    \sa endPass(), BeginPassFlags
10375
 */
10376
void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
10377
                                  const QColor &colorClearValue,
10378
                                  const QRhiDepthStencilClearValue &depthStencilClearValue,
10379
                                  QRhiResourceUpdateBatch *resourceUpdates,
10380
                                  BeginPassFlags flags)
10381
0
{
10382
0
    m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates, flags);
10383
0
}
10384
10385
/*!
10386
    Records ending the current render pass.
10387
10388
    \a resourceUpdates, when not null, specifies a resource update batch that
10389
    is to be committed and then released.
10390
10391
    \sa beginPass()
10392
 */
10393
void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates)
10394
0
{
10395
0
    m_rhi->endPass(this, resourceUpdates);
10396
0
}
10397
10398
/*!
10399
    Records setting a new graphics pipeline \a ps.
10400
10401
    \note This function must be called before recording other \c set or \c draw
10402
    commands on the command buffer.
10403
10404
    \note QRhi will optimize out unnecessary invocations within a pass, so
10405
    therefore overoptimizing to avoid calls to this function is not necessary
10406
    on the applications' side.
10407
10408
    \note This function can only be called inside a render pass, meaning
10409
    between a beginPass() and endPass() call.
10410
10411
    \note The new graphics pipeline \a ps must be a valid pointer.
10412
10413
    Setting a graphics pipeline that does not have the
10414
    \l{QRhiGraphicsPipeline::}{UsesScissor} flag will either disable scissoring,
10415
    with graphics APIs where that is applicable, or set the scissor rectangle to
10416
    match the viewport that was last set (with graphics APIs where scissoring is
10417
    effectively always active), in order to ensure a uniform behavior across QRhi
10418
    backends.
10419
 */
10420
void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)
10421
0
{
10422
0
    Q_ASSERT(ps != nullptr);
10423
0
    m_rhi->setGraphicsPipeline(this, ps);
10424
0
}
10425
10426
/*!
10427
    Records binding a set of shader resources, such as, uniform buffers or
10428
    textures, that are made visible to one or more shader stages.
10429
10430
    \a srb can be null in which case the current graphics or compute pipeline's
10431
    associated QRhiShaderResourceBindings is used. When \a srb is non-null, it
10432
    must be
10433
    \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible},
10434
    meaning the layout (number of bindings, the type and binding number of each
10435
    binding) must fully match the QRhiShaderResourceBindings that was
10436
    associated with the pipeline at the time of calling the pipeline's create().
10437
10438
    There are cases when a seemingly unnecessary setShaderResources() call is
10439
    mandatory: when rebuilding a resource referenced from \a srb, for example
10440
    changing the size of a QRhiBuffer followed by a QRhiBuffer::create(), this
10441
    is the place where associated native objects (such as descriptor sets in
10442
    case of Vulkan) are updated to refer to the current native resources that
10443
    back the QRhiBuffer, QRhiTexture, QRhiSampler objects referenced from \a
10444
    srb. In this case setShaderResources() must be called even if \a srb is
10445
    the same as in the last call.
10446
10447
    When \a srb is not null, the QRhiShaderResourceBindings object the pipeline
10448
    was built with in create() is guaranteed to be not accessed in any form. In
10449
    fact, it does not need to be valid even at this point: destroying the
10450
    pipeline's associated srb after create() and instead explicitly specifying
10451
    another, \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout
10452
    compatible} one in every setShaderResources() call is valid.
10453
10454
    \a dynamicOffsets allows specifying buffer offsets for uniform buffers that
10455
    were associated with \a srb via
10456
    QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(). This is
10457
    different from providing the offset in the \a srb itself: dynamic offsets
10458
    do not require building a new QRhiShaderResourceBindings for every
10459
    different offset, can avoid writing the underlying descriptors (with
10460
    backends where applicable), and so they may be more efficient. Each element
10461
    of \a dynamicOffsets is a \c binding - \c offset pair.
10462
    \a dynamicOffsetCount specifies the number of elements in \a dynamicOffsets.
10463
10464
    \note All offsets in \a dynamicOffsets must be byte aligned to the value
10465
    returned from QRhi::ubufAlignment().
10466
10467
    \note Some backends may limit the number of supported dynamic offsets.
10468
    Avoid using a \a dynamicOffsetCount larger than 8.
10469
10470
    \note QRhi will optimize out unnecessary invocations within a pass (taking
10471
    the conditions described above into account), so therefore overoptimizing
10472
    to avoid calls to this function is not necessary on the applications' side.
10473
10474
    \note This function can only be called inside a render or compute pass,
10475
    meaning between a beginPass() and endPass(), or beginComputePass() and
10476
    endComputePass().
10477
 */
10478
void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb,
10479
                                           int dynamicOffsetCount,
10480
                                           const DynamicOffset *dynamicOffsets)
10481
0
{
10482
0
    m_rhi->setShaderResources(this, srb, dynamicOffsetCount, dynamicOffsets);
10483
0
}
10484
10485
/*!
10486
    Records vertex input bindings.
10487
10488
    The index buffer used by subsequent drawIndexed() commands is specified by
10489
    \a indexBuf, \a indexOffset, and \a indexFormat. \a indexBuf can be set to
10490
    null when indexed drawing is not needed.
10491
10492
    Vertex buffer bindings are batched. \a startBinding specifies the first
10493
    binding number. The recorded command then binds each buffer from \a
10494
    bindings to the binding point \c{startBinding + i} where \c i is the index
10495
    in \a bindings. Each element in \a bindings specifies a QRhiBuffer and an
10496
    offset.
10497
10498
    \note Some backends may limit the number of vertex buffer bindings. Avoid
10499
    using a \a bindingCount larger than 8.
10500
10501
    Superfluous vertex input and index changes in the same pass are ignored
10502
    automatically with most backends and therefore applications do not need to
10503
    overoptimize to avoid calls to this function.
10504
10505
    \note This function can only be called inside a render pass, meaning
10506
    between a beginPass() and endPass() call.
10507
10508
    As a simple example, take a vertex shader with two inputs:
10509
10510
    \badcode
10511
        layout(location = 0) in vec4 position;
10512
        layout(location = 1) in vec3 color;
10513
    \endcode
10514
10515
    and assume we have the data available in interleaved format, using only 2
10516
    floats for position (so 5 floats per vertex: x, y, r, g, b). A QRhiGraphicsPipeline for
10517
    this shader can then be created using the input layout:
10518
10519
    \code
10520
        QRhiVertexInputLayout inputLayout;
10521
        inputLayout.setBindings({
10522
            { 5 * sizeof(float) }
10523
        });
10524
        inputLayout.setAttributes({
10525
            { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
10526
            { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
10527
        });
10528
    \endcode
10529
10530
    Here there is one buffer binding (binding number 0), with two inputs
10531
    referencing it. When recording the pass, once the pipeline is set, the
10532
    vertex bindings can be specified simply like the following, assuming vbuf
10533
    is the QRhiBuffer with all the interleaved position+color data:
10534
10535
    \code
10536
        const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
10537
        cb->setVertexInput(0, 1, &vbufBinding);
10538
    \endcode
10539
 */
10540
void QRhiCommandBuffer::setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
10541
                                       QRhiBuffer *indexBuf, quint32 indexOffset,
10542
                                       IndexFormat indexFormat)
10543
0
{
10544
0
    m_rhi->setVertexInput(this, startBinding, bindingCount, bindings, indexBuf, indexOffset, indexFormat);
10545
0
}
10546
10547
/*!
10548
    Records setting the active viewport rectangle specified in \a viewport.
10549
10550
    With backends where the underlying graphics API has scissoring always
10551
    enabled, this function also sets the scissor to match the viewport whenever
10552
    the active QRhiGraphicsPipeline does not have
10553
    \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set.
10554
10555
    \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
10556
    bottom-left.
10557
10558
    \note This function can only be called inside a render pass, meaning
10559
    between a beginPass() and endPass() call.
10560
 */
10561
void QRhiCommandBuffer::setViewport(const QRhiViewport &viewport)
10562
0
{
10563
0
    m_rhi->setViewport(this, viewport);
10564
0
}
10565
10566
/*!
10567
    Records setting the active scissor rectangle specified in \a scissor.
10568
10569
    This can only be called when the bound pipeline has
10570
    \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set. When the flag is
10571
    set on the active pipeline, this function must be called because scissor
10572
    testing will get enabled and so a scissor rectangle must be provided.
10573
10574
    \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
10575
    bottom-left.
10576
10577
    \note This function can only be called inside a render pass, meaning
10578
    between a beginPass() and endPass() call.
10579
 */
10580
void QRhiCommandBuffer::setScissor(const QRhiScissor &scissor)
10581
0
{
10582
0
    m_rhi->setScissor(this, scissor);
10583
0
}
10584
10585
/*!
10586
    Records setting the active blend constants to \a c.
10587
10588
    This can only be called when the bound pipeline has
10589
    QRhiGraphicsPipeline::UsesBlendConstants set.
10590
10591
    \note This function can only be called inside a render pass, meaning
10592
    between a beginPass() and endPass() call.
10593
 */
10594
void QRhiCommandBuffer::setBlendConstants(const QColor &c)
10595
0
{
10596
0
    m_rhi->setBlendConstants(this, c);
10597
0
}
10598
10599
/*!
10600
    Records setting the active stencil reference value to \a refValue.
10601
10602
    This can only be called when the bound pipeline has
10603
    QRhiGraphicsPipeline::UsesStencilRef set.
10604
10605
    \note This function can only be called inside a render pass, meaning between
10606
    a beginPass() and endPass() call.
10607
 */
10608
void QRhiCommandBuffer::setStencilRef(quint32 refValue)
10609
0
{
10610
0
    m_rhi->setStencilRef(this, refValue);
10611
0
}
10612
10613
/*!
10614
    Sets the shading rate for the following draw calls to \a coarsePixelSize.
10615
10616
    The default is 1x1.
10617
10618
    Functional only when the \l QRhi::VariableRateShading feature is reported as
10619
    supported and the QRhiGraphicsPipeline(s) bound on the command buffer were
10620
    declaring \l QRhiGraphicsPipeline::UsesShadingRate when creating them.
10621
10622
    Call \l QRhi::supportedShadingRates() to check what shading rates are
10623
    supported for a given sample count.
10624
10625
    When both a QRhiShadingRateMap and this function are in use, the higher of
10626
    the two shading rates is used for each tile. There is currently no control
10627
    offered over the combiner behavior.
10628
10629
    \since 6.9
10630
 */
10631
void QRhiCommandBuffer::setShadingRate(const QSize &coarsePixelSize)
10632
0
{
10633
0
    m_rhi->setShadingRate(this, coarsePixelSize);
10634
0
}
10635
10636
/*!
10637
    Records a non-indexed draw.
10638
10639
    The number of vertices is specified in \a vertexCount. For instanced
10640
    drawing set \a instanceCount to a value other than 1. \a firstVertex is the
10641
    index of the first vertex to draw. When drawing multiple instances, the
10642
    first instance ID is specified by \a firstInstance.
10643
10644
    \note \a firstInstance may not be supported, and is ignored when the
10645
    QRhi::BaseInstance feature is reported as not supported. The first instance
10646
    ID is always 0 in that case. QRhi::BaseInstance is never supported with
10647
    OpenGL at the moment, mainly due to OpenGL ES limitations, and therefore
10648
    portable applications should not be designed to rely on this argument.
10649
10650
    \note Shaders that need to access the index of the current vertex or
10651
    instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
10652
    Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
10653
    gl_InstanceID.
10654
10655
    \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
10656
    include the base value with some of the underlying 3D APIs. This is
10657
    indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
10658
    on a base instance value cannot be avoided, applications are advised to pass
10659
    in the value as a uniform conditionally based on what that feature reports,
10660
    and add it to \c gl_InstanceIndex in the shader.
10661
10662
    \note This function can only be called inside a render pass, meaning
10663
    between a beginPass() and endPass() call.
10664
 */
10665
void QRhiCommandBuffer::draw(quint32 vertexCount,
10666
                             quint32 instanceCount,
10667
                             quint32 firstVertex,
10668
                             quint32 firstInstance)
10669
0
{
10670
0
    m_rhi->draw(this, vertexCount, instanceCount, firstVertex, firstInstance);
10671
0
}
10672
10673
/*!
10674
    Records an indexed draw.
10675
10676
    The number of vertices is specified in \a indexCount. \a firstIndex is the
10677
    base index. The effective offset in the index buffer is given by
10678
    \c{indexOffset + firstIndex * n} where \c n is 2 or 4 depending on the
10679
    index element type. \c indexOffset is specified in setVertexInput().
10680
10681
    \note The effective offset in the index buffer must be 4 byte aligned with
10682
    some backends (for example, Metal). With these backends the
10683
    \l{QRhi::NonFourAlignedEffectiveIndexBufferOffset}{NonFourAlignedEffectiveIndexBufferOffset}
10684
    feature will be reported as not-supported.
10685
10686
    \a vertexOffset (also called \c{base vertex}) is a signed value that is
10687
    added to the element index before indexing into the vertex buffer. Support
10688
    for this is not always available, and the value is ignored when the feature
10689
    QRhi::BaseVertex is reported as unsupported.
10690
10691
    For instanced drawing set \a instanceCount to a value other than 1. When
10692
    drawing multiple instances, the first instance ID is specified by \a
10693
    firstInstance.
10694
10695
    \note \a firstInstance may not be supported, and is ignored when the
10696
    QRhi::BaseInstance feature is reported as not supported. The first instance
10697
    ID is always 0 in that case. QRhi::BaseInstance is never supported with
10698
    OpenGL at the moment, mainly due to OpenGL ES limitations, and therefore
10699
    portable applications should not be designed to rely on this argument.
10700
10701
    \note Shaders that need to access the index of the current vertex or
10702
    instance must use \c gl_VertexIndex and \c gl_InstanceIndex, i.e., the
10703
    Vulkan-compatible built-in variables, instead of \c gl_VertexID and \c
10704
    gl_InstanceID.
10705
10706
    \note When \a firstInstance is non-zero, \c gl_InstanceIndex will not
10707
    include the base value with some of the underlying 3D APIs. This is
10708
    indicated by the QRhi::InstanceIndexIncludesBaseInstance feature. If relying
10709
    on a base instance value cannot be avoided, applications are advised to pass
10710
    in the value as a uniform conditionally based on what that feature reports,
10711
    and add it to \c gl_InstanceIndex in the shader.
10712
10713
    \note This function can only be called inside a render pass, meaning
10714
    between a beginPass() and endPass() call.
10715
 */
10716
void QRhiCommandBuffer::drawIndexed(quint32 indexCount,
10717
                                    quint32 instanceCount,
10718
                                    quint32 firstIndex,
10719
                                    qint32 vertexOffset,
10720
                                    quint32 firstInstance)
10721
0
{
10722
0
    m_rhi->drawIndexed(this, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
10723
0
}
10724
10725
/*!
10726
    Records a non-indexed, indirect draw.
10727
10728
    The draw parameters are provided by the buffer specified in \a indirectBuffer,
10729
    which must contain an array of elements of type QRhiIndirectDrawCommand.
10730
    The parameters in QRhiIndirectDrawCommand have the same meaning as in draw().
10731
10732
    The offset, in bytes, from which the parameters are read in the buffer is specified
10733
    by \a indirectBufferOffset.
10734
10735
    \a drawCount specifies the number of such draw commands to issue.
10736
10737
    \a stride indicates the byte size of each individual draw command structure
10738
    in the buffer. This allows interleaving custom data between commands if needed.
10739
    The value must be a multiple of 4 and greater than or equal to sizeof(QRhiIndirectDrawCommand).
10740
10741
    \note A \a drawCount value greater than 1 is only natively supported if the
10742
    QRhi::DrawIndirectMulti feature is reported as supported and stride is the default.
10743
    Otherwise, this function emulates multi-draw by recording multiple draw calls,
10744
    offering no performance benefit over repeated draw() calls.
10745
10746
    \note This function can only be called inside a render pass, meaning
10747
    between a beginPass() and endPass() call.
10748
10749
    \since 6.12
10750
 */
10751
void QRhiCommandBuffer::drawIndirect(QRhiBuffer *indirectBuffer,
10752
                                     quint32 indirectBufferOffset,
10753
                                     quint32 drawCount,
10754
                                     quint32 stride)
10755
0
{
10756
0
    Q_ASSERT(indirectBuffer);
10757
0
    Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
10758
0
    Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
10759
0
    Q_ASSERT(stride >= sizeof(QRhiIndirectDrawCommand));
10760
0
    Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
10761
0
    m_rhi->drawIndirect(this, indirectBuffer, indirectBufferOffset, drawCount, stride);
10762
0
}
10763
10764
/*!
10765
    Records an indexed, indirect draw.
10766
10767
    The draw parameters are provided by the buffer specified in \a indirectBuffer,
10768
    which must contain an array of elements of type QRhiIndexedIndirectDrawCommand.
10769
    The parameters in QRhiIndexedIndirectDrawCommand have the same meaning as in drawIndexed().
10770
10771
    The offset, in bytes, from which the parameters are read in the buffer is specified
10772
    by \a indirectBufferOffset.
10773
10774
    \a drawCount specifies the number of such draw commands to issue.
10775
10776
    \a stride indicates the byte size of each individual draw command structure
10777
    in the buffer. This allows interleaving custom data between commands if needed.
10778
    The value must be a multiple of 4 and greater than or equal to sizeof(QRhiIndexedIndirectDrawCommand).
10779
10780
    \note A \a drawCount value greater than 1 is only natively supported if the
10781
    QRhi::DrawIndirectMulti feature is reported as supported and stride is the default.
10782
    Otherwise, this function emulates multi-draw by recording multiple draw calls,
10783
    offering no performance benefit over repeated drawIndexed() calls.
10784
10785
    \note This function can only be called inside a render pass, meaning
10786
    between a beginPass() and endPass() call.
10787
10788
    \since 6.12
10789
 */
10790
void QRhiCommandBuffer::drawIndexedIndirect(QRhiBuffer *indirectBuffer,
10791
                                            quint32 indirectBufferOffset,
10792
                                            quint32 drawCount,
10793
                                            quint32 stride)
10794
0
{
10795
0
    Q_ASSERT(indirectBuffer);
10796
0
    Q_ASSERT(indirectBuffer->usage().testFlag(QRhiBuffer::IndirectBuffer));
10797
0
    Q_ASSERT_X((indirectBufferOffset & 3u) == 0u, Q_FUNC_INFO, "indirectBufferOffset must be a multiple of 4");
10798
0
    Q_ASSERT(stride >= sizeof(QRhiIndexedIndirectDrawCommand));
10799
0
    Q_ASSERT_X((stride & 3u) == 0u, Q_FUNC_INFO, "stride must be a multiple of 4");
10800
0
    m_rhi->drawIndexedIndirect(this, indirectBuffer, indirectBufferOffset, drawCount, stride);
10801
0
}
10802
10803
/*!
10804
    Records a named debug group on the command buffer with the specified \a
10805
    name. This is shown in graphics debugging tools such as
10806
    \l{https://renderdoc.org/}{RenderDoc} and
10807
    \l{https://developer.apple.com/xcode/}{XCode}. The end of the grouping is
10808
    indicated by debugMarkEnd().
10809
10810
    \note Ignored when QRhi::DebugMarkers are not supported or
10811
    QRhi::EnableDebugMarkers is not set.
10812
10813
    \note Can be called anywhere within the frame, both inside and outside of passes.
10814
 */
10815
void QRhiCommandBuffer::debugMarkBegin(const QByteArray &name)
10816
0
{
10817
0
    m_rhi->debugMarkBegin(this, name);
10818
0
}
10819
10820
/*!
10821
    Records the end of a debug group.
10822
10823
    \note Ignored when QRhi::DebugMarkers are not supported or
10824
    QRhi::EnableDebugMarkers is not set.
10825
10826
    \note Can be called anywhere within the frame, both inside and outside of passes.
10827
 */
10828
void QRhiCommandBuffer::debugMarkEnd()
10829
0
{
10830
0
    m_rhi->debugMarkEnd(this);
10831
0
}
10832
10833
/*!
10834
    Inserts a debug message \a msg into the command stream.
10835
10836
    \note Ignored when QRhi::DebugMarkers are not supported or
10837
    QRhi::EnableDebugMarkers is not set.
10838
10839
    \note With some backends debugMarkMsg() is only supported inside a pass and
10840
    is ignored when called outside a pass. With others it is recorded anywhere
10841
    within the frame.
10842
 */
10843
void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)
10844
0
{
10845
0
    m_rhi->debugMarkMsg(this, msg);
10846
0
}
10847
10848
/*!
10849
    Records starting a new compute pass.
10850
10851
    \a resourceUpdates, when not null, specifies a resource update batch that
10852
    is to be committed and then released.
10853
10854
    \note Do not assume that any state or resource bindings persist between
10855
    passes.
10856
10857
    \note A compute pass can record setComputePipeline(), setShaderResources(),
10858
    and dispatch() calls, not graphics ones. General functionality, such as,
10859
    debug markers and beginExternal() is available both in render and compute
10860
    passes.
10861
10862
    \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
10863
    is reported as supported.
10864
10865
    \a flags is not currently used.
10866
 */
10867
void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates, BeginPassFlags flags)
10868
0
{
10869
0
    m_rhi->beginComputePass(this, resourceUpdates, flags);
10870
0
}
10871
10872
/*!
10873
    Records ending the current compute pass.
10874
10875
    \a resourceUpdates, when not null, specifies a resource update batch that
10876
    is to be committed and then released.
10877
 */
10878
void QRhiCommandBuffer::endComputePass(QRhiResourceUpdateBatch *resourceUpdates)
10879
0
{
10880
0
    m_rhi->endComputePass(this, resourceUpdates);
10881
0
}
10882
10883
/*!
10884
    Records setting a new compute pipeline \a ps.
10885
10886
    \note This function must be called before recording setShaderResources() or
10887
    dispatch() commands on the command buffer.
10888
10889
    \note QRhi will optimize out unnecessary invocations within a pass, so
10890
    therefore overoptimizing to avoid calls to this function is not necessary
10891
    on the applications' side.
10892
10893
    \note This function can only be called inside a compute pass, meaning
10894
    between a beginComputePass() and endComputePass() call.
10895
 */
10896
void QRhiCommandBuffer::setComputePipeline(QRhiComputePipeline *ps)
10897
0
{
10898
0
    m_rhi->setComputePipeline(this, ps);
10899
0
}
10900
10901
/*!
10902
    Records dispatching compute work items, with \a x, \a y, and \a z
10903
    specifying the number of local workgroups in the corresponding dimension.
10904
10905
    \note This function can only be called inside a compute pass, meaning
10906
    between a beginComputePass() and endComputePass() call.
10907
10908
    \note \a x, \a y, and \a z must fit the limits from the underlying graphics
10909
    API implementation at run time. The maximum values are typically 65535.
10910
10911
    \note Watch out for possible limits on the local workgroup size as well.
10912
    This is specified in the shader, for example: \c{layout(local_size_x = 16,
10913
    local_size_y = 16) in;}. For example, with OpenGL the minimum value mandated
10914
    by the specification for the number of invocations in a single local work
10915
    group (the product of \c local_size_x, \c local_size_y, and \c local_size_z)
10916
    is 1024, while with OpenGL ES (3.1) the value may be as low as 128. This
10917
    means that the example given above may be rejected by some OpenGL ES
10918
    implementations as the number of invocations is 256.
10919
 */
10920
void QRhiCommandBuffer::dispatch(int x, int y, int z)
10921
0
{
10922
0
    m_rhi->dispatch(this, x, y, z);
10923
0
}
10924
10925
/*!
10926
    \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
10927
    QRhiVulkanCommandBufferNativeHandles. The returned value is \nullptr when
10928
    exposing the underlying native resources is not supported by, or not
10929
    applicable to, the backend.
10930
10931
    \sa QRhiVulkanCommandBufferNativeHandles,
10932
    QRhiMetalCommandBufferNativeHandles, beginExternal(), endExternal()
10933
 */
10934
const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
10935
0
{
10936
0
    return m_rhi->nativeHandles(this);
10937
0
}
10938
10939
/*!
10940
    To be called when the application before the application is about to
10941
    enqueue commands to the current pass' command buffer by calling graphics
10942
    API functions directly.
10943
10944
    \note This is only available when the intent was declared upfront in
10945
    beginPass() or beginComputePass(). Therefore this function must only be
10946
    called when the pass recording was started with specifying
10947
    QRhiCommandBuffer::ExternalContent.
10948
10949
    With Vulkan, Metal, or Direct3D 12 one can query the native command buffer
10950
    or encoder objects via nativeHandles() and enqueue commands to them. With
10951
    OpenGL or Direct3D 11 the (device) context can be retrieved from
10952
    QRhi::nativeHandles(). However, this must never be done without ensuring
10953
    the QRhiCommandBuffer's state stays up-to-date. Hence the requirement for
10954
    wrapping any externally added command recording between beginExternal() and
10955
    endExternal(). Conceptually this is the same as QPainter's
10956
    \l{QPainter::beginNativePainting()}{beginNativePainting()} and
10957
    \l{QPainter::endNativePainting()}{endNativePainting()} functions.
10958
10959
    For OpenGL in particular, this function has an additional task: it makes
10960
    sure the context is made current on the current thread.
10961
10962
    \note Once beginExternal() is called, no other render pass specific
10963
    functions (\c set* or \c draw*) must be called on the
10964
    QRhiCommandBuffer until endExternal().
10965
10966
    \warning Some backends may return a native command buffer object from
10967
    QRhiCommandBuffer::nativeHandles() that is different from the primary one
10968
    when inside a beginExternal() - endExternal() block. Therefore it is
10969
    important to (re)query the native command buffer object after calling
10970
    beginExternal(). In practical terms this means that with Vulkan for example
10971
    the externally recorded Vulkan commands are placed onto a secondary command
10972
    buffer (with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT).
10973
    nativeHandles() returns this secondary command buffer when called between
10974
    begin/endExternal.
10975
10976
    \sa endExternal(), nativeHandles()
10977
 */
10978
void QRhiCommandBuffer::beginExternal()
10979
0
{
10980
0
    m_rhi->beginExternal(this);
10981
0
}
10982
10983
/*!
10984
    To be called once the externally added commands are recorded to the command
10985
    buffer or context.
10986
10987
    \note All QRhiCommandBuffer state must be assumed as invalid after calling
10988
    this function. Pipelines, vertex and index buffers, and other state must be
10989
    set again if more draw calls are recorded after the external commands.
10990
10991
    \sa beginExternal(), nativeHandles()
10992
 */
10993
void QRhiCommandBuffer::endExternal()
10994
0
{
10995
0
    m_rhi->endExternal(this);
10996
0
}
10997
10998
/*!
10999
    \return the last available timestamp, in seconds, when
11000
    \l QRhi::EnableTimestamps was enabled when creating the QRhi. The value
11001
    indicates the elapsed time on the GPU during the last completed frame.
11002
11003
    \note Do not expect results other than 0 when the QRhi::Timestamps feature
11004
    is not reported as supported, or when QRhi::EnableTimestamps was not passed
11005
    to QRhi::create(). There are exceptions to this, because with some graphics
11006
    APIs (Metal) timings are available without having to perform extra
11007
    operations (timestamp queries), but portable applications should always
11008
    consciously opt-in to timestamp collection when they know it is needed, and
11009
    call this function accordingly.
11010
11011
    Care must be exercised with the interpretation of the value, as its
11012
    precision and granularity is often not controlled by Qt, and depends on the
11013
    underlying graphics API and its implementation. In particular, comparing
11014
    the values between different graphics APIs and hardware is discouraged and
11015
    may be meaningless.
11016
11017
    The timing values will likely become available asynchronously. The returned
11018
    value may therefore be 0 (e.g., for the first 1-2 frames) or the last known
11019
    value referring to some previous frame. The value my also become 0 again
11020
    under certain conditions, such as when resizing the window. It can be
11021
    expected that the most up-to-date available value is retrieved in
11022
    beginFrame() and becomes queriable via this function once beginFrame()
11023
    returns.
11024
11025
    \note Do not assume that the value refers to the previous
11026
    (\c{currently_recorded - 1}) frame. It may refer to \c{currently_recorded -
11027
    2} or \c{currently_recorded - 3} as well. The exact behavior may depend on
11028
    the graphics API and its implementation.
11029
11030
    Watch out for the consequences of GPU frequency scaling and GPU clock
11031
    changes, depending on the platform. For example, on Windows the returned
11032
    timing may vary in a quite wide range between frames with modern graphics
11033
    cards, even when submitting frames with a similar, or the same workload.
11034
    This is out of scope for Qt to control and solve, generally speaking.
11035
    However, the D3D12 backend automatically calls
11036
    \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-setstablepowerstate}{ID3D12Device::SetStablePowerState()}
11037
    whenever the environment variable \c QT_D3D_STABLE_POWER_STATE is set to a
11038
    non-zero value. This can greatly stabilize the result. It can also have a
11039
    non-insignificant effect on the CPU-side timings measured via QElapsedTimer
11040
    for example, especially when offscreen frames are involved.
11041
11042
    \note Do not and never ship applications to production with
11043
    \c QT_D3D_STABLE_POWER_STATE set. See the Windows API documentation for details.
11044
11045
    \sa QRhi::Timestamps, QRhi::EnableTimestamps
11046
 */
11047
double QRhiCommandBuffer::lastCompletedGpuTime()
11048
0
{
11049
0
    return m_rhi->lastCompletedGpuTime(this);
11050
0
}
11051
11052
/*!
11053
    \return the value (typically an offset) \a v aligned to the uniform buffer
11054
    alignment given by ubufAlignment().
11055
 */
11056
int QRhi::ubufAligned(int v) const
11057
0
{
11058
0
    const int byteAlign = ubufAlignment();
11059
0
    return (v + byteAlign - 1) & ~(byteAlign - 1);
11060
0
}
11061
11062
/*!
11063
    \return the number of mip levels for a given \a size.
11064
 */
11065
int QRhi::mipLevelsForSize(const QSize &size)
11066
0
{
11067
0
    return qFloor(std::log2(qMax(size.width(), size.height()))) + 1;
11068
0
}
11069
11070
/*!
11071
    \return the texture image size for a given \a mipLevel, calculated based on
11072
    the level 0 size given in \a baseLevelSize.
11073
 */
11074
QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)
11075
0
{
11076
0
    const int w = qMax(1, baseLevelSize.width() >> mipLevel);
11077
0
    const int h = qMax(1, baseLevelSize.height() >> mipLevel);
11078
0
    return QSize(w, h);
11079
0
}
11080
11081
/*!
11082
    \return \c true if the underlying graphics API has the Y axis pointing up
11083
    in framebuffers and images.
11084
11085
    In practice this is \c true for OpenGL only.
11086
 */
11087
bool QRhi::isYUpInFramebuffer() const
11088
0
{
11089
0
    return d->isYUpInFramebuffer();
11090
0
}
11091
11092
/*!
11093
    \return \c true if the underlying graphics API has the Y axis pointing up
11094
    in its normalized device coordinate system.
11095
11096
    In practice this is \c false for Vulkan only.
11097
11098
    \note clipSpaceCorrMatrix() includes the corresponding adjustment (to make
11099
    Y point up) in its returned matrix.
11100
 */
11101
bool QRhi::isYUpInNDC() const
11102
0
{
11103
0
    return d->isYUpInNDC();
11104
0
}
11105
11106
/*!
11107
    \return \c true if the underlying graphics API uses depth range [0, 1] in
11108
    clip space.
11109
11110
    In practice this is \c false for OpenGL only, because OpenGL uses a
11111
    post-projection depth range of [-1, 1]. (not to be confused with the
11112
    NDC-to-window mapping controlled by glDepthRange(), which uses a range of
11113
    [0, 1], unless overridden by the QRhiViewport) In some OpenGL versions
11114
    glClipControl() could be used to change this, but the OpenGL backend of
11115
    QRhi does not use that function as it is not available in OpenGL ES or
11116
    OpenGL versions lower than 4.5.
11117
11118
    \note clipSpaceCorrMatrix() includes the corresponding adjustment in its
11119
    returned matrix. Therefore, many users of QRhi do not need to take any
11120
    further measures apart from pre-multiplying their projection matrices with
11121
    clipSpaceCorrMatrix(). However, some graphics techniques, such as, some
11122
    types of shadow mapping, involve working with and outputting depth values
11123
    in the shaders. These will need to query and take the value of this
11124
    function into account as appropriate.
11125
 */
11126
bool QRhi::isClipDepthZeroToOne() const
11127
0
{
11128
0
    return d->isClipDepthZeroToOne();
11129
0
}
11130
11131
/*!
11132
    \return a matrix that can be used to allow applications keep using
11133
    OpenGL-targeted vertex data and perspective projection matrices (such as,
11134
    the ones generated by QMatrix4x4::perspective()), regardless of the active
11135
    QRhi backend.
11136
11137
    In a typical renderer, once \c{this_matrix * mvp} is used instead of just
11138
    \c mvp, vertex data with Y up and viewports with depth range 0 - 1 can be
11139
    used without considering what backend (and so graphics API) is going to be
11140
    used at run time. This way branching based on isYUpInNDC() and
11141
    isClipDepthZeroToOne() can be avoided (although such logic may still become
11142
    required when implementing certain advanced graphics techniques).
11143
11144
    See
11145
    \l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this
11146
    page} for a discussion of the topic from Vulkan perspective.
11147
 */
11148
QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
11149
0
{
11150
0
    return d->clipSpaceCorrMatrix();
11151
0
}
11152
11153
/*!
11154
    \return \c true if the specified texture \a format modified by \a flags is
11155
    supported.
11156
11157
    The query is supported both for uncompressed and compressed formats.
11158
 */
11159
bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
11160
0
{
11161
0
    return d->isTextureFormatSupported(format, flags);
11162
0
}
11163
11164
/*!
11165
    \return \c true if the specified \a feature is supported
11166
 */
11167
bool QRhi::isFeatureSupported(QRhi::Feature feature) const
11168
0
{
11169
0
    return d->isFeatureSupported(feature);
11170
0
}
11171
11172
/*!
11173
    \return the value for the specified resource \a limit.
11174
11175
    The values are expected to be queried by the backends upon initialization,
11176
    meaning calling this function is a light operation.
11177
 */
11178
int QRhi::resourceLimit(ResourceLimit limit) const
11179
0
{
11180
0
    return d->resourceLimit(limit);
11181
0
}
11182
11183
/*!
11184
    \return a pointer to the backend-specific collection of native objects
11185
    for the device, context, and similar concepts used by the backend.
11186
11187
    Cast to QRhiVulkanNativeHandles, QRhiD3D11NativeHandles,
11188
    QRhiD3D12NativeHandles, QRhiGles2NativeHandles, or QRhiMetalNativeHandles
11189
    as appropriate.
11190
11191
    \note No ownership is transferred, neither for the returned pointer nor for
11192
    any native objects.
11193
 */
11194
const QRhiNativeHandles *QRhi::nativeHandles()
11195
0
{
11196
0
    return d->nativeHandles();
11197
0
}
11198
11199
/*!
11200
    With OpenGL this makes the OpenGL context current on the current thread.
11201
    The function has no effect with other backends.
11202
11203
    Calling this function is relevant typically in Qt framework code, when one
11204
    has to ensure external OpenGL code provided by the application can still
11205
    run like it did before with direct usage of OpenGL, as long as the QRhi is
11206
    using the OpenGL backend.
11207
11208
    \return false when failed, similarly to QOpenGLContext::makeCurrent(). When
11209
    the operation failed, isDeviceLost() can be called to determine if there
11210
    was a loss of context situation. Such a check is equivalent to checking via
11211
    QOpenGLContext::isValid().
11212
11213
    \sa QOpenGLContext::makeCurrent(), QOpenGLContext::isValid()
11214
 */
11215
bool QRhi::makeThreadLocalNativeContextCurrent()
11216
0
{
11217
0
    return d->makeThreadLocalNativeContextCurrent();
11218
0
}
11219
11220
/*!
11221
    With backends and graphics APIs where applicable, this function allows to
11222
    provide additional arguments to the \b next submission of commands to the
11223
    graphics command queue.
11224
11225
    In particular, with Vulkan this allows passing in a list of Vulkan semaphore
11226
    objects for \c vkQueueSubmit() to signal and wait on. \a params must then be
11227
    a \l QRhiVulkanQueueSubmitParams. This becomes essential in certain advanced
11228
    use cases, such as when performing native Vulkan calls that involve having
11229
    to wait on and signal VkSemaphores that the application's custom Vulkan
11230
    rendering or compute code manages. In addition, this also allows specifying
11231
    additional semaphores to wait on in the next \c vkQueuePresentKHR().
11232
11233
    \note This function affects the next queue submission only, which will
11234
    happen in endFrame(), endOffscreenFrame(), or finish(). The enqueuing of
11235
    present happens in endFrame().
11236
11237
    With many other backends the implementation of this function is a no-op.
11238
11239
    \since 6.9
11240
 */
11241
void QRhi::setQueueSubmitParams(QRhiNativeHandles *params)
11242
0
{
11243
0
    d->setQueueSubmitParams(params);
11244
0
}
11245
11246
/*!
11247
    Attempts to release resources in the backend's caches. This can include both
11248
    CPU and GPU resources.  Only memory and resources that can be recreated
11249
    automatically are in scope. As an example, if the backend's
11250
    QRhiGraphicsPipeline implementation maintains a cache of shader compilation
11251
    results, calling this function leads to emptying that cache, thus
11252
    potentially freeing up memory and graphics resources.
11253
11254
    Calling this function makes sense in resource constrained environments,
11255
    where at a certain point there is a need to ensure minimal resource usage,
11256
    at the expense of performance.
11257
 */
11258
void QRhi::releaseCachedResources()
11259
0
{
11260
0
    d->releaseCachedResources();
11261
11262
0
    for (QRhiResourceUpdateBatch *u : d->resUpdPool) {
11263
0
        if (u->d->poolIndex < 0)
11264
0
            u->d->trimOpLists();
11265
0
    }
11266
0
}
11267
11268
/*!
11269
    \return true if the graphics device was lost.
11270
11271
    The loss of the device is typically detected in beginFrame(), endFrame() or
11272
    QRhiSwapChain::createOrResize(), depending on the backend and the underlying
11273
    native APIs. The most common is endFrame() because that is where presenting
11274
    happens. With some backends QRhiSwapChain::createOrResize() can also fail
11275
    due to a device loss. Therefore this function is provided as a generic way
11276
    to check if a device loss was detected by a previous operation.
11277
11278
    When the device is lost, no further operations should be done via the QRhi.
11279
    Rather, all QRhi resources should be released, followed by destroying the
11280
    QRhi. A new QRhi can then be attempted to be created. If successful, all
11281
    graphics resources must be reinitialized. If not, try again later,
11282
    repeatedly.
11283
11284
    While simple applications may decide to not care about device loss,
11285
    on the commonly used desktop platforms a device loss can happen
11286
    due to a variety of reasons, including physically disconnecting the
11287
    graphics adapter, disabling the device or driver, uninstalling or upgrading
11288
    the graphics driver, or due to errors that lead to a graphics device reset.
11289
    Some of these can happen under perfectly normal circumstances as well, for
11290
    example the upgrade of the graphics driver to a newer version is a common
11291
    task that can happen at any time while a Qt application is running. Users
11292
    may very well expect applications to be able to survive this, even when the
11293
    application is actively using an API like OpenGL or Direct3D.
11294
11295
    Qt's own frameworks built on top of QRhi, such as, Qt Quick, can be
11296
    expected to handle and take appropriate measures when a device loss occurs.
11297
    If the data for graphics resources, such as textures and buffers, are still
11298
    available on the CPU side, such an event may not be noticeable on the
11299
    application level at all since graphics resources can seamlessly be
11300
    reinitialized then. However, applications and libraries working directly
11301
    with QRhi are expected to be prepared to check and handle device loss
11302
    situations themselves.
11303
11304
    \note With OpenGL, applications may need to opt-in to context reset
11305
    notifications by setting QSurfaceFormat::ResetNotification on the
11306
    QOpenGLContext. This is typically done by enabling the flag in
11307
    QRhiGles2InitParams::format. Keep in mind however that some systems may
11308
    generate context resets situations even when this flag is not set.
11309
 */
11310
bool QRhi::isDeviceLost() const
11311
0
{
11312
0
    return d->isDeviceLost();
11313
0
}
11314
11315
/*!
11316
    \return a binary data blob with data collected from the
11317
    QRhiGraphicsPipeline and QRhiComputePipeline successfully created during
11318
    the lifetime of this QRhi.
11319
11320
    By saving and then, in subsequent runs of the same application, reloading
11321
    the cache data, pipeline and shader creation times can potentially be
11322
    reduced. What exactly the cache and its serialized version includes is not
11323
    specified, is always specific to the backend used, and in some cases also
11324
    dependent on the particular implementation of the graphics API.
11325
11326
    When the PipelineCacheDataLoadSave is reported as unsupported, the returned
11327
    QByteArray is empty.
11328
11329
    When the EnablePipelineCacheDataSave flag was not specified when calling
11330
    create(), the returned QByteArray may be empty, even when the
11331
    PipelineCacheDataLoadSave feature is supported.
11332
11333
    When the returned data is non-empty, it is always specific to the Qt
11334
    version and QRhi backend. In addition, in some cases there is a strong
11335
    dependency to the graphics device and the exact driver version used. QRhi
11336
    takes care of adding the appropriate header and safeguards that ensure that
11337
    the data can always be passed safely to setPipelineCacheData(), therefore
11338
    attempting to load data from a run on another version of a driver will be
11339
    handled safely and gracefully.
11340
11341
    \note Calling releaseCachedResources() may, depending on the backend, clear
11342
    the pipeline data collected. A subsequent call to this function may then
11343
    not return any data.
11344
11345
    See EnablePipelineCacheDataSave for further details about this feature.
11346
11347
    \note Minimize the number of calls to this function. Retrieving the blob is
11348
    not always a cheap operation, and therefore this function should only be
11349
    called at a low frequency, ideally only once e.g. when closing the
11350
    application.
11351
11352
    \sa setPipelineCacheData(), create(), isFeatureSupported()
11353
 */
11354
QByteArray QRhi::pipelineCacheData()
11355
0
{
11356
0
    return d->pipelineCacheData();
11357
0
}
11358
11359
/*!
11360
    Loads \a data into the pipeline cache, when applicable.
11361
11362
    When the PipelineCacheDataLoadSave is reported as unsupported, the function
11363
    is safe to call, but has no effect.
11364
11365
    The blob returned by pipelineCacheData() is always specific to the Qt
11366
    version, the QRhi backend, and, in some cases, also to the graphics device,
11367
    and a given version of the graphics driver. QRhi takes care of adding the
11368
    appropriate header and safeguards that ensure that the data can always be
11369
    passed safely to this function. If there is a mismatch, e.g. because the
11370
    driver has been upgraded to a newer version, or because the data was
11371
    generated from a different QRhi backend, a warning is printed and \a data
11372
    is safely ignored.
11373
11374
    With Vulkan, this maps directly to VkPipelineCache. Calling this function
11375
    creates a new Vulkan pipeline cache object, with its initial data sourced
11376
    from \a data. The pipeline cache object is then used by all subsequently
11377
    created QRhiGraphicsPipeline and QRhiComputePipeline objects, thus
11378
    accelerating, potentially, the pipeline creation.
11379
11380
    With other APIs there is no real pipeline cache, but they may provide a
11381
    cache with bytecode from shader compilations (D3D) or program binaries
11382
    (OpenGL). In applications that perform a lot of shader compilation from
11383
    source at run time this can provide a significant boost in subsequent runs
11384
    if the "pipeline cache" is pre-seeded from an earlier run using this
11385
    function.
11386
11387
    \note QRhi cannot give any guarantees that \a data has an effect on the
11388
    pipeline and shader creation performance. With APIs like Vulkan, it is up
11389
    to the driver to decide if \a data is used for some purpose, or if it is
11390
    ignored.
11391
11392
    See EnablePipelineCacheDataSave for further details about this feature.
11393
11394
    \note This mechanism offered by QRhi is independent of the drivers' own
11395
    internal caching mechanism, if any. This means that, depending on the
11396
    graphics API and its implementation, the exact effects of retrieving and
11397
    then reloading \a data are not predictable. Improved performance may not be
11398
    visible at all in case other caching mechanisms outside of Qt's control are
11399
    already active.
11400
11401
    \note Minimize the number of calls to this function. Loading the blob is
11402
    not always a cheap operation, and therefore this function should only be
11403
    called at a low frequency, ideally only once e.g. when starting the
11404
    application.
11405
11406
    \warning Serialized pipeline cache data is assumed to be trusted content. Qt
11407
    performs robust parsing of the header and metadata included in \a data,
11408
    application developers are however advised to never pass in data from
11409
    untrusted sources.
11410
11411
    \sa pipelineCacheData(), isFeatureSupported()
11412
 */
11413
void QRhi::setPipelineCacheData(const QByteArray &data)
11414
0
{
11415
0
    d->setPipelineCacheData(data);
11416
0
}
11417
11418
/*!
11419
    \struct QRhiStats
11420
    \inmodule QtGuiPrivate
11421
    \inheaderfile rhi/qrhi.h
11422
    \since 6.6
11423
11424
    \brief Statistics provided from the underlying memory allocator.
11425
11426
    \note This is a RHI API with limited compatibility guarantees, see \l QRhi
11427
    for details.
11428
 */
11429
11430
/*!
11431
    \variable QRhiStats::totalPipelineCreationTime
11432
11433
    The total time in milliseconds spent in graphics and compute pipeline
11434
    creation, which usually involves shader compilation or cache lookups, and
11435
    potentially expensive processing.
11436
11437
    \note The value should not be compared between different backends since the
11438
    concept of "pipelines" and what exactly happens under the hood during, for
11439
    instance, a call to QRhiGraphicsPipeline::create(), differ greatly between
11440
    graphics APIs and their implementations.
11441
11442
    \sa QRhi::statistics()
11443
*/
11444
11445
/*!
11446
    \variable QRhiStats::blockCount
11447
11448
    Statistic reported from the Vulkan or D3D12 memory allocator.
11449
11450
    \sa QRhi::statistics()
11451
*/
11452
11453
/*!
11454
    \variable QRhiStats::allocCount
11455
11456
    Statistic reported from the Vulkan or D3D12 memory allocator.
11457
11458
    \sa QRhi::statistics()
11459
*/
11460
11461
/*!
11462
    \variable QRhiStats::usedBytes
11463
11464
    Statistic reported from the Vulkan or D3D12 memory allocator.
11465
11466
    \sa QRhi::statistics()
11467
*/
11468
11469
/*!
11470
    \variable QRhiStats::unusedBytes
11471
11472
    Statistic reported from the Vulkan or D3D12 memory allocator.
11473
11474
    \sa QRhi::statistics()
11475
*/
11476
11477
/*!
11478
    \variable QRhiStats::totalUsageBytes
11479
11480
    Valid only with D3D12 currently. Matches IDXGIAdapter3::QueryVideoMemoryInfo().
11481
11482
    \sa QRhi::statistics()
11483
*/
11484
11485
#ifndef QT_NO_DEBUG_STREAM
11486
QDebug operator<<(QDebug dbg, const QRhiStats &info)
11487
0
{
11488
0
    QDebugStateSaver saver(dbg);
11489
0
    dbg.nospace() << "QRhiStats("
11490
0
                  << "totalPipelineCreationTime=" << info.totalPipelineCreationTime
11491
0
                  << " blockCount=" << info.blockCount
11492
0
                  << " allocCount=" << info.allocCount
11493
0
                  << " usedBytes=" << info.usedBytes
11494
0
                  << " unusedBytes=" << info.unusedBytes
11495
0
                  << " totalUsageBytes=" << info.totalUsageBytes
11496
0
                  << ')';
11497
0
    return dbg;
11498
0
}
11499
#endif
11500
11501
/*!
11502
    Gathers and returns statistics about the timings and allocations of
11503
    graphics resources.
11504
11505
    Data about memory allocations is only available with some backends, where
11506
    such operations are under Qt's control. With graphics APIs where there is
11507
    no lower level control over resource memory allocations, this will never be
11508
    supported and all relevant fields in the results are 0.
11509
11510
    With Vulkan in particular, the values are valid always, and are queried
11511
    from the underlying memory allocator library. This gives an insight into
11512
    the memory requirements of the active buffers and textures.
11513
11514
    The same is true for Direct 3D 12. In addition to the memory allocator
11515
    library's statistics, here the result also includes a \c totalUsageBytes
11516
    field which reports the total size including additional resources that are
11517
    not under the memory allocator library's control (swapchain buffers,
11518
    descriptor heaps, etc.), as reported by DXGI.
11519
11520
    The values correspond to all types of memory used, combined. (i.e. video +
11521
    system in case of a discreet GPU)
11522
11523
    Additional data, such as the total time in milliseconds spent in graphics
11524
    and compute pipeline creation (which usually involves shader compilation or
11525
    cache lookups, and potentially expensive processing) is available with most
11526
    backends.
11527
11528
    \note The elapsed times for operations such as pipeline creation may be
11529
    affected by various factors. The results should not be compared between
11530
    different backends since the concept of "pipelines" and what exactly
11531
    happens under the hood during, for instance, a call to
11532
    QRhiGraphicsPipeline::create(), differ greatly between graphics APIs and
11533
    their implementations.
11534
11535
    \note Additionally, many drivers will likely employ various caching
11536
    strategies for shaders, programs, pipelines. (independently of Qt's own
11537
    similar facilities, such as setPipelineCacheData() or the OpenGL-specific
11538
    program binary disk cache). Because such internal behavior is transparent
11539
    to the API client, Qt and QRhi have no knowledge or control over the exact
11540
    caching strategy, persistency, invalidation of the cached data, etc. When
11541
    reading timings, such as the time spent on pipeline creation, the potential
11542
    presence and unspecified behavior of driver-level caching mechanisms should
11543
    be kept in mind.
11544
 */
11545
QRhiStats QRhi::statistics() const
11546
0
{
11547
0
    return d->statistics();
11548
0
}
11549
11550
/*!
11551
    \return a new graphics pipeline resource.
11552
11553
    \sa QRhiResource::destroy()
11554
 */
11555
QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
11556
0
{
11557
0
    return d->createGraphicsPipeline();
11558
0
}
11559
11560
/*!
11561
    \return a new compute pipeline resource.
11562
11563
    \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
11564
    is reported as supported.
11565
11566
    \sa QRhiResource::destroy()
11567
 */
11568
QRhiComputePipeline *QRhi::newComputePipeline()
11569
0
{
11570
0
    return d->createComputePipeline();
11571
0
}
11572
11573
/*!
11574
    \return a new shader resource binding collection resource.
11575
11576
    \sa QRhiResource::destroy()
11577
 */
11578
QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
11579
0
{
11580
0
    return d->createShaderResourceBindings();
11581
0
}
11582
11583
/*!
11584
    \return a new buffer with the specified \a type, \a usage, and \a size.
11585
11586
    \note Some \a usage and \a type combinations may not be supported by all
11587
    backends. See \l{QRhiBuffer::UsageFlag}{UsageFlags} and
11588
    \l{QRhi::NonDynamicUniformBuffers}{the feature flags}.
11589
11590
    \note Backends may choose to allocate buffers bigger than \a size. This is
11591
    done transparently to applications, so there are no special restrictions on
11592
    the value of \a size. QRhiBuffer::size() will always report back the value
11593
    that was requested in \a size.
11594
11595
    \sa QRhiResource::destroy()
11596
 */
11597
QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type,
11598
                            QRhiBuffer::UsageFlags usage,
11599
                            quint32 size)
11600
0
{
11601
0
    return d->createBuffer(type, usage, size);
11602
0
}
11603
11604
/*!
11605
    \return a new renderbuffer with the specified \a type, \a pixelSize, \a
11606
    sampleCount, and \a flags.
11607
11608
    When \a backingFormatHint is set to a texture format other than
11609
    QRhiTexture::UnknownFormat, it may be used by the backend to decide what
11610
    format to use for the storage backing the renderbuffer.
11611
11612
    \note \a backingFormatHint becomes relevant typically when multisampling
11613
    and floating point texture formats are involved: rendering into a
11614
    multisample QRhiRenderBuffer and then resolving into a non-RGBA8
11615
    QRhiTexture implies (with some graphics APIs) that the storage backing the
11616
    QRhiRenderBuffer uses the matching non-RGBA8 format. That means that
11617
    passing a format like QRhiTexture::RGBA32F is important, because backends
11618
    will typically opt for QRhiTexture::RGBA8 by default, which would then
11619
    break later on due to attempting to set up RGBA8->RGBA32F multisample
11620
    resolve in the color attachment(s) of the QRhiTextureRenderTarget.
11621
11622
    \sa QRhiResource::destroy()
11623
 */
11624
QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type,
11625
                                        const QSize &pixelSize,
11626
                                        int sampleCount,
11627
                                        QRhiRenderBuffer::Flags flags,
11628
                                        QRhiTexture::Format backingFormatHint)
11629
0
{
11630
0
    return d->createRenderBuffer(type, pixelSize, sampleCount, flags, backingFormatHint);
11631
0
}
11632
11633
/*!
11634
    \return a new 1D or 2D texture with the specified \a format, \a pixelSize, \a
11635
    sampleCount, and \a flags.
11636
11637
    A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This
11638
    function will implicitly set this flag if the \a pixelSize height is 0.
11639
11640
    \note \a format specifies the requested internal and external format,
11641
    meaning the data to be uploaded to the texture will need to be in a
11642
    compatible format, while the native texture may (but is not guaranteed to,
11643
    in case of OpenGL at least) use this format internally.
11644
11645
    \note 1D textures are only functional when the OneDimensionalTextures feature is
11646
    reported as supported at run time. Further, mipmaps on 1D textures are only
11647
    functional when the OneDimensionalTextureMipmaps feature is reported at run time.
11648
11649
    \sa QRhiResource::destroy()
11650
 */
11651
QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
11652
                              const QSize &pixelSize,
11653
                              int sampleCount,
11654
                              QRhiTexture::Flags flags)
11655
0
{
11656
0
    if (pixelSize.height() == 0)
11657
0
        flags |= QRhiTexture::OneDimensional;
11658
11659
0
    return d->createTexture(format, pixelSize, 1, 0, sampleCount, flags);
11660
0
}
11661
11662
/*!
11663
    \return a new 1D, 2D or 3D texture with the specified \a format, \a width, \a
11664
    height, \a depth, \a sampleCount, and \a flags.
11665
11666
    This overload is suitable for 3D textures because it allows specifying \a
11667
    depth. A 3D texture must have QRhiTexture::ThreeDimensional set in \a
11668
    flags, but using this overload that can be omitted because the flag is set
11669
    implicitly whenever \a depth is greater than 0. For 1D, 2D and cube textures \a
11670
    depth should be set to 0.
11671
11672
    A 1D texture must have QRhiTexture::OneDimensional set in \a flags.  This overload
11673
    will implicitly set this flag if both \a height and \a depth are 0.
11674
11675
    \note 3D textures are only functional when the ThreeDimensionalTextures
11676
    feature is reported as supported at run time.
11677
11678
    \note 1D textures are only functional when the OneDimensionalTextures feature is
11679
    reported as supported at run time. Further, mipmaps on 1D textures are only
11680
    functional when the OneDimensionalTextureMipmaps feature is reported at run time.
11681
11682
    \overload
11683
 */
11684
QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
11685
                              int width, int height, int depth,
11686
                              int sampleCount,
11687
                              QRhiTexture::Flags flags)
11688
0
{
11689
0
    if (depth > 0)
11690
0
        flags |= QRhiTexture::ThreeDimensional;
11691
11692
0
    if (height == 0 && depth == 0)
11693
0
        flags |= QRhiTexture::OneDimensional;
11694
11695
0
    return d->createTexture(format, QSize(width, height), depth, 0, sampleCount, flags);
11696
0
}
11697
11698
/*!
11699
    \return a new 1D or 2D texture array with the specified \a format, \a arraySize,
11700
    \a pixelSize, \a sampleCount, and \a flags.
11701
11702
    This function implicitly sets QRhiTexture::TextureArray in \a flags.
11703
11704
    A 1D texture array must have QRhiTexture::OneDimensional set in \a flags.  This
11705
    function will implicitly set this flag if the \a pixelSize height is 0.
11706
11707
    \note Do not confuse texture arrays with arrays of textures. A QRhiTexture
11708
    created by this function is usable with 1D or 2D array samplers in the shader, for
11709
    example: \c{layout(binding = 1) uniform sampler2DArray texArr;}. Arrays of
11710
    textures refers to a list of textures that are exposed to the shader via
11711
    QRhiShaderResourceBinding::sampledTextures() and a count > 1, and declared
11712
    in the shader for example like this: \c{layout(binding = 1) uniform
11713
    sampler2D textures[4];}
11714
11715
    \note This is only functional when the TextureArrays feature is reported as
11716
    supported at run time.
11717
11718
    \note 1D textures are only functional when the OneDimensionalTextures feature is
11719
    reported as supported at run time. Further, mipmaps on 1D textures are only
11720
    functional when the OneDimensionalTextureMipmaps feature is reported at run time.
11721
11722
11723
    \sa newTexture()
11724
 */
11725
QRhiTexture *QRhi::newTextureArray(QRhiTexture::Format format,
11726
                                   int arraySize,
11727
                                   const QSize &pixelSize,
11728
                                   int sampleCount,
11729
                                   QRhiTexture::Flags flags)
11730
0
{
11731
0
    flags |= QRhiTexture::TextureArray;
11732
11733
0
    if (pixelSize.height() == 0)
11734
0
        flags |= QRhiTexture::OneDimensional;
11735
11736
0
    return d->createTexture(format, pixelSize, 1, arraySize, sampleCount, flags);
11737
0
}
11738
11739
/*!
11740
    \return a new sampler with the specified magnification filter \a magFilter,
11741
    minification filter \a minFilter, mipmapping mode \a mipmapMode, and the
11742
    addressing (wrap) modes \a addressU, \a addressV, and \a addressW.
11743
11744
    \note Setting \a mipmapMode to a value other than \c None implies that
11745
    images for all relevant mip levels will be provided either via
11746
    \l{QRhiResourceUpdateBatch::uploadTexture()}{texture uploads} or by calling
11747
    \l{QRhiResourceUpdateBatch::generateMips()}{generateMips()} on the texture
11748
    that is used with this sampler. Attempting to use the sampler with a
11749
    texture that has no data for all relevant mip levels will lead to rendering
11750
    errors, with the exact behavior dependent on the underlying graphics API.
11751
11752
    \sa QRhiResource::destroy()
11753
 */
11754
QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter,
11755
                              QRhiSampler::Filter minFilter,
11756
                              QRhiSampler::Filter mipmapMode,
11757
                              QRhiSampler::AddressMode addressU,
11758
                              QRhiSampler::AddressMode addressV,
11759
                              QRhiSampler::AddressMode addressW)
11760
0
{
11761
0
    return d->createSampler(magFilter, minFilter, mipmapMode, addressU, addressV, addressW);
11762
0
}
11763
11764
/*!
11765
    \return a new shading rate map object.
11766
11767
    \since 6.9
11768
 */
11769
QRhiShadingRateMap *QRhi::newShadingRateMap()
11770
0
{
11771
0
    return d->createShadingRateMap();
11772
0
}
11773
11774
/*!
11775
    \return a new texture render target with color and depth/stencil
11776
    attachments given in \a desc, and with the specified \a flags.
11777
11778
    \sa QRhiResource::destroy()
11779
 */
11780
11781
QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
11782
                                                      QRhiTextureRenderTarget::Flags flags)
11783
0
{
11784
0
    return d->createTextureRenderTarget(desc, flags);
11785
0
}
11786
11787
/*!
11788
    \return a new swapchain.
11789
11790
    \sa QRhiResource::destroy(), QRhiSwapChain::createOrResize()
11791
 */
11792
QRhiSwapChain *QRhi::newSwapChain()
11793
0
{
11794
0
    return d->createSwapChain();
11795
0
}
11796
11797
/*!
11798
    Starts a new frame targeting the next available buffer of \a swapChain.
11799
11800
    A frame consists of resource updates and one or more render and compute
11801
    passes.
11802
11803
    \a flags can indicate certain special cases.
11804
11805
    The high level pattern of rendering into a QWindow using a swapchain:
11806
11807
    \list
11808
11809
    \li Create a swapchain.
11810
11811
    \li Call QRhiSwapChain::createOrResize() whenever the surface size is
11812
    different than before.
11813
11814
    \li Call QRhiSwapChain::destroy() on
11815
    QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed.
11816
11817
    \li Then on every frame:
11818
    \badcode
11819
       beginFrame(sc);
11820
       updates = nextResourceUpdateBatch();
11821
       updates->...
11822
       QRhiCommandBuffer *cb = sc->currentFrameCommandBuffer();
11823
       cb->beginPass(sc->currentFrameRenderTarget(), colorClear, dsClear, updates);
11824
       ...
11825
       cb->endPass();
11826
       ... // more passes as necessary
11827
       endFrame(sc);
11828
    \endcode
11829
11830
    \endlist
11831
11832
    \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
11833
    value on failure. Some of these should be treated as soft, "try again
11834
    later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
11835
    the swapchain is to be resized or updated by calling
11836
    QRhiSwapChain::createOrResize(). The application should then attempt to
11837
    generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
11838
    lost but this may also be recoverable by releasing all resources, including
11839
    the QRhi itself, and then recreating all resources. See isDeviceLost() for
11840
    further discussion.
11841
11842
    \sa endFrame(), beginOffscreenFrame(), isDeviceLost()
11843
 */
11844
QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
11845
0
{
11846
0
    if (d->inFrame)
11847
0
        qWarning("Attempted to call beginFrame() within a still active frame; ignored");
11848
11849
0
    qCDebug(QRHI_LOG_RUB) << "[rub] new frame";
11850
11851
0
    QRhi::FrameOpResult r = !d->inFrame ? d->beginFrame(swapChain, flags) : FrameOpSuccess;
11852
0
    if (r == FrameOpSuccess)
11853
0
        d->inFrame = true;
11854
11855
0
    return r;
11856
0
}
11857
11858
/*!
11859
    Ends, commits, and presents a frame that was started in the last
11860
    beginFrame() on \a swapChain.
11861
11862
    Double (or triple) buffering is managed internally by the QRhiSwapChain and
11863
    QRhi.
11864
11865
    \a flags can optionally be used to change the behavior in certain ways.
11866
    Passing QRhi::SkipPresent skips queuing the Present command or calling
11867
    swapBuffers.
11868
11869
    \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
11870
    value on failure. Some of these should be treated as soft, "try again
11871
    later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
11872
    the swapchain is to be resized or updated by calling
11873
    QRhiSwapChain::createOrResize(). The application should then attempt to
11874
    generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
11875
    lost but this may also be recoverable by releasing all resources, including
11876
    the QRhi itself, and then recreating all resources. See isDeviceLost() for
11877
    further discussion.
11878
11879
    \sa beginFrame(), isDeviceLost()
11880
 */
11881
QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags)
11882
0
{
11883
0
    if (!d->inFrame)
11884
0
        qWarning("Attempted to call endFrame() without an active frame; ignored");
11885
11886
0
    QRhi::FrameOpResult r = d->inFrame ? d->endFrame(swapChain, flags) : FrameOpSuccess;
11887
0
    d->inFrame = false;
11888
    // deleteLater is a high level QRhi concept the backends know
11889
    // nothing about - handle it here.
11890
0
    qDeleteAll(d->pendingDeleteResources);
11891
0
    d->pendingDeleteResources.clear();
11892
11893
0
    return r;
11894
0
}
11895
11896
/*!
11897
    \return true when there is an active frame, meaning there was a
11898
    beginFrame() (or beginOffscreenFrame()) with no corresponding endFrame()
11899
    (or endOffscreenFrame()) yet.
11900
11901
    \sa currentFrameSlot(), beginFrame(), endFrame()
11902
 */
11903
bool QRhi::isRecordingFrame() const
11904
0
{
11905
0
    return d->inFrame;
11906
0
}
11907
11908
/*!
11909
    \return the current frame slot index while recording a frame. Unspecified
11910
    when called outside an active frame (that is, when isRecordingFrame() is \c
11911
    false).
11912
11913
    With backends like Vulkan or Metal, it is the responsibility of the QRhi
11914
    backend to block whenever starting a new frame and finding the CPU is
11915
    already \c{FramesInFlight - 1} frames ahead of the GPU (because the command
11916
    buffer submitted in frame no. \c{current} - \c{FramesInFlight} has not yet
11917
    completed).
11918
11919
    Resources that tend to change between frames (such as, the native buffer
11920
    object backing a QRhiBuffer with type QRhiBuffer::Dynamic) exist in
11921
    multiple versions, so that each frame, that can be submitted while a
11922
    previous one is still being processed, works with its own copy, thus
11923
    avoiding the need to stall the pipeline when preparing the frame. (The
11924
    contents of a resource that may still be in use in the GPU should not be
11925
    touched, but simply always waiting for the previous frame to finish would
11926
    reduce GPU utilization and ultimately, performance and efficiency.)
11927
11928
    Conceptually this is somewhat similar to copy-on-write schemes used by some
11929
    C++ containers and other types. It may also be similar to what an OpenGL or
11930
    Direct 3D 11 implementation performs internally for certain type of objects.
11931
11932
    In practice, such double (or triple) buffering resources is realized in
11933
    the Vulkan, Metal, and similar QRhi backends by having a fixed number of
11934
    native resource (such as, VkBuffer) \c slots behind a QRhiResource. That
11935
    can then be indexed by a frame slot index running 0, 1, ..,
11936
    FramesInFlight-1, and then wrapping around.
11937
11938
    All this is managed transparently to the users of QRhi. However,
11939
    applications that integrate rendering done directly with the graphics API
11940
    may want to perform a similar double or triple buffering of their own
11941
    graphics resources. That is then most easily achieved by knowing the values
11942
    of the maximum number of in-flight frames (retrievable via resourceLimit())
11943
    and the current frame (slot) index (returned by this function).
11944
11945
    \sa isRecordingFrame(), beginFrame(), endFrame()
11946
 */
11947
int QRhi::currentFrameSlot() const
11948
0
{
11949
0
    return d->currentFrameSlot;
11950
0
}
11951
11952
/*!
11953
    Starts a new offscreen frame. Provides a command buffer suitable for
11954
    recording rendering commands in \a cb. \a flags is used to indicate
11955
    certain special cases, just like with beginFrame().
11956
11957
    \note The QRhiCommandBuffer stored to *cb is not owned by the caller.
11958
11959
    Rendering without a swapchain is possible as well. The typical use case is
11960
    to use it in completely offscreen applications, e.g. to generate image
11961
    sequences by rendering and reading back without ever showing a window.
11962
11963
    Usage in on-screen applications (so beginFrame, endFrame,
11964
    beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) is possible too.
11965
11966
    When a \l{QRhiResourceUpdateBatch::readBackTexture()}{texture} or
11967
    \l{QRhiResourceUpdateBatch::readBackBuffer()}{buffer} readback was
11968
    scheduled, offscreen frames do not let the CPU potentially generate another
11969
    frame while the GPU is still processing the previous one. This has the side
11970
    effect that if readbacks are scheduled, the results are guaranteed to be
11971
    available once endOffscreenFrame() returns. That is not the case with frames
11972
    targeting a swapchain: there the GPU is potentially better utilized, but
11973
    working with readback operations needs more care from the application
11974
    because endFrame(), unlike endOffscreenFrame(), does not guarantee that the
11975
    results from the readback are available at that point.
11976
11977
    The skeleton of rendering a frame without a swapchain and then reading the
11978
    frame contents back could look like the following:
11979
11980
    \code
11981
        QRhiReadbackResult rbResult;
11982
        QRhiCommandBuffer *cb;
11983
        rhi->beginOffscreenFrame(&cb);
11984
        cb->beginPass(rt, colorClear, dsClear);
11985
        // ...
11986
        u = nextResourceUpdateBatch();
11987
        u->readBackTexture(rb, &rbResult);
11988
        cb->endPass(u);
11989
        rhi->endOffscreenFrame();
11990
        // image data available in rbResult
11991
   \endcode
11992
11993
   \sa endOffscreenFrame(), beginFrame()
11994
 */
11995
QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags)
11996
0
{
11997
0
    if (d->inFrame)
11998
0
        qWarning("Attempted to call beginOffscreenFrame() within a still active frame; ignored");
11999
12000
0
    qCDebug(QRHI_LOG_RUB) << "[rub] new offscreen frame";
12001
12002
0
    QRhi::FrameOpResult r = !d->inFrame ? d->beginOffscreenFrame(cb, flags) : FrameOpSuccess;
12003
0
    if (r == FrameOpSuccess)
12004
0
        d->inFrame = true;
12005
12006
0
    return r;
12007
0
}
12008
12009
/*!
12010
    Ends, submits, and potentially waits for the offscreen frame.
12011
12012
    Unlike endFrame(), this function will block and wait for completion of the
12013
    GPU-side work when there are active buffer or texture readbacks.
12014
12015
    \a flags is not currently used.
12016
12017
    \sa beginOffscreenFrame()
12018
 */
12019
QRhi::FrameOpResult QRhi::endOffscreenFrame(EndFrameFlags flags)
12020
0
{
12021
0
    if (!d->inFrame)
12022
0
        qWarning("Attempted to call endOffscreenFrame() without an active frame; ignored");
12023
12024
0
    QRhi::FrameOpResult r = d->inFrame ? d->endOffscreenFrame(flags) : FrameOpSuccess;
12025
0
    d->inFrame = false;
12026
0
    qDeleteAll(d->pendingDeleteResources);
12027
0
    d->pendingDeleteResources.clear();
12028
12029
0
    return r;
12030
0
}
12031
12032
/*!
12033
    Waits for any work on the graphics queue (where applicable) to complete,
12034
    then executes all deferred operations, like completing readbacks and
12035
    resource releases. Can be called inside and outside of a frame, but not
12036
    inside a pass. Inside a frame it implies submitting any work on the
12037
    command buffer.
12038
12039
    \note Avoid this function. One case where it may be needed is when the
12040
    results of an enqueued readback in a swapchain-based frame are needed at a
12041
    fixed given point and so waiting for the results is desired.
12042
 */
12043
QRhi::FrameOpResult QRhi::finish()
12044
0
{
12045
0
    return d->finish();
12046
0
}
12047
12048
/*!
12049
    \return the list of supported sample counts.
12050
12051
    A typical example would be (1, 2, 4, 8).
12052
12053
    With some backend this list of supported values is fixed in advance, while
12054
    with some others the (physical) device properties indicate what is
12055
    supported at run time.
12056
12057
    \sa QRhiRenderBuffer::setSampleCount(), QRhiTexture::setSampleCount(),
12058
    QRhiGraphicsPipeline::setSampleCount(), QRhiSwapChain::setSampleCount()
12059
 */
12060
QList<int> QRhi::supportedSampleCounts() const
12061
0
{
12062
0
    return d->supportedSampleCounts();
12063
0
}
12064
12065
/*!
12066
    \return the minimum uniform buffer offset alignment in bytes. This is
12067
    typically 256.
12068
12069
    Attempting to bind a uniform buffer region with an offset not aligned to
12070
    this value will lead to failures depending on the backend and the
12071
    underlying graphics API.
12072
12073
    \sa ubufAligned()
12074
 */
12075
int QRhi::ubufAlignment() const
12076
0
{
12077
0
    return d->ubufAlignment();
12078
0
}
12079
12080
/*!
12081
    \return The list of supported variable shading rates for the specified \a sampleCount.
12082
12083
    1x1 is always supported.
12084
12085
    \since 6.9
12086
 */
12087
QList<QSize> QRhi::supportedShadingRates(int sampleCount) const
12088
0
{
12089
0
    return d->supportedShadingRates(sampleCount);
12090
0
}
12091
12092
Q_CONSTINIT static QBasicAtomicInteger<QRhiGlobalObjectIdGenerator::Type> counter = Q_BASIC_ATOMIC_INITIALIZER(0);
12093
12094
QRhiGlobalObjectIdGenerator::Type QRhiGlobalObjectIdGenerator::newId()
12095
0
{
12096
0
    return counter.fetchAndAddRelaxed(1) + 1;
12097
0
}
12098
12099
bool QRhiPassResourceTracker::isEmpty() const
12100
0
{
12101
0
    return m_buffers.isEmpty() && m_textures.isEmpty();
12102
0
}
12103
12104
void QRhiPassResourceTracker::reset()
12105
0
{
12106
0
    m_buffers.clear();
12107
0
    m_textures.clear();
12108
0
}
12109
12110
static inline QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a,
12111
                                                                QRhiPassResourceTracker::BufferStage b)
12112
0
{
12113
0
    return QRhiPassResourceTracker::BufferStage(qMin(int(a), int(b)));
12114
0
}
12115
12116
void QRhiPassResourceTracker::registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
12117
                                             const UsageState &state)
12118
0
{
12119
0
    auto it = m_buffers.find(buf);
12120
0
    if (it != m_buffers.end()) {
12121
0
        Buffer &b = it->second;
12122
0
        if (Q_UNLIKELY(b.access != *access)) {
12123
0
            const QByteArray name = buf->name();
12124
0
            qWarning("Buffer %p (%s) used with different accesses within the same pass, this is not allowed.",
12125
0
                     buf, name.constData());
12126
0
            return;
12127
0
        }
12128
0
        if (b.stage != *stage) {
12129
0
            b.stage = earlierStage(b.stage, *stage);
12130
0
            *stage = b.stage;
12131
0
        }
12132
0
        return;
12133
0
    }
12134
12135
0
    Buffer b;
12136
0
    b.slot = slot;
12137
0
    b.access = *access;
12138
0
    b.stage = *stage;
12139
0
    b.stateAtPassBegin = state; // first use -> initial state
12140
0
    m_buffers.insert(buf, b);
12141
0
}
12142
12143
static inline QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a,
12144
                                                                 QRhiPassResourceTracker::TextureStage b)
12145
0
{
12146
0
    return QRhiPassResourceTracker::TextureStage(qMin(int(a), int(b)));
12147
0
}
12148
12149
static inline bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess access)
12150
0
{
12151
0
    return access == QRhiPassResourceTracker::TexStorageLoad
12152
0
            || access == QRhiPassResourceTracker::TexStorageStore
12153
0
            || access == QRhiPassResourceTracker::TexStorageLoadStore;
12154
0
}
12155
12156
void QRhiPassResourceTracker::registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage,
12157
                                              const UsageState &state)
12158
0
{
12159
0
    auto it = m_textures.find(tex);
12160
0
    if (it != m_textures.end()) {
12161
0
        Texture &t = it->second;
12162
0
        if (t.access != *access) {
12163
            // Different subresources of a texture may be used for both load
12164
            // and store in the same pass. (think reading from one mip level
12165
            // and writing to another one in a compute shader) This we can
12166
            // handle by treating the entire resource as read-write.
12167
0
            if (Q_LIKELY(isImageLoadStore(t.access) && isImageLoadStore(*access))) {
12168
0
                t.access = QRhiPassResourceTracker::TexStorageLoadStore;
12169
0
                *access = t.access;
12170
0
            } else {
12171
0
                const QByteArray name = tex->name();
12172
0
                qWarning("Texture %p (%s) used with different accesses within the same pass, this is not allowed.",
12173
0
                         tex, name.constData());
12174
0
            }
12175
0
        }
12176
0
        if (t.stage != *stage) {
12177
0
            t.stage = earlierStage(t.stage, *stage);
12178
0
            *stage = t.stage;
12179
0
        }
12180
0
        return;
12181
0
    }
12182
12183
0
    Texture t;
12184
0
    t.access = *access;
12185
0
    t.stage = *stage;
12186
0
    t.stateAtPassBegin = state; // first use -> initial state
12187
0
    m_textures.insert(tex, t);
12188
0
}
12189
12190
QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
12191
0
{
12192
    // pick the earlier stage (as this is going to be dstAccessMask)
12193
0
    if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
12194
0
        return QRhiPassResourceTracker::BufVertexStage;
12195
0
    if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
12196
0
        return QRhiPassResourceTracker::BufTCStage;
12197
0
    if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
12198
0
        return QRhiPassResourceTracker::BufTEStage;
12199
0
    if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
12200
0
        return QRhiPassResourceTracker::BufFragmentStage;
12201
0
    if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
12202
0
        return QRhiPassResourceTracker::BufComputeStage;
12203
0
    if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
12204
0
        return QRhiPassResourceTracker::BufGeometryStage;
12205
12206
0
    Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::BufVertexStage);
12207
0
}
12208
12209
QRhiPassResourceTracker::TextureStage QRhiPassResourceTracker::toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
12210
0
{
12211
    // pick the earlier stage (as this is going to be dstAccessMask)
12212
0
    if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
12213
0
        return QRhiPassResourceTracker::TexVertexStage;
12214
0
    if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
12215
0
        return QRhiPassResourceTracker::TexTCStage;
12216
0
    if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
12217
0
        return QRhiPassResourceTracker::TexTEStage;
12218
0
    if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
12219
0
        return QRhiPassResourceTracker::TexFragmentStage;
12220
0
    if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
12221
0
        return QRhiPassResourceTracker::TexComputeStage;
12222
0
    if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
12223
0
        return QRhiPassResourceTracker::TexGeometryStage;
12224
12225
0
    Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::TexVertexStage);
12226
0
}
12227
12228
QSize QRhiImplementation::clampedSubResourceUploadSize(QSize size, QPoint dstPos, int level, QSize textureSizeAtLevelZero, bool warn)
12229
0
{
12230
0
    const QSize subResSize = q->sizeForMipLevel(level, textureSizeAtLevelZero);
12231
0
    const bool outOfBoundsHoriz = dstPos.x() + size.width() > subResSize.width();
12232
0
    const bool outOfBoundsVert = dstPos.y() + size.height() > subResSize.height();
12233
0
    if (Q_UNLIKELY(outOfBoundsHoriz || outOfBoundsVert)) {
12234
0
        if (warn) {
12235
0
            qWarning("Invalid texture upload issued; size %dx%d dst.position %d,%d dst.subresource size %dx%d; size will be clamped",
12236
0
                     size.width(), size.height(), dstPos.x(), dstPos.y(), subResSize.width(), subResSize.height());
12237
0
        }
12238
0
        if (outOfBoundsHoriz)
12239
0
            size.setWidth(subResSize.width() - dstPos.x());
12240
0
        if (outOfBoundsVert)
12241
0
            size.setHeight(subResSize.height() - dstPos.y());
12242
0
    }
12243
0
    return size;
12244
0
}
12245
12246
// Clamps size so that reading the image with a source row stride of bpl does
12247
// not go past dataSize bytes. bpl may be 0, meaning the data is tightly packed.
12248
// Returns a size with a height of 0 when not even a single row can be
12249
// satisfied, in which case the caller is expected to skip the copy.
12250
QSize QRhiImplementation::clampedSubResourceUploadSizeForSourceData(QSize size, quint32 bpl,
12251
                                                                    quint32 bytesPerPixel,
12252
                                                                    qsizetype dataSize, bool warn)
12253
0
{
12254
0
    if (size.isEmpty() || !bytesPerPixel)
12255
0
        return size;
12256
12257
0
    const quint64 rowBytes = quint64(bytesPerPixel) * quint64(size.width());
12258
0
    if (!bpl)
12259
0
        bpl = quint32(qMin(rowBytes, quint64(std::numeric_limits<quint32>::max())));
12260
12261
0
    if (quint64(bpl) < rowBytes) {
12262
0
        if (warn) {
12263
0
            qWarning("Invalid texture upload issued; source row stride %u is smaller than the %llu "
12264
0
                     "bytes a row of %d pixels needs; upload will be skipped",
12265
0
                     bpl, rowBytes, size.width());
12266
0
        }
12267
0
        return QSize(size.width(), 0);
12268
0
    }
12269
12270
    // Row y is read from y * bpl and needs rowBytes bytes, so the last row ends
12271
    // at (height - 1) * bpl + rowBytes.
12272
0
    const quint64 needed = quint64(bpl) * quint64(size.height() - 1) + rowBytes;
12273
0
    if (quint64(dataSize) >= needed)
12274
0
        return size;
12275
12276
0
    int rows = 0;
12277
0
    if (quint64(dataSize) >= rowBytes)
12278
0
        rows = int((quint64(dataSize) - rowBytes) / quint64(bpl)) + 1;
12279
12280
0
    if (warn) {
12281
0
        qWarning("Invalid texture upload issued; %lld bytes of data cannot back a %dx%d upload with "
12282
0
                 "source row stride %u (needs %llu bytes); height will be clamped to %d",
12283
0
                 qint64(dataSize), size.width(), size.height(), bpl, needed, rows);
12284
0
    }
12285
12286
0
    return QSize(size.width(), rows);
12287
0
}
12288
12289
QT_END_NAMESPACE