Coverage Report

Created: 2026-07-30 07:17

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