1/****************************************************************************
2**
3** Copyright (C) 2019 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the Qt Gui module
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "qrhi_p_p.h"
38#include <qmath.h>
39
40#include "qrhinull_p_p.h"
41#ifndef QT_NO_OPENGL
42#include "qrhigles2_p_p.h"
43#endif
44#if QT_CONFIG(vulkan)
45#include "qrhivulkan_p_p.h"
46#endif
47#ifdef Q_OS_WIN
48#include "qrhid3d11_p_p.h"
49#endif
50//#ifdef Q_OS_DARWIN
51#ifdef Q_OS_MACOS
52#include "qrhimetal_p_p.h"
53#endif
54
55QT_BEGIN_NAMESPACE
56
57/*!
58 \class QRhi
59 \inmodule QtRhi
60
61 \brief Accelerated 2D/3D graphics API abstraction.
62
63 The Qt Rendering Hardware Interface is an abstraction for hardware accelerated
64 graphics APIs, such as, \l{https://www.khronos.org/opengl/}{OpenGL},
65 \l{https://www.khronos.org/opengles/}{OpenGL ES},
66 \l{https://docs.microsoft.com/en-us/windows/desktop/direct3d}{Direct3D},
67 \l{https://developer.apple.com/metal/}{Metal}, and
68 \l{https://www.khronos.org/vulkan/}{Vulkan}.
69
70 Some of the main design goals are:
71
72 \list
73
74 \li Simple, minimal, understandable, extensible. Follow the proven path of the
75 Qt Quick scenegraph.
76
77 \li Aim to be a product - and in the bigger picture, part of a product (Qt) -
78 that is usable out of the box both by internal (such as, Qt Quick) and,
79 eventually, external users.
80
81 \li Not a complete 1:1 wrapper for any of the underlying APIs. The feature set
82 is tuned towards the needs of Qt's 2D and 3D offering (QPainter, Qt Quick, Qt
83 3D Studio). Iterate and evolve in a sustainable manner.
84
85 \li Intrinsically cross-platform, without reinventing: abstracting
86 cross-platform aspects of certain APIs (such as, OpenGL context creation and
87 windowing system interfaces, Vulkan instance and surface management) is not in
88 scope here. These are delegated to the existing QtGui facilities (QWindow,
89 QOpenGLContext, QVulkanInstance) and its backing QPA architecture.
90
91 \endlist
92
93 Each QRhi instance is backed by a backend for a specific graphics API. The
94 selection of the backend is a run time choice and is up to the application
95 or library that creates the QRhi instance. Some backends are available on
96 multiple platforms (OpenGL, Vulkan, Null), while APIs specific to a given
97 platform are only available when running on the platform in question (Metal
98 on macOS/iOS/tvOS, Direct3D on Windows).
99
100 The available backends currently are:
101
102 \list
103
104 \li OpenGL 2.1 or OpenGL ES 2.0 or newer. Some extensions are utilized when
105 present, for example to enable multisample framebuffers.
106
107 \li Direct3D 11.1
108
109 \li Metal
110
111 \li Vulkan 1.0, optionally with some extensions that are part of Vulkan 1.1
112
113 \li Null - A "dummy" backend that issues no graphics calls at all.
114
115 \endlist
116
117 In order to allow shader code to be written once in Qt applications and
118 libraries, all shaders are expected to be written in a single language
119 which is then compiled into SPIR-V. Versions for various shading language
120 are then generated from that, together with reflection information (inputs,
121 outputs, shader resources). This is then packed into easily and efficiently
122 serializable QShader instances. The compilers and tools to generate such
123 shaders are not part of QRhi, but the core classes for using such shaders,
124 QShader and QShaderDescription, are.
125
126 \section2 Design Fundamentals
127
128 A QRhi cannot be instantiated directly. Instead, use the create()
129 function. Delete the QRhi instance normally to release the graphics device.
130
131 \section3 Resources
132
133 Instances of classes deriving from QRhiResource, such as, QRhiBuffer,
134 QRhiTexture, etc., encapsulate zero, one, or more native graphics
135 resources. Instances of such classes are always created via the \c new
136 functions of the QRhi, such as, newBuffer(), newTexture(),
137 newTextureRenderTarget(), newSwapChain().
138
139 \badcode
140 vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
141 if (!vbuf->build()) { error }
142 ...
143 delete vbuf;
144 \endcode
145
146 \list
147
148 \li The returned value from both create() and functions like newBuffer() is
149 owned by the caller.
150
151 \li Just creating a QRhiResource subclass never allocates or initializes any
152 native resources. That is only done when calling the \c build function of a
153 subclass, for example, QRhiBuffer::build() or QRhiTexture::build().
154
155 \li The exception is
156 QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() and
157 QRhiSwapChain::newCompatibleRenderPassDescriptor(). There is no \c build
158 operation for these and the returned object is immediately active.
159
160 \li The resource objects themselves are treated as immutable: once a
161 resource is built, changing any parameters via the setters, such as,
162 QRhiTexture::setPixelSize(), has no effect, unless the underlying native
163 resource is released and \c build is called again. See more about resource
164 reuse in the sections below.
165
166 \li The underlying native resources are scheduled for releasing by the
167 QRhiResource destructor, or by calling QRhiResource::release(). Backends
168 often queue release requests and defer executing them to an unspecified
169 time, this is hidden from the applications. This way applications do not
170 have to worry about releasing native resources that may still be in use by
171 an in-flight frame.
172
173 \li Note that this does not mean that a QRhiResource can freely be
174 destroyed or release()'d within a frame (that is, in a
175 \l{QRhiCommandBuffer::beginFrame()}{beginFrame()} -
176 \l{QRhiCommandBuffer::endFrame()}{endFrame()} section). As a general rule,
177 all referenced QRhiResource objects must stay unchanged until the frame is
178 submitted by calling \l{QRhiCommandBuffer::endFrame()}{endFrame()}. To ease
179 this, QRhiResource::releaseAndDestroyLater() is provided as a convenience.
180
181 \endlist
182
183 \section3 Command buffers and deferred command execution
184
185 Regardless of the design and capabilities of the underlying graphics API,
186 all QRhi backends implement some level of command buffers. No
187 QRhiCommandBuffer function issues any native bind or draw command (such as,
188 \c glDrawElements) directly. Commands are always recorded in a queue,
189 either native or provided by the QRhi backend. The command buffer is
190 submitted, and so execution starts only upon QRhi::endFrame() or
191 QRhi::finish().
192
193 The deferred nature has consequences for some types of objects. For example,
194 writing to a dynamic buffer multiple times within a frame, in case such
195 buffers are backed by host-visible memory, will result in making the
196 results of all writes are visible to all draw calls in the command buffer
197 of the frame, regardless of when the dynamic buffer update was recorded
198 relative to a draw call.
199
200 Furthermore, instances of QRhiResource subclasses must be treated immutable
201 within a frame in which they are referenced in any way. Create or rebuild
202 all resources upfront, before starting to record commands for the next
203 frame. Reusing a QRhiResource instance within a frame (by rebuilding it and
204 then referencing it again in the same \c{beginFrame - endFrame} section)
205 should be avoided as it may lead to unexpected results, depending on the
206 backend.
207
208 As a general rule, all referenced QRhiResource objects must stay valid and
209 unmodified until the frame is submitted by calling
210 \l{QRhiCommandBuffer::endFrame()}{endFrame()}. On the other hand, calling
211 \l{QRhiResource::release()}{release()} or destroying the QRhiResource are
212 always safe once the frame is submitted, regardless of the status of the
213 underlying native resources (which may still be in use by the GPU - but
214 that is taken care of internally).
215
216 Unlike APIs like OpenGL, upload and copy type of commands cannot be mixed
217 with draw commands. The typical renderer will involve a sequence similar to
218 the following: \c{(re)build resources} - \c{begin frame} - \c{record
219 uploads and copies} - \c{start renderpass} - \c{record draw calls} - \c{end
220 renderpass} - \c{end frame}. Recording copy type of operations happens via
221 QRhiResourceUpdateBatch. Such operations are committed typically on
222 \l{QRhiCommandBuffer::beginPass()}{beginPass()}.
223
224 When working with legacy rendering engines designed for OpenGL, the
225 migration to QRhi often involves redesigning from having a single \c render
226 step (that performs copies and uploads, clears buffers, and issues draw
227 calls, all mixed together) to a clearly separated, two phase \c prepare -
228 \c render setup where the \c render step only starts a renderpass and
229 records draw calls, while all resource creation and queuing of updates,
230 uploads and copies happens beforehand, in the \c prepare step.
231
232 QRhi does not at the moment allow freely creating and submitting command
233 buffers. This may be lifted in the future to some extent, in particular if
234 compute support is introduced, but the model of well defined
235 \c{frame-start} and \c{frame-end} points, combined with a dedicated,
236 "frame" command buffer, where \c{frame-end} implies presenting, is going to
237 remain the primary way of operating since this is what fits Qt's various UI
238 technologies best.
239
240 \section3 Threading
241
242 A QRhi instance and the associated resources can be created and used on any
243 thread but all usage must be limited to that one single thread. When
244 rendering to multiple QWindows in an application, having a dedicated thread
245 and QRhi instance for each window is often advisable, as this can eliminate
246 issues with unexpected throttling caused by presenting to multiple windows.
247 Conceptually that is then the same as how Qt Quick scene graph's threaded
248 render loop operates when working directly with OpenGL: one thread for each
249 window, one QOpenGLContext for each thread. When moving onto QRhi,
250 QOpenGLContext is replaced by QRhi, making the migration straightforward.
251
252 When it comes to externally created native objects, such as OpenGL contexts
253 passed in via QRhiGles2NativeHandles, it is up to the application to ensure
254 they are not misused by other threads.
255
256 Resources are not shareable between QRhi instances. This is an intentional
257 choice since QRhi hides most queue, command buffer, and resource
258 synchronization related tasks, and provides no API for them. Safe and
259 efficient concurrent use of graphics resources from multiple threads is
260 tied to those concepts, however, and is thus a topic that is currently out
261 of scope, but may be introduced in the future.
262
263 \note The Metal backend requires that an autorelease pool is available on
264 the rendering thread, ideally wrapping each iteration of the render loop.
265 This needs no action from the users of QRhi when rendering on the main
266 (gui) thread, but becomes important when a separate, dedicated render
267 thread is used.
268
269 \section3 Resource synchronization
270
271 QRhi does not expose APIs for resource barriers or image layout
272 transitions. Such synchronization is done implicitly by the backends, where
273 applicable (for example, Vulkan), by tracking resource usage as necessary.
274
275 \note Resources within a render or compute pass are expected to be bound to
276 a single usage during that pass. For example, a buffer can be used as
277 vertex, index, uniform, or storage buffer, but not a combination of them
278 within a single pass. However, it is perfectly fine to use a buffer as a
279 storage buffer in a compute pass, and then as a vertex buffer in a render
280 pass, for example, assuming the buffer declared both usages upon creation.
281
282 \note Textures have this rule relaxed in certain cases, because using two
283 subresources (typically two different mip levels) of the same texture for
284 different access (one for load, one for store) is supported even within the
285 same pass.
286
287 \section3 Resource reuse
288
289 From the user's point of view a QRhiResource is reusable immediately after
290 calling QRhiResource::release(). With the exception of swapchains, calling
291 \c build() on an already built object does an implicit \c release(). This
292 provides a handy shortcut to reuse a QRhiResource instance with different
293 parameters, with a new native graphics object underneath.
294
295 The importance of reusing the same object lies in the fact that some
296 objects reference other objects: for example, a QRhiShaderResourceBindings
297 can reference QRhiBuffer, QRhiTexture, and QRhiSampler instances. If in a
298 later frame one of these buffers need to be resized or a sampler parameter
299 needs changing, destroying and creating a whole new QRhiBuffer or
300 QRhiSampler would invalidate all references to the old instance. By just
301 changing the appropriate parameters via QRhiBuffer::setSize() or similar
302 and then calling QRhiBuffer::build(), everything works as expected and
303 there is no need to touch the QRhiShaderResourceBindings at all, even
304 though there is a good chance that under the hood the QRhiBuffer is now
305 backed by a whole new native buffer.
306
307 \badcode
308 ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 256);
309 ubuf->build();
310
311 srb = rhi->newShaderResourceBindings()
312 srb->setBindings({
313 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf)
314 });
315 srb->build();
316
317 ...
318
319 // now in a later frame we need to grow the buffer to a larger size
320 ubuf->setSize(512);
321 ubuf->build(); // same as ubuf->release(); ubuf->build();
322
323 // that's it, srb needs no changes whatsoever
324 \endcode
325
326 \section3 Pooled objects
327
328 In addition to resources, there are pooled objects as well, such as,
329 QRhiResourceUpdateBatch. An instance is retrieved via a \c next function,
330 such as, nextResourceUpdateBatch(). The caller does not own the returned
331 instance in this case. The only valid way of operating here is calling
332 functions on the QRhiResourceUpdateBatch and then passing it to
333 QRhiCommandBuffer::beginPass() or QRhiCommandBuffer::endPass(). These
334 functions take care of returning the batch to the pool. Alternatively, a
335 batch can be "canceled" and returned to the pool without processing by
336 calling QRhiResourceUpdateBatch::release().
337
338 A typical pattern is thus:
339
340 \badcode
341 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
342 ...
343 resUpdates->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
344 if (!image.isNull()) {
345 resUpdates->uploadTexture(texture, image);
346 image = QImage();
347 }
348 ...
349 QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
350 cb->beginPass(swapchain->currentFrameRenderTarget(), clearCol, clearDs, resUpdates);
351 \endcode
352
353 \section3 Swapchain specifics
354
355 QRhiSwapChain features some special semantics due to the peculiar nature of
356 swapchains.
357
358 \list
359
360 \li It has no \c build but rather a QRhiSwapChain::buildOrResize().
361 Repeatedly calling this function is \b not the same as calling
362 QRhiSwapChain::release() followed by QRhiSwapChain::buildOrResize(). This
363 is because swapchains often have ways to handle the case where buffers need
364 to be resized in a manner that is more efficient than a brute force
365 destroying and recreating from scratch.
366
367 \li An active QRhiSwapChain must be released by calling
368 \l{QRhiSwapChain::release()}{release()}, or by destroying the object, before
369 the QWindow's underlying QPlatformWindow, and so the associated native
370 window object, is destroyed. It should not be postponed because releasing
371 the swapchain may become problematic (and with some APIs, like Vulkan, is
372 explicitly disallowed) when the native window is not around anymore, for
373 example because the QPlatformWindow got destroyed upon getting a
374 QWindow::close(). Therefore, releasing the swapchain must happen whenever
375 the targeted QWindow sends the
376 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed event. If the event does
377 not arrive before the destruction of the QWindow - this can happen when
378 using QCoreApplication::quit() -, then check QWindow::handle() after the
379 event loop exits and invoke the swapchain release when non-null (meaning
380 the underlying native window is still around).
381
382 \endlist
383
384 \section3 Ownership
385
386 The general rule is no ownership transfer. Creating a QRhi with an already
387 existing graphics device does not mean the QRhi takes ownership of the
388 device object. Similarly, ownership is not given away when a device or
389 texture object is "exported" via QRhi::nativeHandles() or
390 QRhiTexture::nativeHandles(). Most importantly, passing pointers in structs
391 and via setters does not transfer ownership.
392 */
393
394/*!
395 \enum QRhi::Implementation
396 Describes which graphics API-specific backend gets used by a QRhi instance.
397
398 \value Null
399 \value Vulkan
400 \value OpenGLES2
401 \value D3D11
402 \value Metal
403 */
404
405/*!
406 \enum QRhi::Flag
407 Describes what special features to enable.
408
409 \value EnableProfiling Enables gathering timing (CPU, GPU) and resource
410 (QRhiBuffer, QRhiTexture, etc.) information and additional metadata. See
411 QRhiProfiler. Avoid enabling in production builds as it may involve a
412 performance penalty.
413
414 \value EnableDebugMarkers Enables debug marker groups. Without this frame
415 debugging features like making debug groups and custom resource name
416 visible in external GPU debugging tools will not be available and functions
417 like QRhiCommandBuffer::debugMarkBegin() will become a no-op. Avoid
418 enabling in production builds as it may involve a performance penalty.
419 */
420
421/*!
422 \enum QRhi::FrameOpResult
423 Describes the result of operations that can have a soft failure.
424
425 \value FrameOpSuccess Success
426
427 \value FrameOpError Unspecified error
428
429 \value FrameOpSwapChainOutOfDate The swapchain is in an inconsistent state
430 internally. This can be recoverable by attempting to repeat the operation
431 (such as, beginFrame()) later.
432
433 \value FrameOpDeviceLost The graphics device was lost. This can be
434 recoverable by attempting to repeat the operation (such as, beginFrame())
435 and releasing and reinitializing all objects backed by native graphics
436 resources.
437 */
438
439/*!
440 \enum QRhi::Feature
441 Flag values to indicate what features are supported by the backend currently in use.
442
443 \value MultisampleTexture Indicates that textures with a sample count larger
444 than 1 are supported.
445
446 \value MultisampleRenderBuffer Indicates that renderbuffers with a sample
447 count larger than 1 are supported.
448
449 \value DebugMarkers Indicates that debug marker groups (and so
450 QRhiCommandBuffer::debugMarkBegin()) are supported.
451
452 \value Timestamps Indicates that command buffer timestamps are supported.
453 Relevant for QRhiProfiler::gpuFrameTimes().
454
455 \value Instancing Indicates that instanced drawing is supported.
456
457 \value CustomInstanceStepRate Indicates that instance step rates other than
458 1 are supported.
459
460 \value PrimitiveRestart Indicates that restarting the assembly of
461 primitives when encountering an index value of 0xFFFF
462 (\l{QRhiCommandBuffer::IndexUInt16}{IndexUInt16}) or 0xFFFFFFFF
463 (\l{QRhiCommandBuffer::IndexUInt32}{IndexUInt32}) is enabled, for certain
464 primitive topologies at least. QRhi will try to enable this with all
465 backends, but in some cases it will not be supported. Dynamically
466 controlling primitive restart is not possible since with some APIs
467 primitive restart with a fixed index is always on. Applications must assume
468 that whenever this feature is reported as supported, the above mentioned
469 index values \c may be treated specially, depending on the topology. The
470 only two topologies where primitive restart is guaranteed to behave
471 identically across backends, as long as this feature is reported as
472 supported, are \l{QRhiGraphicsPipeline::LineStrip}{LineStrip} and
473 \l{QRhiGraphicsPipeline::TriangleStrip}{TriangleStrip}.
474
475 \value NonDynamicUniformBuffers Indicates that creating buffers with the
476 usage \l{QRhiBuffer::UniformBuffer}{UniformBuffer} and the types
477 \l{QRhiBuffer::Immutable}{Immutable} or \l{QRhiBuffer::Static}{Static} is
478 supported. When reported as unsupported, uniform (constant) buffers must be
479 created as \l{QRhiBuffer::Dynamic}{Dynamic}. (which is recommended
480 regardless)
481
482 \value NonFourAlignedEffectiveIndexBufferOffset Indicates that effective
483 index buffer offsets (\c{indexOffset + firstIndex * indexComponentSize})
484 that are not 4 byte aligned are supported. When not supported, attempting
485 to issue a \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} with a
486 non-aligned effective offset may lead to unspecified behavior.
487
488 \value NPOTTextureRepeat Indicates that the \l{QRhiSampler::Repeat}{Repeat}
489 mode is supported for textures with a non-power-of-two size.
490
491 \value RedOrAlpha8IsRed Indicates that the
492 \l{QRhiTexture::RED_OR_ALPHA8}{RED_OR_ALPHA8} format maps to a one
493 component 8-bit \c red format. This is the case for all backends except
494 OpenGL, where \c{GL_ALPHA}, a one component 8-bit \c alpha format, is used
495 instead. This is relevant for shader code that samples from the texture.
496
497 \value ElementIndexUint Indicates that 32-bit unsigned integer elements are
498 supported in the index buffer. In practice this is true everywhere except
499 when running on plain OpenGL ES 2.0 implementations without the necessary
500 extension. When false, only 16-bit unsigned elements are supported in the
501 index buffer.
502
503 \value Compute Indicates that compute shaders, image load/store, and
504 storage buffers are supported.
505
506 \value WideLines Indicates that lines with a width other than 1 are
507 supported. When reported as not supported, the line width set on the
508 graphics pipeline state is ignored. This can always be false with some
509 backends (D3D11, Metal). With Vulkan, the value depends on the
510 implementation.
511
512 \value VertexShaderPointSize Indicates that the size of rasterized points
513 set via \c{gl_PointSize} in the vertex shader is taken into account. When
514 reported as not supported, drawing points with a size other than 1 is not
515 supported. Setting \c{gl_PointSize} in the shader is still valid then, but
516 is ignored. (for example, when generating HLSL, the assignment is silently
517 dropped from the generated code) Note that some APIs (Metal, Vulkan)
518 require the point size to be set in the shader explicitly whenever drawing
519 points, even when the size is 1, as they do not automatically default to 1.
520
521 \value BaseVertex Indicates that \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()}
522 supports the \c vertexOffset argument. When reported as not supported, the
523 vertexOffset value in an indexed draw is ignored.
524
525 \value BaseInstance Indicates that instanced draw commands support the \c
526 firstInstance argument. When reported as not supported, the firstInstance
527 value is ignored and the instance ID starts from 0.
528 */
529
530/*!
531 \enum QRhi::BeginFrameFlag
532 Flag values for QRhi::beginFrame()
533 */
534
535/*!
536 \enum QRhi::EndFrameFlag
537 Flag values for QRhi::endFrame()
538
539 \value SkipPresent Specifies that no present command is to be queued or no
540 swapBuffers call is to be made. This way no image is presented. Generating
541 multiple frames with all having this flag set is not recommended (except,
542 for example, for benchmarking purposes - but keep in mind that backends may
543 behave differently when it comes to waiting for command completion without
544 presenting so the results are not comparable between them)
545 */
546
547/*!
548 \enum QRhi::ResourceLimit
549 Describes the resource limit to query.
550
551 \value TextureSizeMin Minimum texture width and height. This is typically
552 1. The minimum texture size is handled gracefully, meaning attempting to
553 create a texture with an empty size will instead create a texture with the
554 minimum size.
555
556 \value TextureSizeMax Maximum texture width and height. This depends on the
557 graphics API and sometimes the platform or implementation as well.
558 Typically the value is in the range 4096 - 16384. Attempting to create
559 textures larger than this is expected to fail.
560
561 \value MaxColorAttachments The maximum number of color attachments for a
562 QRhiTextureRenderTarget, in case multiple render targets are supported. When
563 MRT is not supported, the value is 1. Otherwise this is typically 8, but
564 watch out for the fact that OpenGL only mandates 4 as the minimum, and that
565 is what some OpenGL ES implementations provide.
566
567 \value FramesInFlight The number of frames the backend may keep "in
568 flight". The value has no relevance, and is unspecified, with backends like
569 OpenGL and Direct3D 11. With backends like Vulkan or Metal, it is the
570 responsibility of QRhi to block whenever starting a new frame and finding
571 the CPU is already \c{N - 1} frames ahead of the GPU (because the command
572 buffer submitted in frame no. \c{current} - \c{N} has not yet completed).
573 The value N is what is returned from here, and is typically 2. This can be
574 relevant to applications that integrate rendering done directly with the
575 graphics API, as such rendering code may want to perform double (if the
576 value is 2) buffering for resources, such as, buffers, similarly to the
577 QRhi backends themselves. The current frame slot index (a value running 0,
578 1, .., N-1, then wrapping around) is retrievable from
579 QRhi::currentFrameSlot().
580 */
581
582/*!
583 \class QRhiInitParams
584 \inmodule QtRhi
585 \brief Base class for backend-specific initialization parameters.
586
587 Contains fields that are relevant to all backends.
588 */
589
590/*!
591 \class QRhiDepthStencilClearValue
592 \inmodule QtRhi
593 \brief Specifies clear values for a depth or stencil buffer.
594 */
595
596/*!
597 \fn QRhiDepthStencilClearValue::QRhiDepthStencilClearValue()
598
599 Constructs a depth/stencil clear value with depth clear value 1.0f and
600 stencil clear value 0.
601 */
602
603/*!
604 Constructs a depth/stencil clear value with depth clear value \a d and
605 stencil clear value \a s.
606 */
607QRhiDepthStencilClearValue::QRhiDepthStencilClearValue(float d, quint32 s)
608 : m_d(d),
609 m_s(s)
610{
611}
612
613/*!
614 \return \c true if the values in the two QRhiDepthStencilClearValue objects
615 \a a and \a b are equal.
616
617 \relates QRhiDepthStencilClearValue
618 */
619bool operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) Q_DECL_NOTHROW
620{
621 return a.depthClearValue() == b.depthClearValue()
622 && a.stencilClearValue() == b.stencilClearValue();
623}
624
625/*!
626 \return \c false if the values in the two QRhiDepthStencilClearValue
627 objects \a a and \a b are equal; otherwise returns \c true.
628
629 \relates QRhiDepthStencilClearValue
630*/
631bool operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) Q_DECL_NOTHROW
632{
633 return !(a == b);
634}
635
636/*!
637 \return the hash value for \a v, using \a seed to seed the calculation.
638
639 \relates QRhiDepthStencilClearValue
640 */
641uint qHash(const QRhiDepthStencilClearValue &v, uint seed) Q_DECL_NOTHROW
642{
643 return seed * (qFloor(v.depthClearValue() * 100) + v.stencilClearValue());
644}
645
646#ifndef QT_NO_DEBUG_STREAM
647QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
648{
649 QDebugStateSaver saver(dbg);
650 dbg.nospace() << "QRhiDepthStencilClearValue(depth-clear=" << v.depthClearValue()
651 << " stencil-clear=" << v.stencilClearValue()
652 << ')';
653 return dbg;
654}
655#endif
656
657/*!
658 \class QRhiViewport
659 \inmodule QtRhi
660 \brief Specifies a viewport rectangle.
661
662 Used with QRhiCommandBuffer::setViewport().
663
664 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
665 bottom-left.
666
667 Typical usage is like the following:
668
669 \badcode
670 const QSize outputSizeInPixels = swapchain->currentPixelSize();
671 const QRhiViewport viewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height());
672 cb->beginPass(swapchain->currentFrameRenderTarget(), { 0, 0, 0, 1 }, { 1, 0 });
673 cb->setGraphicsPipeline(ps);
674 cb->setViewport(viewport);
675 ...
676 \endcode
677
678 \sa QRhiCommandBuffer::setViewport(), QRhi::clipSpaceCorrMatrix(), QRhiScissor
679 */
680
681/*!
682 \fn QRhiViewport::QRhiViewport()
683
684 Constructs a viewport description with an empty rectangle and a depth range
685 of 0.0f - 1.0f.
686
687 \sa QRhi::clipSpaceCorrMatrix()
688 */
689
690/*!
691 Constructs a viewport description with the rectangle specified by \a x, \a
692 y, \a w, \a h and the depth range \a minDepth and \a maxDepth.
693
694 \note x and y are assumed to be the bottom-left position.
695
696 \sa QRhi::clipSpaceCorrMatrix()
697 */
698QRhiViewport::QRhiViewport(float x, float y, float w, float h, float minDepth, float maxDepth)
699 : m_rect { { x, y, w, h } },
700 m_minDepth(minDepth),
701 m_maxDepth(maxDepth)
702{
703}
704
705/*!
706 \return \c true if the values in the two QRhiViewport objects
707 \a a and \a b are equal.
708
709 \relates QRhiViewport
710 */
711bool operator==(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW
712{
713 return a.viewport() == b.viewport()
714 && a.minDepth() == b.minDepth()
715 && a.maxDepth() == b.maxDepth();
716}
717
718/*!
719 \return \c false if the values in the two QRhiViewport
720 objects \a a and \a b are equal; otherwise returns \c true.
721
722 \relates QRhiViewport
723*/
724bool operator!=(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW
725{
726 return !(a == b);
727}
728
729/*!
730 \return the hash value for \a v, using \a seed to seed the calculation.
731
732 \relates QRhiViewport
733 */
734uint qHash(const QRhiViewport &v, uint seed) Q_DECL_NOTHROW
735{
736 const std::array<float, 4> r = v.viewport();
737 return seed + r[0] + r[1] + r[2] + r[3] + qFloor(v.minDepth() * 100) + qFloor(v.maxDepth() * 100);
738}
739
740#ifndef QT_NO_DEBUG_STREAM
741QDebug operator<<(QDebug dbg, const QRhiViewport &v)
742{
743 QDebugStateSaver saver(dbg);
744 const std::array<float, 4> r = v.viewport();
745 dbg.nospace() << "QRhiViewport(bottom-left-x=" << r[0]
746 << " bottom-left-y=" << r[1]
747 << " width=" << r[2]
748 << " height=" << r[3]
749 << " minDepth=" << v.minDepth()
750 << " maxDepth=" << v.maxDepth()
751 << ')';
752 return dbg;
753}
754#endif
755
756/*!
757 \class QRhiScissor
758 \inmodule QtRhi
759 \brief Specifies a scissor rectangle.
760
761 Used with QRhiCommandBuffer::setScissor(). Setting a scissor rectangle is
762 only possible with a QRhiGraphicsPipeline that has
763 QRhiGraphicsPipeline::UsesScissor set.
764
765 \note QRhi assumes OpenGL-style scissor coordinates, meaning x and y are
766 bottom-left.
767
768 \sa QRhiCommandBuffer::setScissor(), QRhiViewport
769 */
770
771/*!
772 \fn QRhiScissor::QRhiScissor()
773
774 Constructs an empty scissor.
775 */
776
777/*!
778 Constructs a scissor with the rectangle specified by \a x, \a y, \a w, and
779 \a h.
780
781 \note x and y are assumed to be the bottom-left position.
782 */
783QRhiScissor::QRhiScissor(int x, int y, int w, int h)
784 : m_rect { { x, y, w, h } }
785{
786}
787
788/*!
789 \return \c true if the values in the two QRhiScissor objects
790 \a a and \a b are equal.
791
792 \relates QRhiScissor
793 */
794bool operator==(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW
795{
796 return a.scissor() == b.scissor();
797}
798
799/*!
800 \return \c false if the values in the two QRhiScissor
801 objects \a a and \a b are equal; otherwise returns \c true.
802
803 \relates QRhiScissor
804*/
805bool operator!=(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW
806{
807 return !(a == b);
808}
809
810/*!
811 \return the hash value for \a v, using \a seed to seed the calculation.
812
813 \relates QRhiScissor
814 */
815uint qHash(const QRhiScissor &v, uint seed) Q_DECL_NOTHROW
816{
817 const std::array<int, 4> r = v.scissor();
818 return seed + r[0] + r[1] + r[2] + r[3];
819}
820
821#ifndef QT_NO_DEBUG_STREAM
822QDebug operator<<(QDebug dbg, const QRhiScissor &s)
823{
824 QDebugStateSaver saver(dbg);
825 const std::array<int, 4> r = s.scissor();
826 dbg.nospace() << "QRhiScissor(bottom-left-x=" << r[0]
827 << " bottom-left-y=" << r[1]
828 << " width=" << r[2]
829 << " height=" << r[3]
830 << ')';
831 return dbg;
832}
833#endif
834
835/*!
836 \class QRhiVertexInputBinding
837 \inmodule QtRhi
838 \brief Describes a vertex input binding.
839
840 Specifies the stride (in bytes, must be a multiple of 4), the
841 classification and optionally the instance step rate.
842
843 As an example, assume a vertex shader with the following inputs:
844
845 \badcode
846 layout(location = 0) in vec4 position;
847 layout(location = 1) in vec2 texcoord;
848 \endcode
849
850 Now let's assume also that 3 component vertex positions \c{(x, y, z)} and 2
851 component texture coordinates \c{(u, v)} are provided in a non-interleaved
852 format in a buffer (or separate buffers even). Definining two bindings
853 could then be done like this:
854
855 \badcode
856 QRhiVertexInputLayout inputLayout;
857 inputLayout.setBindings({
858 { 3 * sizeof(float) },
859 { 2 * sizeof(float) }
860 });
861 \endcode
862
863 Only the stride is interesting here since instancing is not used. The
864 binding number is given by the index of the QRhiVertexInputBinding
865 element in the bindings vector of the QRhiVertexInputLayout.
866
867 Once a graphics pipeline with this vertex input layout is bound, the vertex
868 inputs could be set up like the following for drawing a cube with 36
869 vertices, assuming we have a single buffer with first the positions and
870 then the texture coordinates:
871
872 \badcode
873 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
874 { cubeBuf, 0 },
875 { cubeBuf, 36 * 3 * sizeof(float) }
876 };
877 cb->setVertexInput(0, 2, vbufBindings);
878 \endcode
879
880 Note how the index defined by \c {startBinding + i}, where \c i is the
881 index in the second argument of
882 \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}, matches the
883 index of the corresponding entry in the \c bindings vector of the
884 QRhiVertexInputLayout.
885
886 \note the stride must always be a multiple of 4.
887
888 \sa QRhiCommandBuffer::setVertexInput()
889 */
890
891/*!
892 \enum QRhiVertexInputBinding::Classification
893 Describes the input data classification.
894
895 \value PerVertex Data is per-vertex
896 \value PerInstance Data is per-instance
897 */
898
899/*!
900 \fn QRhiVertexInputBinding::QRhiVertexInputBinding()
901
902 Constructs a default vertex input binding description.
903 */
904
905/*!
906 Constructs a vertex input binding description with the specified \a stride,
907 classification \a cls, and instance step rate \a stepRate.
908
909 \note \a stepRate other than 1 is only supported when
910 QRhi::CustomInstanceStepRate is reported to be supported.
911 */
912QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cls, int stepRate)
913 : m_stride(stride),
914 m_classification(cls),
915 m_instanceStepRate(stepRate)
916{
917}
918
919/*!
920 \return \c true if the values in the two QRhiVertexInputBinding objects
921 \a a and \a b are equal.
922
923 \relates QRhiVertexInputBinding
924 */
925bool operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) Q_DECL_NOTHROW
926{
927 return a.stride() == b.stride()
928 && a.classification() == b.classification()
929 && a.instanceStepRate() == b.instanceStepRate();
930}
931
932/*!
933 \return \c false if the values in the two QRhiVertexInputBinding
934 objects \a a and \a b are equal; otherwise returns \c true.
935
936 \relates QRhiVertexInputBinding
937*/
938bool operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) Q_DECL_NOTHROW
939{
940 return !(a == b);
941}
942
943/*!
944 \return the hash value for \a v, using \a seed to seed the calculation.
945
946 \relates QRhiVertexInputBinding
947 */
948uint qHash(const QRhiVertexInputBinding &v, uint seed) Q_DECL_NOTHROW
949{
950 return seed + v.stride() + v.classification();
951}
952
953#ifndef QT_NO_DEBUG_STREAM
954QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
955{
956 QDebugStateSaver saver(dbg);
957 dbg.nospace() << "QRhiVertexInputBinding(stride=" << b.stride()
958 << " cls=" << b.classification()
959 << " step-rate=" << b.instanceStepRate()
960 << ')';
961 return dbg;
962}
963#endif
964
965/*!
966 \class QRhiVertexInputAttribute
967 \inmodule QtRhi
968 \brief Describes a single vertex input element.
969
970 The members specify the binding number, location, format, and offset for a
971 single vertex input element.
972
973 \note For HLSL it is assumed that the vertex shader uses
974 \c{TEXCOORD<location>} as the semantic for each input. Hence no separate
975 semantic name and index.
976
977 As an example, assume a vertex shader with the following inputs:
978
979 \badcode
980 layout(location = 0) in vec4 position;
981 layout(location = 1) in vec2 texcoord;
982 \endcode
983
984 Now let's assume that we have 3 component vertex positions \c{(x, y, z)}
985 and 2 component texture coordinates \c{(u, v)} are provided in a
986 non-interleaved format in a buffer (or separate buffers even). Once two
987 bindings are defined, the attributes could be specified as:
988
989 \badcode
990 QRhiVertexInputLayout inputLayout;
991 inputLayout.setBindings({
992 { 3 * sizeof(float) },
993 { 2 * sizeof(float) }
994 });
995 inputLayout.setAttributes({
996 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
997 { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
998 });
999 \endcode
1000
1001 Once a graphics pipeline with this vertex input layout is bound, the vertex
1002 inputs could be set up like the following for drawing a cube with 36
1003 vertices, assuming we have a single buffer with first the positions and
1004 then the texture coordinates:
1005
1006 \badcode
1007 const QRhiCommandBuffer::VertexInput vbufBindings[] = {
1008 { cubeBuf, 0 },
1009 { cubeBuf, 36 * 3 * sizeof(float) }
1010 };
1011 cb->setVertexInput(0, 2, vbufBindings);
1012 \endcode
1013
1014 When working with interleaved data, there will typically be just one
1015 binding, with multiple attributes referring to that same buffer binding
1016 point:
1017
1018 \badcode
1019 QRhiVertexInputLayout inputLayout;
1020 inputLayout.setBindings({
1021 { 5 * sizeof(float) }
1022 });
1023 inputLayout.setAttributes({
1024 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
1025 { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
1026 });
1027 \endcode
1028
1029 and then:
1030
1031 \badcode
1032 const QRhiCommandBuffer::VertexInput vbufBinding(interleavedCubeBuf, 0);
1033 cb->setVertexInput(0, 1, &vbufBinding);
1034 \endcode
1035
1036 \sa QRhiCommandBuffer::setVertexInput()
1037 */
1038
1039/*!
1040 \enum QRhiVertexInputAttribute::Format
1041 Specifies the type of the element data.
1042
1043 \value Float4 Four component float vector
1044 \value Float3 Three component float vector
1045 \value Float2 Two component float vector
1046 \value Float Float
1047 \value UNormByte4 Four component normalized unsigned byte vector
1048 \value UNormByte2 Two component normalized unsigned byte vector
1049 \value UNormByte Normalized unsigned byte
1050 */
1051
1052/*!
1053 \fn QRhiVertexInputAttribute::QRhiVertexInputAttribute()
1054
1055 Constructs a default vertex input attribute description.
1056 */
1057
1058/*!
1059 Constructs a vertex input attribute description with the specified \a
1060 binding number, \a location, \a format, and \a offset.
1061 */
1062QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset)
1063 : m_binding(binding),
1064 m_location(location),
1065 m_format(format),
1066 m_offset(offset)
1067{
1068}
1069
1070/*!
1071 \return \c true if the values in the two QRhiVertexInputAttribute objects
1072 \a a and \a b are equal.
1073
1074 \relates QRhiVertexInputAttribute
1075 */
1076bool operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) Q_DECL_NOTHROW
1077{
1078 return a.binding() == b.binding()
1079 && a.location() == b.location()
1080 && a.format() == b.format()
1081 && a.offset() == b.offset();
1082}
1083
1084/*!
1085 \return \c false if the values in the two QRhiVertexInputAttribute
1086 objects \a a and \a b are equal; otherwise returns \c true.
1087
1088 \relates QRhiVertexInputAttribute
1089*/
1090bool operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) Q_DECL_NOTHROW
1091{
1092 return !(a == b);
1093}
1094
1095/*!
1096 \return the hash value for \a v, using \a seed to seed the calculation.
1097
1098 \relates QRhiVertexInputAttribute
1099 */
1100uint qHash(const QRhiVertexInputAttribute &v, uint seed) Q_DECL_NOTHROW
1101{
1102 return seed + v.binding() + v.location() + v.format() + v.offset();
1103}
1104
1105#ifndef QT_NO_DEBUG_STREAM
1106QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a)
1107{
1108 QDebugStateSaver saver(dbg);
1109 dbg.nospace() << "QRhiVertexInputAttribute(binding=" << a.binding()
1110 << " location=" << a.location()
1111 << " format=" << a.format()
1112 << " offset=" << a.offset()
1113 << ')';
1114 return dbg;
1115}
1116#endif
1117
1118/*!
1119 \class QRhiVertexInputLayout
1120 \inmodule QtRhi
1121 \brief Describes the layout of vertex inputs consumed by a vertex shader.
1122
1123 The vertex input layout is defined by the collections of
1124 QRhiVertexInputBinding and QRhiVertexInputAttribute.
1125 */
1126
1127/*!
1128 \fn QRhiVertexInputLayout::QRhiVertexInputLayout()
1129
1130 Constructs an empty vertex input layout description.
1131 */
1132
1133/*!
1134 \return \c true if the values in the two QRhiVertexInputLayout objects
1135 \a a and \a b are equal.
1136
1137 \relates QRhiVertexInputLayout
1138 */
1139bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW
1140{
1141 return a.bindings() == b.bindings()
1142 && a.attributes() == b.attributes();
1143}
1144
1145/*!
1146 \return \c false if the values in the two QRhiVertexInputLayout
1147 objects \a a and \a b are equal; otherwise returns \c true.
1148
1149 \relates QRhiVertexInputLayout
1150*/
1151bool operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW
1152{
1153 return !(a == b);
1154}
1155
1156/*!
1157 \return the hash value for \a v, using \a seed to seed the calculation.
1158
1159 \relates QRhiVertexInputLayout
1160 */
1161uint qHash(const QRhiVertexInputLayout &v, uint seed) Q_DECL_NOTHROW
1162{
1163 return qHash(v.bindings(), seed) + qHash(v.attributes(), seed);
1164}
1165
1166#ifndef QT_NO_DEBUG_STREAM
1167QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
1168{
1169 QDebugStateSaver saver(dbg);
1170 dbg.nospace() << "QRhiVertexInputLayout(bindings=" << v.bindings()
1171 << " attributes=" << v.attributes()
1172 << ')';
1173 return dbg;
1174}
1175#endif
1176
1177/*!
1178 \class QRhiShaderStage
1179 \inmodule QtRhi
1180 \brief Specifies the type and the shader code for a shader stage in the pipeline.
1181 */
1182
1183/*!
1184 \enum QRhiShaderStage::Type
1185 Specifies the type of the shader stage.
1186
1187 \value Vertex Vertex stage
1188 \value Fragment Fragment (pixel) stage
1189 \value Compute Compute stage (this may not always be supported at run time)
1190 */
1191
1192/*!
1193 \fn QRhiShaderStage::QRhiShaderStage()
1194
1195 Constructs a shader stage description for the vertex stage with an empty
1196 QShader.
1197 */
1198
1199/*!
1200 Constructs a shader stage description with the \a type of the stage and the
1201 \a shader.
1202
1203 The shader variant \a v defaults to QShader::StandardShader. A
1204 QShader contains multiple source and binary versions of a shader.
1205 In addition, it can also contain variants of the shader with slightly
1206 modified code. \a v can then be used to select the desired variant.
1207 */
1208QRhiShaderStage::QRhiShaderStage(Type type, const QShader &shader, QShader::Variant v)
1209 : m_type(type),
1210 m_shader(shader),
1211 m_shaderVariant(v)
1212{
1213}
1214
1215/*!
1216 \return \c true if the values in the two QRhiShaderStage objects
1217 \a a and \a b are equal.
1218
1219 \relates QRhiShaderStage
1220 */
1221bool operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) Q_DECL_NOTHROW
1222{
1223 return a.type() == b.type()
1224 && a.shader() == b.shader()
1225 && a.shaderVariant() == b.shaderVariant();
1226}
1227
1228/*!
1229 \return \c false if the values in the two QRhiShaderStage
1230 objects \a a and \a b are equal; otherwise returns \c true.
1231
1232 \relates QRhiShaderStage
1233*/
1234bool operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) Q_DECL_NOTHROW
1235{
1236 return !(a == b);
1237}
1238
1239/*!
1240 \return the hash value for \a v, using \a seed to seed the calculation.
1241
1242 \relates QRhiShaderStage
1243 */
1244uint qHash(const QRhiShaderStage &v, uint seed) Q_DECL_NOTHROW
1245{
1246 return v.type() + qHash(v.shader(), seed) + v.shaderVariant();
1247}
1248
1249#ifndef QT_NO_DEBUG_STREAM
1250QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
1251{
1252 QDebugStateSaver saver(dbg);
1253 dbg.nospace() << "QRhiShaderStage(type=" << s.type()
1254 << " shader=" << s.shader()
1255 << " variant=" << s.shaderVariant()
1256 << ')';
1257 return dbg;
1258}
1259#endif
1260
1261/*!
1262 \class QRhiColorAttachment
1263 \inmodule QtRhi
1264 \brief Describes the a single color attachment of a render target.
1265
1266 A color attachment is either a QRhiTexture or a QRhiRenderBuffer. The
1267 former, when texture() is set, is used in most cases.
1268
1269 \note texture() and renderBuffer() cannot be both set (be non-null at the
1270 same time).
1271
1272 Setting renderBuffer instead is recommended only when multisampling is
1273 needed. Relying on QRhi::MultisampleRenderBuffer is a better choice than
1274 QRhi::MultisampleTexture in practice since the former is available in more
1275 run time configurations (e.g. when running on OpenGL ES 3.0 which has no
1276 support for multisample textures, but does support multisample
1277 renderbuffers).
1278
1279 When targeting a non-multisample texture, the layer() and level()
1280 indicate the targeted layer (face index \c{0-5} for cubemaps) and mip
1281 level.
1282
1283 When texture() or renderBuffer() is multisample, resolveTexture() can be
1284 set optionally. When set, samples are resolved automatically into that
1285 (non-multisample) texture at the end of the render pass. When rendering
1286 into a multisample renderbuffers, this is the only way to get resolved,
1287 non-multisample content out of them. Multisample textures allow sampling in
1288 shaders so for them this is just one option.
1289
1290 \note when resolving is enabled, the multisample data may not be written
1291 out at all. This means that the multisample texture() must not be used
1292 afterwards with shaders for sampling when resolveTexture() is set.
1293 */
1294
1295/*!
1296 \fn QRhiColorAttachment::QRhiColorAttachment()
1297
1298 Constructs an empty color attachment description.
1299 */
1300
1301/*!
1302 Constructs a color attachment description that specifies \a texture as the
1303 associated color buffer.
1304 */
1305QRhiColorAttachment::QRhiColorAttachment(QRhiTexture *texture)
1306 : m_texture(texture)
1307{
1308}
1309
1310/*!
1311 Constructs a color attachment description that specifies \a renderBuffer as
1312 the associated color buffer.
1313 */
1314QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
1315 : m_renderBuffer(renderBuffer)
1316{
1317}
1318
1319/*!
1320 \class QRhiTextureRenderTargetDescription
1321 \inmodule QtRhi
1322 \brief Describes the color and depth or depth/stencil attachments of a render target.
1323
1324 A texture render target has zero or more textures as color attachments,
1325 zero or one renderbuffer as combined depth/stencil buffer or zero or one
1326 texture as depth buffer.
1327
1328 \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
1329 non-null at the same time).
1330 */
1331
1332/*!
1333 \fn QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription()
1334
1335 Constructs an empty texture render target description.
1336 */
1337
1338/*!
1339 Constructs a texture render target description with one attachment
1340 described by \a colorAttachment.
1341 */
1342QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment)
1343{
1344 m_colorAttachments.append(colorAttachment);
1345}
1346
1347/*!
1348 Constructs a texture render target description with two attachments, a
1349 color attachment described by \a colorAttachment, and a depth/stencil
1350 attachment with \a depthStencilBuffer.
1351 */
1352QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
1353 QRhiRenderBuffer *depthStencilBuffer)
1354 : m_depthStencilBuffer(depthStencilBuffer)
1355{
1356 m_colorAttachments.append(colorAttachment);
1357}
1358
1359/*!
1360 Constructs a texture render target description with two attachments, a
1361 color attachment described by \a colorAttachment, and a depth attachment
1362 with \a depthTexture.
1363
1364 \note \a depthTexture must have a suitable format, such as QRhiTexture::D16
1365 or QRhiTexture::D32F.
1366 */
1367QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
1368 QRhiTexture *depthTexture)
1369 : m_depthTexture(depthTexture)
1370{
1371 m_colorAttachments.append(colorAttachment);
1372}
1373
1374/*!
1375 \class QRhiTextureSubresourceUploadDescription
1376 \inmodule QtRhi
1377 \brief Describes the source for one mip level in a layer in a texture upload operation.
1378
1379 The source content is specified either as a QImage or as a raw blob. The
1380 former is only allowed for uncompressed textures with a format that can be
1381 mapped to QImage, while the latter is supported for all formats, including
1382 floating point and compressed.
1383
1384 \note image() and data() cannot be both set at the same time.
1385
1386 destinationTopLeft() specifies the top-left corner of the target
1387 rectangle. Defaults to (0, 0).
1388
1389 An empty sourceSize() (the default) indicates that size is assumed to be
1390 the size of the subresource. With QImage-based uploads this implies that
1391 the size of the source image() must match the subresource. When providing
1392 raw data instead, sufficient number of bytes must be provided in data().
1393
1394 \note With compressed textures the first upload must always match the
1395 subresource size due to graphics API limitations with some backends.
1396
1397 sourceTopLeft() is supported only for QImage-based uploads, and specifies
1398 the top-left corner of the source rectangle.
1399
1400 \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
1401 internally, depending on the format and the backend.
1402
1403 When providing raw data, the stride (row pitch, row length in bytes) of the
1404 provided data must be equal to \c{width * pixelSize} where \c pixelSize is
1405 the number of bytes used for one pixel, and there must be no additional
1406 padding between rows. There is no row start alignment requirement.
1407
1408 \note The format of the source data must be compatible with the texture
1409 format. With many graphics APIs the data is copied as-is into a staging
1410 buffer, there is no intermediate format conversion provided by QRhi. This
1411 applies to floating point formats as well, with, for example, RGBA16F
1412 requiring half floats in the source data.
1413 */
1414
1415/*!
1416 \fn QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription()
1417
1418 Constructs an empty subresource description.
1419
1420 \note an empty QRhiTextureSubresourceUploadDescription is not useful on its
1421 own and should not be submitted to a QRhiTextureUploadEntry. At minimum
1422 image or data must be set first.
1423 */
1424
1425/*!
1426 Constructs a mip level description with a \a image.
1427
1428 The \l{QImage::size()}{size} of \a image must match the size of the mip
1429 level. For level 0 that is the \l{QRhiTexture::pixelSize()}{texture size}.
1430
1431 The bit depth of \a image must be compatible with the
1432 \l{QRhiTexture::Format}{texture format}.
1433
1434 To describe a partial upload, call setSourceSize(), setSourceTopLeft(), or
1435 setDestinationTopLeft() afterwards.
1436 */
1437QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QImage &image)
1438 : m_image(image)
1439{
1440}
1441
1442/*!
1443 Constructs a mip level description with the image data is specified by \a
1444 data and \a size. This is suitable for floating point and compressed
1445 formats as well.
1446
1447 \a data can safely be destroyed or changed once this function returns.
1448 */
1449QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const void *data, int size)
1450 : m_data(reinterpret_cast<const char *>(data), size)
1451{
1452}
1453
1454/*!
1455 \class QRhiTextureUploadEntry
1456 \inmodule QtRhi
1457 \brief Describes one layer (face for cubemaps) in a texture upload operation.
1458 */
1459
1460/*!
1461 \fn QRhiTextureUploadEntry::QRhiTextureUploadEntry()
1462
1463 Constructs an empty QRhiTextureUploadEntry targeting layer 0 and level 0.
1464
1465 \note an empty QRhiTextureUploadEntry should not be submitted without
1466 setting a QRhiTextureSubresourceUploadDescription via setDescription()
1467 first.
1468 */
1469
1470/*!
1471 Constructs a QRhiTextureUploadEntry targeting the given \a layer and mip
1472 \a level, with the subresource contents described by \a desc.
1473 */
1474QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
1475 const QRhiTextureSubresourceUploadDescription &desc)
1476 : m_layer(layer),
1477 m_level(level),
1478 m_desc(desc)
1479{
1480}
1481
1482/*!
1483 \class QRhiTextureUploadDescription
1484 \inmodule QtRhi
1485 \brief Describes a texture upload operation.
1486
1487 Used with QRhiResourceUpdateBatch::uploadTexture(). That function has two
1488 variants: one taking a QImage and one taking a
1489 QRhiTextureUploadDescription. The former is a convenience version,
1490 internally creating a QRhiTextureUploadDescription with a single image
1491 targeting level 0 for layer 0. However, when cubemaps, pre-generated mip
1492 images, or compressed textures are involved, applications will have to work
1493 directly with this class instead.
1494
1495 QRhiTextureUploadDescription also enables specifying batched uploads, which
1496 are useful for example when generating an atlas or glyph cache texture:
1497 multiple, partial uploads for the same subresource (meaning the same layer
1498 and level) are supported, and can be, depending on the backend and the
1499 underlying graphics API, more efficient when batched into the same
1500 QRhiTextureUploadDescription as opposed to issuing individual
1501 \l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} commands for
1502 each of them.
1503
1504 \note Cubemaps have one layer for each of the six faces in the order +X,
1505 -X, +Y, -Y, +Z, -Z.
1506
1507 For example, specifying the faces of a cubemap could look like the following:
1508
1509 \badcode
1510 QImage faces[6];
1511 ...
1512 QVector<QRhiTextureUploadEntry> entries;
1513 for (int i = 0; i < 6; ++i)
1514 entries.append(QRhiTextureUploadEntry(i, 0, faces[i]));
1515 QRhiTextureUploadDescription desc(entries);
1516 resourceUpdates->uploadTexture(texture, desc);
1517 \endcode
1518
1519 Another example that specifies mip images for a compressed texture:
1520
1521 \badcode
1522 QRhiTextureUploadDescription desc;
1523 const int mipCount = rhi->mipLevelsForSize(compressedTexture->pixelSize());
1524 for (int level = 0; level < mipCount; ++level) {
1525 const QByteArray compressedDataForLevel = ..
1526 desc.append(QRhiTextureUploadEntry(0, level, compressedDataForLevel));
1527 }
1528 resourceUpdates->uploadTexture(compressedTexture, desc);
1529 \endcode
1530
1531 With partial uploads targeting the same subresource, it is recommended to
1532 batch them into a single upload request, whenever possible:
1533
1534 \badcode
1535 QRhiTextureSubresourceUploadDescription subresDesc(image);
1536 subresDesc.setSourceSize(QSize(10, 10));
1537 subResDesc.setDestinationTopLeft(QPoint(50, 40));
1538 QRhiTextureUploadEntry entry(0, 0, subresDesc); // layer 0, level 0
1539
1540 QRhiTextureSubresourceUploadDescription subresDesc2(image);
1541 subresDesc2.setSourceSize(QSize(30, 40));
1542 subResDesc2.setDestinationTopLeft(QPoint(100, 200));
1543 QRhiTextureUploadEntry entry2(0, 0, subresDesc2); // layer 0, level 0, i.e. same subresource
1544
1545 QRhiTextureUploadDescription desc({ entry, entry2});
1546 resourceUpdates->uploadTexture(texture, desc);
1547 \endcode
1548 */
1549
1550/*!
1551 \fn QRhiTextureUploadDescription::QRhiTextureUploadDescription()
1552
1553 Constructs an empty texture upload description.
1554 */
1555
1556/*!
1557 Constructs a texture upload description with a single subresource upload
1558 described by \a entry.
1559 */
1560QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry)
1561{
1562 m_entries.append(entry);
1563}
1564
1565/*!
1566 Constructs a texture upload description with the specified list of \a entries.
1567
1568 \note \a entries can also contain multiple QRhiTextureUploadEntry elements
1569 with the the same layer and level. This makes sense when those uploads are
1570 partial, meaning their subresource description has a source size or image
1571 smaller than the subresource dimensions, and can be more efficient than
1572 issuing separate uploadTexture()'s.
1573 */
1574QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QVector<QRhiTextureUploadEntry> &entries)
1575 : m_entries(entries)
1576{
1577}
1578
1579/*!
1580 Adds \a entry to the list of subresource uploads.
1581 */
1582void QRhiTextureUploadDescription::append(const QRhiTextureUploadEntry &entry)
1583{
1584 m_entries.append(entry);
1585}
1586
1587/*!
1588 \class QRhiTextureCopyDescription
1589 \inmodule QtRhi
1590 \brief Describes a texture-to-texture copy operation.
1591
1592 An empty pixelSize() indicates that the entire subresource is to be copied.
1593 A default constructed copy description therefore leads to copying the
1594 entire subresource at level 0 of layer 0.
1595
1596 \note The source texture must be created with
1597 QRhiTexture::UsedAsTransferSource.
1598
1599 \note The source and destination rectangles defined by pixelSize(),
1600 sourceTopLeft(), and destinationTopLeft() must fit the source and
1601 destination textures, respectively. The behavior is undefined otherwise.
1602 */
1603
1604/*!
1605 \fn QRhiTextureCopyDescription::QRhiTextureCopyDescription()
1606
1607 Constructs an empty texture copy description.
1608 */
1609
1610/*!
1611 \class QRhiReadbackDescription
1612 \inmodule QtRhi
1613 \brief Describes a readback (reading back texture contents from possibly GPU-only memory) operation.
1614
1615 The source of the readback operation is either a QRhiTexture or the
1616 current backbuffer of the currently targeted QRhiSwapChain. When
1617 texture() is not set, the swapchain is used. Otherwise the specified
1618 QRhiTexture is treated as the source.
1619
1620 \note Textures used in readbacks must be created with
1621 QRhiTexture::UsedAsTransferSource.
1622
1623 \note Swapchains used in readbacks must be created with
1624 QRhiSwapChain::UsedAsTransferSource.
1625
1626 layer() and level() are only applicable when the source is a QRhiTexture.
1627
1628 \note Multisample textures cannot be read back. Readbacks are supported for
1629 multisample swapchain buffers however.
1630 */
1631
1632/*!
1633 \fn QRhiReadbackDescription::QRhiReadbackDescription()
1634
1635 Constructs an empty texture readback description.
1636
1637 \note The source texture is set to null by default, which is still a valid
1638 readback: it specifies that the backbuffer of the current swapchain is to
1639 be read back. (current meaning the frame's target swapchain at the time of
1640 committing the QRhiResourceUpdateBatch with the
1641 \l{QRhiResourceUpdateBatch::readBackTexture()}{texture readback} on it)
1642 */
1643
1644/*!
1645 Constructs an texture readback description that specifies that level 0 of
1646 layer 0 of \a texture is to be read back.
1647
1648 \note \a texture can also be null in which case this constructor is
1649 identical to the argumentless variant.
1650 */
1651QRhiReadbackDescription::QRhiReadbackDescription(QRhiTexture *texture)
1652 : m_texture(texture)
1653{
1654}
1655
1656/*!
1657 \class QRhiReadbackResult
1658 \inmodule QtRhi
1659 \brief Describes the results of a potentially asynchronous readback operation.
1660
1661 When \l completed is set, the function is invoked when the \l data is
1662 available. \l format and \l pixelSize are set upon completion together with
1663 \l data.
1664 */
1665
1666/*!
1667 \class QRhiNativeHandles
1668 \inmodule QtRhi
1669 \brief Base class for classes exposing backend-specific collections of native resource objects.
1670 */
1671
1672/*!
1673 \class QRhiResource
1674 \inmodule QtRhi
1675 \brief Base class for classes encapsulating native resource objects.
1676 */
1677
1678/*!
1679 \fn QRhiResource::Type QRhiResource::resourceType() const
1680
1681 \return the type of the resource.
1682 */
1683
1684/*!
1685 \internal
1686 */
1687QRhiResource::QRhiResource(QRhiImplementation *rhi)
1688 : m_rhi(rhi)
1689{
1690 m_id = QRhiGlobalObjectIdGenerator::newId();
1691}
1692
1693/*!
1694 Destructor.
1695
1696 Releases (or requests deferred releasing of) the underlying native graphics
1697 resources, if there are any.
1698
1699 \note Resources referenced by commands for the current frame should not be
1700 released until the frame is submitted by QRhi::endFrame().
1701
1702 \sa release()
1703 */
1704QRhiResource::~QRhiResource()
1705{
1706 // release() cannot be called here, it being virtual; it is up to the
1707 // subclasses to do that.
1708}
1709
1710/*!
1711 \fn void QRhiResource::release()
1712
1713 Releases (or requests deferred releasing of) the underlying native graphics
1714 resources. Safe to call multiple times, subsequent invocations will be a
1715 no-op then.
1716
1717 Once release() is called, the QRhiResource instance can be reused, by
1718 calling \c build() again. That will then result in creating new native
1719 graphics resources underneath.
1720
1721 \note Resources referenced by commands for the current frame should not be
1722 released until the frame is submitted by QRhi::endFrame().
1723
1724 The QRhiResource destructor also performs the same task, so calling this
1725 function is not necessary before destroying a QRhiResource.
1726
1727 \sa releaseAndDestroyLater()
1728 */
1729
1730/*!
1731 When called without a frame being recorded, this function is equivalent to
1732 deleting the object. Between a QRhi::beginFrame() and QRhi::endFrame()
1733 however the behavior is different: the QRhiResource will not be destroyed
1734 until the frame is submitted via QRhi::endFrame(), thus satisfying the QRhi
1735 requirement of not altering QRhiResource objects that are referenced by the
1736 frame being recorded.
1737
1738 \sa release()
1739 */
1740void QRhiResource::releaseAndDestroyLater()
1741{
1742 m_rhi->addReleaseAndDestroyLater(this);
1743}
1744
1745/*!
1746 \return the currently set object name. By default the name is empty.
1747 */
1748QByteArray QRhiResource::name() const
1749{
1750 return m_objectName;
1751}
1752
1753/*!
1754 Sets a \a name for the object.
1755
1756 This has two uses: to get descriptive names for the native graphics
1757 resources visible in graphics debugging tools, such as
1758 \l{https://renderdoc.org/}{RenderDoc} and
1759 \l{https://developer.apple.com/xcode/}{XCode}, and in the output stream of
1760 QRhiProfiler.
1761
1762 When it comes to naming native objects by relaying the name via the
1763 appropriate graphics API, note that the name is ignored when
1764 QRhi::DebugMarkers are not supported, and may, depending on the backend,
1765 also be ignored when QRhi::EnableDebugMarkers is not set.
1766
1767 \note The name may be ignored for objects other than buffers,
1768 renderbuffers, and textures, depending on the backend.
1769
1770 \note The name may be modified. For slotted resources, such as a QRhiBuffer
1771 backed by multiple native buffers, QRhi will append a suffix to make the
1772 underlying native buffers easily distinguishable from each other.
1773 */
1774void QRhiResource::setName(const QByteArray &name)
1775{
1776 m_objectName = name;
1777 m_objectName.replace(',', '_'); // cannot contain comma for QRhiProfiler
1778}
1779
1780/*!
1781 \return the global, unique identifier of this QRhiResource.
1782
1783 User code rarely needs to deal with the value directly. It is used
1784 internally for tracking and bookkeeping purposes.
1785 */
1786quint64 QRhiResource::globalResourceId() const
1787{
1788 return m_id;
1789}
1790
1791/*!
1792 \class QRhiBuffer
1793 \inmodule QtRhi
1794 \brief Vertex, index, or uniform (constant) buffer resource.
1795 */
1796
1797/*!
1798 \enum QRhiBuffer::Type
1799 Specifies storage type of buffer resource.
1800
1801 \value Immutable Indicates that the data is not expected to change ever
1802 after the initial upload. Under the hood such buffer resources are
1803 typically placed in device local (GPU) memory (on systems where
1804 applicable). Uploading new data is possible, but may be expensive. The
1805 upload typically happens by copying to a separate, host visible staging
1806 buffer from which a GPU buffer-to-buffer copy is issued into the actual
1807 GPU-only buffer.
1808
1809 \value Static Indicates that the data is expected to change only
1810 infrequently. Typically placed in device local (GPU) memory, where
1811 applicable. On backends where host visible staging buffers are used for
1812 uploading, the staging buffers are kept around for this type, unlike with
1813 Immutable, so subsequent uploads do not suffer in performance. Frequent
1814 updates, especially updates in consecutive frames, should be avoided.
1815
1816 \value Dynamic Indicates that the data is expected to change frequently.
1817 Not recommended for large buffers. Typically backed by host visible memory
1818 in 2 copies in order to allow for changing without stalling the graphics
1819 pipeline. The double buffering is managed transparently to the applications
1820 and is not exposed in the API here in any form. This is the recommended,
1821 and, with some backends, the only possible, type for buffers with
1822 UniformBuffer usage.
1823 */
1824
1825/*!
1826 \enum QRhiBuffer::UsageFlag
1827 Flag values to specify how the buffer is going to be used.
1828
1829 \value VertexBuffer Vertex buffer. This allows the QRhiBuffer to be used in
1830 \l{setVertexInput()}{QRhiCommandBuffer::setVertexInput()}.
1831
1832 \value IndexBuffer Index buffer. This allows the QRhiBuffer to be used in
1833 \l{setVertexInput()}{QRhiCommandBuffer::setVertexInput()}.
1834
1835 \value UniformBuffer Uniform buffer (also called constant buffer). This
1836 allows the QRhiBuffer to be used in combination with
1837 \l{UniformBuffer}{QRhiShaderResourceBinding::UniformBuffer}. When
1838 \l{QRhi::NonDynamicUniformBuffers}{NonDynamicUniformBuffers} is reported as
1839 not supported, this usage can only be combined with the type Dynamic.
1840
1841 \value StorageBuffer Storage buffer. This allows the QRhiBuffer to be used
1842 in combination with \l{BufferLoad}{QRhiShaderResourceBinding::BufferLoad},
1843 \l{BufferStore}{QRhiShaderResourceBinding::BufferStore}, or
1844 \l{BufferLoadStore}{QRhiShaderResourceBinding::BufferLoadStore}. This usage
1845 can only be combined with the types Immutable or Static, and is only
1846 available when the \l{QRhi::Compute}{Compute feature} is reported as
1847 supported.
1848 */
1849
1850/*!
1851 \fn void QRhiBuffer::setSize(int sz)
1852
1853 Sets the size of the buffer in bytes. The size is normally specified in
1854 QRhi::newBuffer() so this function is only used when the size has to be
1855 changed. As with other setters, the size only takes effect when calling
1856 build(), and for already built buffers this involves releasing the previous
1857 native resource and creating new ones under the hood.
1858
1859 Backends may choose to allocate buffers bigger than \a sz in order to
1860 fulfill alignment requirements. This is hidden from the applications and
1861 size() will always report the size requested in \a sz.
1862 */
1863
1864/*!
1865 \internal
1866 */
1867QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, int size_)
1868 : QRhiResource(rhi),
1869 m_type(type_), m_usage(usage_), m_size(size_)
1870{
1871}
1872
1873/*!
1874 \return the resource type.
1875 */
1876QRhiResource::Type QRhiBuffer::resourceType() const
1877{
1878 return Buffer;
1879}
1880
1881/*!
1882 \fn bool QRhiBuffer::build()
1883
1884 Creates the corresponding native graphics resources. If there are already
1885 resources present due to an earlier build() with no corresponding
1886 release(), then release() is called implicitly first.
1887
1888 \return \c true when successful, \c false when a graphics operation failed.
1889 Regardless of the return value, calling release() is always safe.
1890 */
1891
1892/*!
1893 \class QRhiRenderBuffer
1894 \inmodule QtRhi
1895 \brief Renderbuffer resource.
1896
1897 Renderbuffers cannot be sampled or read but have some benefits over
1898 textures in some cases:
1899
1900 A DepthStencil renderbuffer may be lazily allocated and be backed by
1901 transient memory with some APIs. On some platforms this may mean the
1902 depth/stencil buffer uses no physical backing at all.
1903
1904 Color renderbuffers are useful since QRhi::MultisampleRenderBuffer may be
1905 supported even when QRhi::MultisampleTexture is not.
1906
1907 How the renderbuffer is implemented by a backend is not exposed to the
1908 applications. In some cases it may be backed by ordinary textures, while in
1909 others there may be a different kind of native resource used.
1910 */
1911
1912/*!
1913 \enum QRhiRenderBuffer::Type
1914 Specifies the type of the renderbuffer
1915
1916 \value DepthStencil Combined depth/stencil
1917 \value Color Color
1918 */
1919
1920/*!
1921 \enum QRhiRenderBuffer::Flag
1922 Flag values for flags() and setFlags()
1923
1924 \value UsedWithSwapChainOnly For DepthStencil renderbuffers this indicates
1925 that the renderbuffer is only used in combination with a QRhiSwapChain and
1926 never in other ways. Relevant with some backends, while others ignore it.
1927 With OpenGL where a separate windowing system interface API is in use (EGL,
1928 GLX, etc.), the flag is important since it avoids creating any actual
1929 resource as there is already a windowing system provided depth/stencil
1930 buffer as requested by QSurfaceFormat.
1931 */
1932
1933/*!
1934 \internal
1935 */
1936QRhiRenderBuffer::QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
1937 int sampleCount_, Flags flags_)
1938 : QRhiResource(rhi),
1939 m_type(type_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_)
1940{
1941}
1942
1943/*!
1944 \return the resource type.
1945 */
1946QRhiResource::Type QRhiRenderBuffer::resourceType() const
1947{
1948 return RenderBuffer;
1949}
1950
1951/*!
1952 \fn bool QRhiRenderBuffer::build()
1953
1954 Creates the corresponding native graphics resources. If there are already
1955 resources present due to an earlier build() with no corresponding
1956 release(), then release() is called implicitly first.
1957
1958 \return \c true when successful, \c false when a graphics operation failed.
1959 Regardless of the return value, calling release() is always safe.
1960 */
1961
1962/*!
1963 \fn QRhiTexture::Format QRhiRenderBuffer::backingFormat() const
1964
1965 \internal
1966 */
1967
1968/*!
1969 \class QRhiTexture
1970 \inmodule QtRhi
1971 \brief Texture resource.
1972 */
1973
1974/*!
1975 \enum QRhiTexture::Flag
1976
1977 Flag values to specify how the texture is going to be used. Not honoring
1978 the flags set before build() and attempting to use the texture in ways that
1979 was not declared upfront can lead to unspecified behavior or decreased
1980 performance depending on the backend and the underlying graphics API.
1981
1982 \value RenderTarget The texture going to be used in combination with
1983 QRhiTextureRenderTarget.
1984
1985 \value CubeMap The texture is a cubemap. Such textures have 6 layers, one
1986 for each face in the order of +X, -X, +Y, -Y, +Z, -Z. Cubemap textures
1987 cannot be multisample.
1988
1989 \value MipMapped The texture has mipmaps. The appropriate mip count is
1990 calculated automatically and can also be retrieved via
1991 QRhi::mipLevelsForSize(). The images for the mip levels have to be
1992 provided in the texture uploaded or generated via
1993 QRhiResourceUpdateBatch::generateMips(). Multisample textures cannot have
1994 mipmaps.
1995
1996 \value sRGB Use an sRGB format.
1997
1998 \value UsedAsTransferSource The texture is used as the source of a texture
1999 copy or readback, meaning the texture is given as the source in
2000 QRhiResourceUpdateBatch::copyTexture() or
2001 QRhiResourceUpdateBatch::readBackTexture().
2002
2003 \value UsedWithGenerateMips The texture is going to be used with
2004 QRhiResourceUpdateBatch::generateMips().
2005
2006 \value UsedWithLoadStore The texture is going to be used with image
2007 load/store operations, for example, in a compute shader.
2008 */
2009
2010/*!
2011 \enum QRhiTexture::Format
2012
2013 Specifies the texture format. See also QRhi::isTextureFormatSupported() and
2014 note that flags() can modify the format when QRhiTexture::sRGB is set.
2015
2016 \value UnknownFormat Not a valid format. This cannot be passed to setFormat().
2017
2018 \value RGBA8 Four component, unsigned normalized 8 bit per component. Always supported.
2019
2020 \value BGRA8 Four component, unsigned normalized 8 bit per component.
2021
2022 \value R8 One component, unsigned normalized 8 bit.
2023
2024 \value R16 One component, unsigned normalized 16 bit.
2025
2026 \value RED_OR_ALPHA8 Either same as R8, or is a similar format with the component swizzled to alpha,
2027 depending on \l{QRhi::RedOrAlpha8IsRed}{RedOrAlpha8IsRed}.
2028
2029 \value RGBA16F Four components, 16-bit float per component.
2030
2031 \value RGBA32F Four components, 32-bit float per component.
2032
2033 \value D16 16-bit depth (normalized unsigned integer)
2034
2035 \value D32F 32-bit depth (32-bit float)
2036
2037 \value BC1
2038 \value BC2
2039 \value BC3
2040 \value BC4
2041 \value BC5
2042 \value BC6H
2043 \value BC7
2044
2045 \value ETC2_RGB8
2046 \value ETC2_RGB8A1
2047 \value ETC2_RGBA8
2048
2049 \value ASTC_4x4
2050 \value ASTC_5x4
2051 \value ASTC_5x5
2052 \value ASTC_6x5
2053 \value ASTC_6x6
2054 \value ASTC_8x5
2055 \value ASTC_8x6
2056 \value ASTC_8x8
2057 \value ASTC_10x5
2058 \value ASTC_10x6
2059 \value ASTC_10x8
2060 \value ASTC_10x10
2061 \value ASTC_12x10
2062 \value ASTC_12x12
2063 */
2064
2065/*!
2066 \internal
2067 */
2068QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_,
2069 int sampleCount_, Flags flags_)
2070 : QRhiResource(rhi),
2071 m_format(format_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_)
2072{
2073}
2074
2075/*!
2076 \return the resource type.
2077 */
2078QRhiResource::Type QRhiTexture::resourceType() const
2079{
2080 return Texture;
2081}
2082
2083/*!
2084 \fn bool QRhiTexture::build()
2085
2086 Creates the corresponding native graphics resources. If there are already
2087 resources present due to an earlier build() with no corresponding
2088 release(), then release() is called implicitly first.
2089
2090 \return \c true when successful, \c false when a graphics operation failed.
2091 Regardless of the return value, calling release() is always safe.
2092 */
2093
2094/*!
2095 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
2096 QRhiVulkanTextureNativeHandles. The returned value is null when exposing
2097 the underlying native resources is not supported by the backend.
2098
2099 \sa QRhiVulkanTextureNativeHandles, QRhiD3D11TextureNativeHandles,
2100 QRhiMetalTextureNativeHandles, QRhiGles2TextureNativeHandles
2101 */
2102const QRhiNativeHandles *QRhiTexture::nativeHandles()
2103{
2104 return nullptr;
2105}
2106
2107/*!
2108 Similar to build() except that no new native textures are created. Instead,
2109 the texture from \a src is used.
2110
2111 This allows importing an existing native texture object (which must belong
2112 to the same device or sharing context, depending on the graphics API) from
2113 an external graphics engine.
2114
2115 \note format(), pixelSize(), sampleCount(), and flags() must still be set
2116 correctly. Passing incorrect sizes and other values to QRhi::newTexture()
2117 and then following it with a buildFrom() expecting that the native texture
2118 object alone is sufficient to deduce such values is \b wrong and will lead
2119 to problems.
2120
2121 \note QRhiTexture does not take ownership of the texture object. release()
2122 does not free the object or any associated memory.
2123
2124 The opposite of this operation, exposing a QRhiTexture-created native
2125 texture object to a foreign engine, is possible via nativeHandles().
2126
2127 \sa QRhiVulkanTextureNativeHandles, QRhiD3D11TextureNativeHandles,
2128 QRhiMetalTextureNativeHandles, QRhiGles2TextureNativeHandles
2129 */
2130bool QRhiTexture::buildFrom(const QRhiNativeHandles *src)
2131{
2132 Q_UNUSED(src);
2133 return false;
2134}
2135
2136/*!
2137 \class QRhiSampler
2138 \inmodule QtRhi
2139 \brief Sampler resource.
2140 */
2141
2142/*!
2143 \enum QRhiSampler::Filter
2144 Specifies the minification, magnification, or mipmap filtering
2145
2146 \value None Applicable only for mipmapMode(), indicates no mipmaps to be used
2147 \value Nearest
2148 \value Linear
2149 */
2150
2151/*!
2152 \enum QRhiSampler::AddressMode
2153 Specifies the addressing mode
2154
2155 \value Repeat
2156 \value ClampToEdge
2157 \value Border
2158 \value Mirror
2159 \value MirrorOnce
2160 */
2161
2162/*!
2163 \enum QRhiSampler::CompareOp
2164 Specifies the texture comparison function.
2165
2166 \value Never (default)
2167 \value Less
2168 \value Equal
2169 \value LessOrEqual
2170 \value Greater
2171 \value NotEqual
2172 \value GreaterOrEqual
2173 \value Always
2174 */
2175
2176/*!
2177 \internal
2178 */
2179QRhiSampler::QRhiSampler(QRhiImplementation *rhi,
2180 Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
2181 AddressMode u_, AddressMode v_)
2182 : QRhiResource(rhi),
2183 m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_),
2184 m_addressU(u_), m_addressV(v_),
2185 m_addressW(QRhiSampler::ClampToEdge),
2186 m_compareOp(QRhiSampler::Never)
2187{
2188}
2189
2190/*!
2191 \return the resource type.
2192 */
2193QRhiResource::Type QRhiSampler::resourceType() const
2194{
2195 return Sampler;
2196}
2197
2198/*!
2199 \class QRhiRenderPassDescriptor
2200 \inmodule QtRhi
2201 \brief Render pass resource.
2202 */
2203
2204/*!
2205 \internal
2206 */
2207QRhiRenderPassDescriptor::QRhiRenderPassDescriptor(QRhiImplementation *rhi)
2208 : QRhiResource(rhi)
2209{
2210}
2211
2212/*!
2213 \return the resource type.
2214 */
2215QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
2216{
2217 return RenderPassDescriptor;
2218}
2219
2220/*!
2221 \class QRhiRenderTarget
2222 \inmodule QtRhi
2223 \brief Represents an onscreen (swapchain) or offscreen (texture) render target.
2224 */
2225
2226/*!
2227 \internal
2228 */
2229QRhiRenderTarget::QRhiRenderTarget(QRhiImplementation *rhi)
2230 : QRhiResource(rhi)
2231{
2232}
2233
2234/*!
2235 \return the resource type.
2236 */
2237QRhiResource::Type QRhiRenderTarget::resourceType() const
2238{
2239 return RenderTarget;
2240}
2241
2242/*!
2243 \fn QSize QRhiRenderTarget::pixelSize() const
2244
2245 \return the size in pixels.
2246 */
2247
2248/*!
2249 \fn float QRhiRenderTarget::devicePixelRatio() const
2250
2251 \return the device pixel ratio. For QRhiTextureRenderTarget this is always
2252 1. For targets retrieved from a QRhiSwapChain the value reflects the
2253 \l{QWindow::devicePixelRatio()}{device pixel ratio} of the targeted
2254 QWindow.
2255 */
2256
2257/*!
2258 \class QRhiTextureRenderTarget
2259 \inmodule QtRhi
2260 \brief Texture render target resource.
2261
2262 A texture render target allows rendering into one or more textures,
2263 optionally with a depth texture or depth/stencil renderbuffer.
2264
2265 \note Textures used in combination with QRhiTextureRenderTarget must be
2266 created with the QRhiTexture::RenderTarget flag.
2267
2268 The simplest example of creating a render target with a texture as its
2269 single color attachment:
2270
2271 \badcode
2272 texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
2273 texture->build();
2274 rt = rhi->newTextureRenderTarget({ texture });
2275 rp = rt->newCompatibleRenderPassDescriptor();
2276 rt->setRenderPassDescriptor(rt);
2277 rt->build();
2278 // rt can now be used with beginPass()
2279 \endcode
2280 */
2281
2282/*!
2283 \enum QRhiTextureRenderTarget::Flag
2284
2285 Flag values describing the load/store behavior for the render target. The
2286 load/store behavior may be baked into native resources under the hood,
2287 depending on the backend, and therefore it needs to be known upfront and
2288 cannot be changed without rebuilding (and so releasing and creating new
2289 native resources).
2290
2291 \value PreserveColorContents Indicates that the contents of the color
2292 attachments is to be loaded when starting a render pass, instead of
2293 clearing. This is potentially more expensive, especially on mobile (tiled)
2294 GPUs, but allows preserving the existing contents between passes.
2295
2296 \value PreserveDepthStencilContents Indicates that the contents of the
2297 depth texture is to be loaded when starting a render pass, instead
2298 clearing. Only applicable when a texture is used as the depth buffer
2299 (QRhiTextureRenderTargetDescription::depthTexture() is set) because
2300 depth/stencil renderbuffers may not have any physical backing and data may
2301 not be written out in the first place.
2302 */
2303
2304/*!
2305 \internal
2306 */
2307QRhiTextureRenderTarget::QRhiTextureRenderTarget(QRhiImplementation *rhi,
2308 const QRhiTextureRenderTargetDescription &desc_,
2309 Flags flags_)
2310 : QRhiRenderTarget(rhi),
2311 m_desc(desc_),
2312 m_flags(flags_)
2313{
2314}
2315
2316/*!
2317 \return the resource type.
2318 */
2319QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
2320{
2321 return TextureRenderTarget;
2322}
2323
2324/*!
2325 \fn QRhiRenderPassDescriptor *QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()
2326
2327 \return a new QRhiRenderPassDescriptor that is compatible with this render
2328 target.
2329
2330 The returned value is used in two ways: it can be passed to
2331 setRenderPassDescriptor() and
2332 QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
2333 describes the attachments (color, depth/stencil) and the load/store
2334 behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
2335 be used in combination with a render target that has the same
2336 QRhiRenderPassDescriptor set.
2337
2338 Two QRhiTextureRenderTarget instances can share the same render pass
2339 descriptor as long as they have the same number and type of attachments.
2340 The associated QRhiTexture or QRhiRenderBuffer instances are not part of
2341 the render pass descriptor so those can differ in the two
2342 QRhiTextureRenderTarget intances.
2343
2344 \note resources, such as QRhiTexture instances, referenced in description()
2345 must already be built
2346
2347 \sa build()
2348 */
2349
2350/*!
2351 \fn bool QRhiTextureRenderTarget::build()
2352
2353 Creates the corresponding native graphics resources. If there are already
2354 resources present due to an earlier build() with no corresponding
2355 release(), then release() is called implicitly first.
2356
2357 \note renderPassDescriptor() must be set before calling build(). To obtain
2358 a QRhiRenderPassDescriptor compatible with the render target, call
2359 newCompatibleRenderPassDescriptor() before build() but after setting all
2360 other parameters, such as description() and flags(). To save resources,
2361 reuse the same QRhiRenderPassDescriptor with multiple
2362 QRhiTextureRenderTarget instances, whenever possible. Sharing the same
2363 render pass descriptor is only possible when the render targets have the
2364 same number and type of attachments (the actual textures can differ) and
2365 the same flags.
2366
2367 \note resources, such as QRhiTexture instances, referenced in description()
2368 must already be built
2369
2370 \return \c true when successful, \c false when a graphics operation failed.
2371 Regardless of the return value, calling release() is always safe.
2372 */
2373
2374/*!
2375 \class QRhiShaderResourceBindings
2376 \inmodule QtRhi
2377 \brief Encapsulates resources for making buffer, texture, sampler resources visible to shaders.
2378
2379 A QRhiShaderResourceBindings is a collection of QRhiShaderResourceBinding
2380 objects, each of which describe a single binding.
2381
2382 Take a fragment shader with the following interface:
2383
2384 \badcode
2385 layout(std140, binding = 0) uniform buf {
2386 mat4 mvp;
2387 int flip;
2388 } ubuf;
2389
2390 layout(binding = 1) uniform sampler2D tex;
2391 \endcode
2392
2393 To make resources visible to the shader, the following
2394 QRhiShaderResourceBindings could be created and then passed to
2395 QRhiGraphicsPipeline::setShaderResourceBindings():
2396
2397 \badcode
2398 srb = rhi->newShaderResourceBindings();
2399 srb->setBindings({
2400 QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf),
2401 QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler)
2402 });
2403 srb->build();
2404 ...
2405 ps = rhi->newGraphicsPipeline();
2406 ...
2407 ps->setShaderResourceBindings(srb);
2408 ps->build();
2409 ...
2410 cb->setGraphicsPipeline(ps);
2411 cb->setShaderResources(); // binds srb
2412 \endcode
2413
2414 This assumes that \c ubuf is a QRhiBuffer, \c texture is a QRhiTexture,
2415 while \a sampler is a QRhiSampler. The example also assumes that the
2416 uniform block is present in the vertex shader as well so the same buffer is
2417 made visible to the vertex stage too.
2418
2419 \section3 Advanced usage
2420
2421 Building on the above example, let's assume that a pass now needs to use
2422 the exact same pipeline and shaders with a different texture. Creating a
2423 whole separate QRhiGraphicsPipeline just for this would be an overkill.
2424 This is why QRhiCommandBuffer::setShaderResources() allows specifying a \a
2425 srb argument. As long as the layouts (so the number of bindings and the
2426 binding points) match between two QRhiShaderResourceBindings, they can both
2427 be used with the same pipeline, assuming the pipeline was built with one of
2428 them in the first place.
2429
2430 Creating and then using a new \c srb2 that is very similar to \c srb with
2431 the exception of referencing another texture could be implemented like the
2432 following:
2433
2434 \badcode
2435 srb2 = rhi->newShaderResourceBindings();
2436 QVector<QRhiShaderResourceBinding> bindings = srb->bindings();
2437 bindings[1] = QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, anotherTexture, sampler);
2438 srb2->setBindings(bindings);
2439 srb2->build();
2440 ...
2441 cb->setGraphicsPipeline(ps);
2442 cb->setShaderResources(srb2); // binds srb2
2443 \endcode
2444 */
2445
2446/*!
2447 \internal
2448 */
2449QRhiShaderResourceBindings::QRhiShaderResourceBindings(QRhiImplementation *rhi)
2450 : QRhiResource(rhi)
2451{
2452}
2453
2454/*!
2455 \return the resource type.
2456 */
2457QRhiResource::Type QRhiShaderResourceBindings::resourceType() const
2458{
2459 return ShaderResourceBindings;
2460}
2461
2462/*!
2463 \return \c true if the layout is compatible with \a other. The layout does
2464 not include the actual resource (such as, buffer or texture) and related
2465 parameters (such as, offset or size). It does include the binding point,
2466 pipeline stage, and resource type, however. The number and order of the
2467 bindings must also match in order to be compatible.
2468
2469 When there is a QRhiGraphicsPipeline created with this
2470 QRhiShaderResourceBindings, and the function returns \c true, \a other can
2471 then safely be passed to QRhiCommandBuffer::setShaderResources(), and so
2472 be used with the pipeline in place of this QRhiShaderResourceBindings.
2473
2474 This function can be called before build() as well. The bindings must
2475 already be set via setBindings() however.
2476 */
2477bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBindings *other) const
2478{
2479 const int count = m_bindings.count();
2480 if (count != other->m_bindings.count())
2481 return false;
2482
2483 for (int i = 0; i < count; ++i) {
2484 if (!m_bindings[i].isLayoutCompatible(other->m_bindings.at(i)))
2485 return false;
2486 }
2487
2488 return true;
2489}
2490
2491/*!
2492 \class QRhiShaderResourceBinding
2493 \inmodule QtRhi
2494 \brief Describes the shader resource for a single binding point.
2495
2496 A QRhiShaderResourceBinding cannot be constructed directly. Instead, use
2497 the static functions uniformBuffer(), sampledTexture() to get an instance.
2498 */
2499
2500/*!
2501 \enum QRhiShaderResourceBinding::Type
2502 Specifies type of the shader resource bound to a binding point
2503
2504 \value UniformBuffer Uniform buffer
2505
2506 \value SampledTexture Combined image sampler
2507
2508 \value ImageLoad Image load (with GLSL this maps to doing imageLoad() on a
2509 single level - and either one or all layers - of a texture exposed to the
2510 shader as an image object)
2511
2512 \value ImageStore Image store (with GLSL this maps to doing imageStore() or
2513 imageAtomic*() on a single level - and either one or all layers - of a
2514 texture exposed to the shader as an image object)
2515
2516 \value ImageLoadStore Image load and store
2517
2518 \value BufferLoad Storage buffer store (with GLSL this maps to reading from
2519 a shader storage buffer)
2520
2521 \value BufferStore Storage buffer store (with GLSL this maps to writing to
2522 a shader storage buffer)
2523
2524 \value BufferLoadStore Storage buffer load and store
2525 */
2526
2527/*!
2528 \enum QRhiShaderResourceBinding::StageFlag
2529 Flag values to indicate which stages the shader resource is visible in
2530
2531 \value VertexStage Vertex stage
2532 \value FragmentStage Fragment (pixel) stage
2533 \value ComputeStage Compute stage
2534 */
2535
2536/*!
2537 \internal
2538 */
2539QRhiShaderResourceBinding::QRhiShaderResourceBinding()
2540 : d(new QRhiShaderResourceBindingPrivate)
2541{
2542}
2543
2544/*!
2545 \internal
2546 */
2547void QRhiShaderResourceBinding::detach()
2548{
2549 qAtomicDetach(d);
2550}
2551
2552/*!
2553 \internal
2554 */
2555QRhiShaderResourceBinding::QRhiShaderResourceBinding(const QRhiShaderResourceBinding &other)
2556 : d(other.d)
2557{
2558 d->ref.ref();
2559}
2560
2561/*!
2562 \internal
2563 */
2564QRhiShaderResourceBinding &QRhiShaderResourceBinding::operator=(const QRhiShaderResourceBinding &other)
2565{
2566 qAtomicAssign(d, other.d);
2567 return *this;
2568}
2569
2570/*!
2571 Destructor.
2572 */
2573QRhiShaderResourceBinding::~QRhiShaderResourceBinding()
2574{
2575 if (!d->ref.deref())
2576 delete d;
2577}
2578
2579/*!
2580 \return \c true if the layout is compatible with \a other. The layout does not
2581 include the actual resource (such as, buffer or texture) and related
2582 parameters (such as, offset or size).
2583
2584 For example, \c a and \c b below are not equal, but are compatible layout-wise:
2585
2586 \badcode
2587 auto a = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buffer);
2588 auto b = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, someOtherBuffer, 256);
2589 \endcode
2590 */
2591bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBinding &other) const
2592{
2593 return (d == other.d)
2594 || (d->binding == other.d->binding && d->stage == other.d->stage && d->type == other.d->type);
2595}
2596
2597/*!
2598 \return a shader resource binding for the given binding number, pipeline
2599 stages, and buffer specified by \a binding, \a stage, and \a buf.
2600
2601 \note \a buf must have been created with QRhiBuffer::UniformBuffer.
2602 */
2603QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
2604 int binding, StageFlags stage, QRhiBuffer *buf)
2605{
2606 QRhiShaderResourceBinding b;
2607 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2608 Q_ASSERT(d->ref.loadRelaxed() == 1);
2609 d->binding = binding;
2610 d->stage = stage;
2611 d->type = UniformBuffer;
2612 d->u.ubuf.buf = buf;
2613 d->u.ubuf.offset = 0;
2614 d->u.ubuf.maybeSize = 0; // entire buffer
2615 d->u.ubuf.hasDynamicOffset = false;
2616 return b;
2617}
2618
2619/*!
2620 \return a shader resource binding for the given binding number, pipeline
2621 stages, and buffer specified by \a binding, \a stage, and \a buf. This
2622 overload binds a region only, as specified by \a offset and \a size.
2623
2624 \note It is up to the user to ensure the offset is aligned to
2625 QRhi::ubufAlignment().
2626
2627 \note \a size must be greater than 0.
2628
2629 \note \a buf must have been created with QRhiBuffer::UniformBuffer.
2630 */
2631QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
2632 int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
2633{
2634 Q_ASSERT(size > 0);
2635 QRhiShaderResourceBinding b = uniformBuffer(binding, stage, buf);
2636 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2637 d->u.ubuf.offset = offset;
2638 d->u.ubuf.maybeSize = size;
2639 return b;
2640}
2641
2642/*!
2643 \return a shader resource binding for the given binding number, pipeline
2644 stages, and buffer specified by \a binding, \a stage, and \a buf. The
2645 uniform buffer is assumed to have dynamic offset. The dynamic offset can be
2646 specified in QRhiCommandBuffer::setShaderResources(), thus allowing using
2647 varying offset values without creating new bindings for the buffer. The
2648 size of the bound region is specified by \a size. Like with non-dynamic
2649 offsets, \c{offset + size} cannot exceed the size of \a buf.
2650
2651 \note \a buf must have been created with QRhiBuffer::UniformBuffer.
2652 */
2653QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(
2654 int binding, StageFlags stage, QRhiBuffer *buf, int size)
2655{
2656 QRhiShaderResourceBinding b = uniformBuffer(binding, stage, buf, 0, size);
2657 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2658 d->u.ubuf.hasDynamicOffset = true;
2659 return b;
2660}
2661
2662/*!
2663 \return a shader resource binding for the given binding number, pipeline
2664 stages, texture, and sampler specified by \a binding, \a stage, \a tex,
2665 \a sampler.
2666 */
2667QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
2668 int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
2669{
2670 QRhiShaderResourceBinding b;
2671 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2672 Q_ASSERT(d->ref.loadRelaxed() == 1);
2673 d->binding = binding;
2674 d->stage = stage;
2675 d->type = SampledTexture;
2676 d->u.stex.tex = tex;
2677 d->u.stex.sampler = sampler;
2678 return b;
2679}
2680
2681/*!
2682 \return a shader resource binding for a read-only storage image with the
2683 given \a binding number and pipeline \a stage. The image load operations
2684 will have access to all layers of the specified \a level. (so if the texture
2685 is a cubemap, the shader must use imageCube instead of image2D)
2686
2687 \note \a tex must have been created with QRhiTexture::UsedWithLoadStore.
2688 */
2689QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoad(
2690 int binding, StageFlags stage, QRhiTexture *tex, int level)
2691{
2692 QRhiShaderResourceBinding b;
2693 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2694 Q_ASSERT(d->ref.loadRelaxed() == 1);
2695 d->binding = binding;
2696 d->stage = stage;
2697 d->type = ImageLoad;
2698 d->u.simage.tex = tex;
2699 d->u.simage.level = level;
2700 return b;
2701}
2702
2703/*!
2704 \return a shader resource binding for a write-only storage image with the
2705 given \a binding number and pipeline \a stage. The image store operations
2706 will have access to all layers of the specified \a level. (so if the texture
2707 is a cubemap, the shader must use imageCube instead of image2D)
2708
2709 \note \a tex must have been created with QRhiTexture::UsedWithLoadStore.
2710 */
2711QRhiShaderResourceBinding QRhiShaderResourceBinding::imageStore(
2712 int binding, StageFlags stage, QRhiTexture *tex, int level)
2713{
2714 QRhiShaderResourceBinding b = imageLoad(binding, stage, tex, level);
2715 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2716 d->type = ImageStore;
2717 return b;
2718}
2719
2720/*!
2721 \return a shader resource binding for a read/write storage image with the
2722 given \a binding number and pipeline \a stage. The image load/store operations
2723 will have access to all layers of the specified \a level. (so if the texture
2724 is a cubemap, the shader must use imageCube instead of image2D)
2725
2726 \note \a tex must have been created with QRhiTexture::UsedWithLoadStore.
2727 */
2728QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoadStore(
2729 int binding, StageFlags stage, QRhiTexture *tex, int level)
2730{
2731 QRhiShaderResourceBinding b = imageLoad(binding, stage, tex, level);
2732 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2733 d->type = ImageLoadStore;
2734 return b;
2735}
2736
2737/*!
2738 \return a shader resource binding for a read-only storage buffer with the
2739 given \a binding number and pipeline \a stage.
2740
2741 \note \a buf must have been created with QRhiBuffer::StorageBuffer.
2742 */
2743QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
2744 int binding, StageFlags stage, QRhiBuffer *buf)
2745{
2746 QRhiShaderResourceBinding b;
2747 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2748 Q_ASSERT(d->ref.loadRelaxed() == 1);
2749 d->binding = binding;
2750 d->stage = stage;
2751 d->type = BufferLoad;
2752 d->u.sbuf.buf = buf;
2753 d->u.sbuf.offset = 0;
2754 d->u.sbuf.maybeSize = 0; // entire buffer
2755 return b;
2756}
2757
2758/*!
2759 \return a shader resource binding for a read-only storage buffer with the
2760 given \a binding number and pipeline \a stage. This overload binds a region
2761 only, as specified by \a offset and \a size.
2762
2763 \note \a buf must have been created with QRhiBuffer::StorageBuffer.
2764 */
2765QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
2766 int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
2767{
2768 Q_ASSERT(size > 0);
2769 QRhiShaderResourceBinding b = bufferLoad(binding, stage, buf);
2770 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2771 d->u.sbuf.offset = offset;
2772 d->u.sbuf.maybeSize = size;
2773 return b;
2774}
2775
2776/*!
2777 \return a shader resource binding for a write-only storage buffer with the
2778 given \a binding number and pipeline \a stage.
2779
2780 \note \a buf must have been created with QRhiBuffer::StorageBuffer.
2781 */
2782QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
2783 int binding, StageFlags stage, QRhiBuffer *buf)
2784{
2785 QRhiShaderResourceBinding b = bufferLoad(binding, stage, buf);
2786 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2787 d->type = BufferStore;
2788 return b;
2789}
2790
2791/*!
2792 \return a shader resource binding for a write-only storage buffer with the
2793 given \a binding number and pipeline \a stage. This overload binds a region
2794 only, as specified by \a offset and \a size.
2795
2796 \note \a buf must have been created with QRhiBuffer::StorageBuffer.
2797 */
2798QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
2799 int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
2800{
2801 Q_ASSERT(size > 0);
2802 QRhiShaderResourceBinding b = bufferStore(binding, stage, buf);
2803 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2804 d->u.sbuf.offset = offset;
2805 d->u.sbuf.maybeSize = size;
2806 return b;
2807}
2808
2809/*!
2810 \return a shader resource binding for a read-write storage buffer with the
2811 given \a binding number and pipeline \a stage.
2812
2813 \note \a buf must have been created with QRhiBuffer::StorageBuffer.
2814 */
2815QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
2816 int binding, StageFlags stage, QRhiBuffer *buf)
2817{
2818 QRhiShaderResourceBinding b = bufferLoad(binding, stage, buf);
2819 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2820 d->type = BufferLoadStore;
2821 return b;
2822}
2823
2824/*!
2825 \return a shader resource binding for a read-write storage buffer with the
2826 given \a binding number and pipeline \a stage. This overload binds a region
2827 only, as specified by \a offset and \a size.
2828
2829 \note \a buf must have been created with QRhiBuffer::StorageBuffer.
2830 */
2831QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
2832 int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
2833{
2834 Q_ASSERT(size > 0);
2835 QRhiShaderResourceBinding b = bufferLoadStore(binding, stage, buf);
2836 QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
2837 d->u.sbuf.offset = offset;
2838 d->u.sbuf.maybeSize = size;
2839 return b;
2840}
2841
2842/*!
2843 \return \c true if the contents of the two QRhiShaderResourceBinding
2844 objects \a a and \a b are equal. This includes the resources (buffer,
2845 texture) and related parameters (offset, size) as well. To only compare
2846 layouts (binding point, pipeline stage, resource type), use
2847 \l{QRhiShaderResourceBinding::isLayoutCompatible()}{isLayoutCompatible()}
2848 instead.
2849
2850 \relates QRhiShaderResourceBinding
2851 */
2852bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) Q_DECL_NOTHROW
2853{
2854 if (a.d == b.d)
2855 return true;
2856
2857 if (a.d->binding != b.d->binding
2858 || a.d->stage != b.d->stage
2859 || a.d->type != b.d->type)
2860 {
2861 return false;
2862 }
2863
2864 switch (a.d->type) {
2865 case QRhiShaderResourceBinding::UniformBuffer:
2866 if (a.d->u.ubuf.buf != b.d->u.ubuf.buf
2867 || a.d->u.ubuf.offset != b.d->u.ubuf.offset
2868 || a.d->u.ubuf.maybeSize != b.d->u.ubuf.maybeSize)
2869 {
2870 return false;
2871 }
2872 break;
2873 case QRhiShaderResourceBinding::SampledTexture:
2874 if (a.d->u.stex.tex != b.d->u.stex.tex
2875 || a.d->u.stex.sampler != b.d->u.stex.sampler)
2876 {
2877 return false;
2878 }
2879 break;
2880 case QRhiShaderResourceBinding::ImageLoad:
2881 Q_FALLTHROUGH();
2882 case QRhiShaderResourceBinding::ImageStore:
2883 Q_FALLTHROUGH();
2884 case QRhiShaderResourceBinding::ImageLoadStore:
2885 if (a.d->u.simage.tex != b.d->u.simage.tex
2886 || a.d->u.simage.level != b.d->u.simage.level)
2887 {
2888 return false;
2889 }
2890 break;
2891 case QRhiShaderResourceBinding::BufferLoad:
2892 Q_FALLTHROUGH();
2893 case QRhiShaderResourceBinding::BufferStore:
2894 Q_FALLTHROUGH();
2895 case QRhiShaderResourceBinding::BufferLoadStore:
2896 if (a.d->u.sbuf.buf != b.d->u.sbuf.buf
2897 || a.d->u.sbuf.offset != b.d->u.sbuf.offset
2898 || a.d->u.sbuf.maybeSize != b.d->u.sbuf.maybeSize)
2899 {
2900 return false;
2901 }
2902 break;
2903 default:
2904 Q_UNREACHABLE();
2905 return false;
2906 }
2907
2908 return true;
2909}
2910
2911/*!
2912 \return \c false if all the bindings in the two QRhiShaderResourceBinding
2913 objects \a a and \a b are equal; otherwise returns \c true.
2914
2915 \relates QRhiShaderResourceBinding
2916 */
2917bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) Q_DECL_NOTHROW
2918{
2919 return !(a == b);
2920}
2921
2922/*!
2923 \return the hash value for \a b, using \a seed to seed the calculation.
2924
2925 \relates QRhiShaderResourceBinding
2926 */
2927uint qHash(const QRhiShaderResourceBinding &b, uint seed) Q_DECL_NOTHROW
2928{
2929 const char *u = reinterpret_cast<const char *>(&b.d->u);
2930 return seed + b.d->binding + 10 * b.d->stage + 100 * b.d->type
2931 + qHash(QByteArray::fromRawData(u, sizeof(b.d->u)), seed);
2932}
2933
2934#ifndef QT_NO_DEBUG_STREAM
2935QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
2936{
2937 const QRhiShaderResourceBindingPrivate *d = b.d;
2938 QDebugStateSaver saver(dbg);
2939 dbg.nospace() << "QRhiShaderResourceBinding("
2940 << "binding=" << d->binding
2941 << " stage=" << d->stage
2942 << " type=" << d->type;
2943 switch (d->type) {
2944 case QRhiShaderResourceBinding::UniformBuffer:
2945 dbg.nospace() << " UniformBuffer("
2946 << "buffer=" << d->u.ubuf.buf
2947 << " offset=" << d->u.ubuf.offset
2948 << " maybeSize=" << d->u.ubuf.maybeSize
2949 << ')';
2950 break;
2951 case QRhiShaderResourceBinding::SampledTexture:
2952 dbg.nospace() << " SampledTexture("
2953 << "texture=" << d->u.stex.tex
2954 << " sampler=" << d->u.stex.sampler
2955 << ')';
2956 break;
2957 case QRhiShaderResourceBinding::ImageLoad:
2958 dbg.nospace() << " ImageLoad("
2959 << "texture=" << d->u.simage.tex
2960 << " level=" << d->u.simage.level
2961 << ')';
2962 break;
2963 case QRhiShaderResourceBinding::ImageStore:
2964 dbg.nospace() << " ImageStore("
2965 << "texture=" << d->u.simage.tex
2966 << " level=" << d->u.simage.level
2967 << ')';
2968 break;
2969 case QRhiShaderResourceBinding::ImageLoadStore:
2970 dbg.nospace() << " ImageLoadStore("
2971 << "texture=" << d->u.simage.tex
2972 << " level=" << d->u.simage.level
2973 << ')';
2974 break;
2975 case QRhiShaderResourceBinding::BufferLoad:
2976 dbg.nospace() << " BufferLoad("
2977 << "buffer=" << d->u.sbuf.buf
2978 << " offset=" << d->u.sbuf.offset
2979 << " maybeSize=" << d->u.sbuf.maybeSize
2980 << ')';
2981 break;
2982 case QRhiShaderResourceBinding::BufferStore:
2983 dbg.nospace() << " BufferStore("
2984 << "buffer=" << d->u.sbuf.buf
2985 << " offset=" << d->u.sbuf.offset
2986 << " maybeSize=" << d->u.sbuf.maybeSize
2987 << ')';
2988 break;
2989 case QRhiShaderResourceBinding::BufferLoadStore:
2990 dbg.nospace() << " BufferLoadStore("
2991 << "buffer=" << d->u.sbuf.buf
2992 << " offset=" << d->u.sbuf.offset
2993 << " maybeSize=" << d->u.sbuf.maybeSize
2994 << ')';
2995 break;
2996 default:
2997 Q_UNREACHABLE();
2998 break;
2999 }
3000 dbg.nospace() << ')';
3001 return dbg;
3002}
3003#endif
3004
3005#ifndef QT_NO_DEBUG_STREAM
3006QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
3007{
3008 QDebugStateSaver saver(dbg);
3009 dbg.nospace() << "QRhiShaderResourceBindings("
3010 << srb.m_bindings
3011 << ')';
3012 return dbg;
3013}
3014#endif
3015
3016/*!
3017 \class QRhiGraphicsPipeline
3018 \inmodule QtRhi
3019 \brief Graphics pipeline state resource.
3020
3021 \note Setting the shader resource bindings is mandatory. The referenced
3022 QRhiShaderResourceBindings must already be built by the time build() is
3023 called.
3024
3025 \note Setting the render pass descriptor is mandatory. To obtain a
3026 QRhiRenderPassDescriptor that can be passed to setRenderPassDescriptor(),
3027 use either QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() or
3028 QRhiSwapChain::newCompatibleRenderPassDescriptor().
3029
3030 \note Setting the vertex input layout is mandatory.
3031
3032 \note Setting the shader stages is mandatory.
3033
3034 \note sampleCount() defaults to 1 and must match the sample count of the
3035 render target's color and depth stencil attachments.
3036
3037 \note The depth test, depth write, and stencil test are disabled by
3038 default.
3039
3040 \note stencilReadMask() and stencilWriteMask() apply to both faces. They
3041 both default to 0xFF.
3042 */
3043
3044/*!
3045 \fn void QRhiGraphicsPipeline::setTargetBlends(const QVector<TargetBlend> &blends)
3046
3047 Sets the blend specification for color attachments. Each element in \a
3048 blends corresponds to a color attachment of the render target.
3049
3050 By default no blends are set, which is a shortcut to disabling blending and
3051 enabling color write for all four channels.
3052 */
3053
3054/*!
3055 \enum QRhiGraphicsPipeline::Flag
3056
3057 Flag values for describing the dynamic state of the pipeline. The viewport is always dynamic.
3058
3059 \value UsesBlendConstants Indicates that a blend color constant will be set
3060 via QRhiCommandBuffer::setBlendConstants()
3061
3062 \value UsesStencilRef Indicates that a stencil reference value will be set
3063 via QRhiCommandBuffer::setStencilRef()
3064
3065 \value UsesScissor Indicates that a scissor rectangle will be set via
3066 QRhiCommandBuffer::setScissor()
3067 */
3068
3069/*!
3070 \enum QRhiGraphicsPipeline::Topology
3071 Specifies the primitive topology
3072
3073 \value Triangles (default)
3074 \value TriangleStrip
3075 \value Lines
3076 \value LineStrip
3077 \value Points
3078 */
3079
3080/*!
3081 \enum QRhiGraphicsPipeline::CullMode
3082 Specifies the culling mode
3083
3084 \value None No culling (default)
3085 \value Front Cull front faces
3086 \value Back Cull back faces
3087 */
3088
3089/*!
3090 \enum QRhiGraphicsPipeline::FrontFace
3091 Specifies the front face winding order
3092
3093 \value CCW Counter clockwise (default)
3094 \value CW Clockwise
3095 */
3096
3097/*!
3098 \enum QRhiGraphicsPipeline::ColorMaskComponent
3099 Flag values for specifying the color write mask
3100
3101 \value R
3102 \value G
3103 \value B
3104 \value A
3105 */
3106
3107/*!
3108 \enum QRhiGraphicsPipeline::BlendFactor
3109 Specifies the blend factor
3110
3111 \value Zero
3112 \value One
3113 \value SrcColor
3114 \value OneMinusSrcColor
3115 \value DstColor
3116 \value OneMinusDstColor
3117 \value SrcAlpha
3118 \value OneMinusSrcAlpha
3119 \value DstAlpha
3120 \value OneMinusDstAlpha
3121 \value ConstantColor
3122 \value OneMinusConstantColor
3123 \value ConstantAlpha
3124 \value OneMinusConstantAlpha
3125 \value SrcAlphaSaturate
3126 \value Src1Color
3127 \value OneMinusSrc1Color
3128 \value Src1Alpha
3129 \value OneMinusSrc1Alpha
3130 */
3131
3132/*!
3133 \enum QRhiGraphicsPipeline::BlendOp
3134 Specifies the blend operation
3135
3136 \value Add
3137 \value Subtract
3138 \value ReverseSubtract
3139 \value Min
3140 \value Max
3141 */
3142
3143/*!
3144 \enum QRhiGraphicsPipeline::CompareOp
3145 Specifies the depth or stencil comparison function
3146
3147 \value Never
3148 \value Less (default for depth)
3149 \value Equal
3150 \value LessOrEqual
3151 \value Greater
3152 \value NotEqual
3153 \value GreaterOrEqual
3154 \value Always (default for stencil)
3155 */
3156
3157/*!
3158 \enum QRhiGraphicsPipeline::StencilOp
3159 Specifies the stencil operation
3160
3161 \value StencilZero
3162 \value Keep (default)
3163 \value Replace
3164 \value IncrementAndClamp
3165 \value DecrementAndClamp
3166 \value Invert
3167 \value IncrementAndWrap
3168 \value DecrementAndWrap
3169 */
3170
3171/*!
3172 \class QRhiGraphicsPipeline::TargetBlend
3173 \inmodule QtRhi
3174 \brief Describes the blend state for one color attachment.
3175
3176 Defaults to color write enabled, blending disabled. The blend values are
3177 set up for pre-multiplied alpha (One, OneMinusSrcAlpha, One,
3178 OneMinusSrcAlpha) by default.
3179 */
3180
3181/*!
3182 \class QRhiGraphicsPipeline::StencilOpState
3183 \inmodule QtRhi
3184 \brief Describes the stencil operation state.
3185 */
3186
3187/*!
3188 \internal
3189 */
3190QRhiGraphicsPipeline::QRhiGraphicsPipeline(QRhiImplementation *rhi)
3191 : QRhiResource(rhi)
3192{
3193}
3194
3195/*!
3196 \return the resource type.
3197 */
3198QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
3199{
3200 return GraphicsPipeline;
3201}
3202
3203/*!
3204 \fn bool QRhiGraphicsPipeline::build()
3205
3206 Creates the corresponding native graphics resources. If there are already
3207 resources present due to an earlier build() with no corresponding
3208 release(), then release() is called implicitly first.
3209
3210 \return \c true when successful, \c false when a graphics operation failed.
3211 Regardless of the return value, calling release() is always safe.
3212 */
3213
3214/*!
3215 \fn void QRhiGraphicsPipeline::setDepthTest(bool enable)
3216
3217 Enables or disables depth testing. Both depth test and the writing out of
3218 depth data are disabled by default.
3219
3220 \sa setDepthWrite()
3221 */
3222
3223/*!
3224 \fn void QRhiGraphicsPipeline::setDepthWrite(bool enable)
3225
3226 Controls the writing out of depth data into the depth buffer. By default
3227 this is disabled. Depth write is typically enabled together with the depth
3228 test.
3229
3230 \note Enabling depth write without having depth testing enabled may not
3231 lead to the desired result, and should be avoided.
3232
3233 \sa setDepthTest()
3234 */
3235
3236/*!
3237 \class QRhiSwapChain
3238 \inmodule QtRhi
3239 \brief Swapchain resource.
3240
3241 A swapchain enables presenting rendering results to a surface. A swapchain
3242 is typically backed by a set of color buffers. Of these, one is displayed
3243 at a time.
3244
3245 Below is a typical pattern for creating and managing a swapchain and some
3246 associated resources in order to render onto a QWindow:
3247
3248 \badcode
3249 void init()
3250 {
3251 sc = rhi->newSwapChain();
3252 ds = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
3253 QSize(), // no need to set the size yet
3254 1,
3255 QRhiRenderBuffer::UsedWithSwapChainOnly);
3256 sc->setWindow(window);
3257 sc->setDepthStencil(ds);
3258 rp = sc->newCompatibleRenderPassDescriptor();
3259 sc->setRenderPassDescriptor(rp);
3260 resizeSwapChain();
3261 }
3262
3263 void resizeSwapChain()
3264 {
3265 const QSize outputSize = sc->surfacePixelSize();
3266 ds->setPixelSize(outputSize);
3267 ds->build();
3268 hasSwapChain = sc->buildOrResize();
3269 }
3270
3271 void render()
3272 {
3273 if (!hasSwapChain || notExposed)
3274 return;
3275
3276 if (sc->currentPixelSize() != sc->surfacePixelSize() || newlyExposed) {
3277 resizeSwapChain();
3278 if (!hasSwapChain)
3279 return;
3280 newlyExposed = false;
3281 }
3282
3283 rhi->beginFrame(sc);
3284 // ...
3285 rhi->endFrame(sc);
3286 }
3287 \endcode
3288
3289 Avoid relying on QWindow resize events to resize swapchains, especially
3290 considering that surface sizes may not always fully match the QWindow
3291 reported dimensions. The safe, cross-platform approach is to do the check
3292 via surfacePixelSize() whenever starting a new frame.
3293
3294 Releasing the swapchain must happen while the QWindow and the underlying
3295 native window is fully up and running. Building on the previous example:
3296
3297 \badcode
3298 void releaseSwapChain()
3299 {
3300 if (hasSwapChain) {
3301 sc->release();
3302 hasSwapChain = false;
3303 }
3304 }
3305
3306 // assuming Window is our QWindow subclass
3307 bool Window::event(QEvent *e)
3308 {
3309 switch (e->type()) {
3310 case QEvent::UpdateRequest: // for QWindow::requestUpdate()
3311 render();
3312 break;
3313 case QEvent::PlatformSurface:
3314 if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
3315 releaseSwapChain();
3316 break;
3317 default:
3318 break;
3319 }
3320 return QWindow::event(e);
3321 }
3322 \endcode
3323
3324 Initializing the swapchain and starting to render the first frame cannot
3325 start at any time. The safe, cross-platform approach is to rely on expose
3326 events. QExposeEvent is a loosely specified event that is sent whenever a
3327 window gets mapped, obscured, and resized, depending on the platform.
3328
3329 \badcode
3330 void Window::exposeEvent(QExposeEvent *)
3331 {
3332 // initialize and start rendering when the window becomes usable for graphics purposes
3333 if (isExposed() && !running) {
3334 running = true;
3335 init();
3336 }
3337
3338 // stop pushing frames when not exposed or size becomes 0
3339 if ((!isExposed() || (hasSwapChain && sc->surfacePixelSize().isEmpty())) && running)
3340 notExposed = true;
3341
3342 // continue when exposed again and the surface has a valid size
3343 if (isExposed() && running && notExposed && !sc->surfacePixelSize().isEmpty()) {
3344 notExposed = false;
3345 newlyExposed = true;
3346 }
3347
3348 if (isExposed() && !sc->surfacePixelSize().isEmpty())
3349 render();
3350 }
3351 \endcode
3352
3353 Once the rendering has started, a simple way to request a new frame is
3354 QWindow::requestUpdate(). While on some platforms this is merely a small
3355 timer, on others it has a specific implementation: for instance on macOS or
3356 iOS it may be backed by
3357 \l{https://developer.apple.com/documentation/corevideo/cvdisplaylink?language=objc}{CVDisplayLink}.
3358 The example above is already prepared for update requests by handling
3359 QEvent::UpdateRequest.
3360
3361 While acting as a QRhiRenderTarget, QRhiSwapChain also manages a
3362 QRhiCommandBuffer. Calling QRhi::endFrame() submits the recorded commands
3363 and also enqueues a \c present request. The default behavior is to do this
3364 with a swap interval of 1, meaning synchronizing to the display's vertical
3365 refresh is enabled. Thus the rendering thread calling beginFrame() and
3366 endFrame() will get throttled to vsync. On some backends this can be
3367 disabled by passing QRhiSwapChain:NoVSync in flags().
3368
3369 Multisampling (MSAA) is handled transparently to the applications when
3370 requested via setSampleCount(). Where applicable, QRhiSwapChain will take
3371 care of creating additional color buffers and issuing a multisample resolve
3372 command at the end of a frame. For OpenGL, it is necessary to request the
3373 appropriate sample count also via QSurfaceFormat, by calling
3374 QSurfaceFormat::setDefaultFormat() before initializing the QRhi.
3375 */
3376
3377/*!
3378 \enum QRhiSwapChain::Flag
3379 Flag values to describe swapchain properties
3380
3381 \value SurfaceHasPreMulAlpha Indicates that the target surface has
3382 transparency with premultiplied alpha.
3383
3384 \value SurfaceHasNonPreMulAlpha Indicates the target surface has
3385 transparencyt with non-premultiplied alpha.
3386
3387 \value sRGB Requests to pick an sRGB format for the swapchain and/or its
3388 render target views, where applicable. Note that this implies that sRGB
3389 framebuffer update and blending will get enabled for all content targeting
3390 this swapchain, and opting out is not possible. For OpenGL, set
3391 \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the QSurfaceFormat of
3392 the QWindow in addition.
3393
3394 \value UsedAsTransferSource Indicates the the swapchain will be used as the
3395 source of a readback in QRhiResourceUpdateBatch::readBackTexture().
3396
3397 \value NoVSync Requests disabling waiting for vertical sync, also avoiding
3398 throttling the rendering thread. The behavior is backend specific and
3399 applicable only where it is possible to control this. Some may ignore the
3400 request altogether. For OpenGL, try instead setting the swap interval to 0
3401 on the QWindow via QSurfaceFormat::setSwapInterval().
3402
3403 \value MinimalBufferCount Requests creating the swapchain with the minimum
3404 number of buffers, which is in practice 2, unless the graphics
3405 implementation has a higher minimum number than that. Only applicable with
3406 backends where such control is available via the graphics API, for example,
3407 Vulkan. By default it is up to the backend to decide what number of buffers
3408 it requests (in practice this is almost always either 2 or 3), and it is
3409 not the applications' concern. However, on Vulkan for instance the backend
3410 will likely prefer the higher number (3), for example to avoid odd
3411 performance issues with some Vulkan implementations on mobile devices. It
3412 could be that on some platforms it can prove to be beneficial to force the
3413 lower buffer count (2), so this flag allows forcing that. Note that all
3414 this has no effect on the number of frames kept in flight, so the CPU
3415 (QRhi) will still prepare frames at most \c{N - 1} frames ahead of the GPU,
3416 even when the swapchain image buffer count larger than \c N. (\c{N} =
3417 QRhi::FramesInFlight and typically 2).
3418 */
3419
3420/*!
3421 \internal
3422 */
3423QRhiSwapChain::QRhiSwapChain(QRhiImplementation *rhi)
3424 : QRhiResource(rhi)
3425{
3426}
3427
3428/*!
3429 \return the resource type.
3430 */
3431QRhiResource::Type QRhiSwapChain::resourceType() const
3432{
3433 return SwapChain;
3434}
3435
3436/*!
3437 \fn QSize QRhiSwapChain::currentPixelSize() const
3438
3439 \return the size with which the swapchain was last successfully built. Use
3440 this to decide if buildOrResize() needs to be called again: if
3441 \c{currentPixelSize() != surfacePixelSize()} then the swapchain needs to be
3442 resized.
3443
3444 \sa surfacePixelSize()
3445 */
3446
3447/*!
3448 \fn QSize QRhiSwapChain::surfacePixelSize()
3449
3450 \return The size of the window's associated surface or layer. Do not assume
3451 this is the same as QWindow::size() * QWindow::devicePixelRatio().
3452
3453 Can be called before buildOrResize() (but with window() already set), which
3454 allows setting the correct size for the depth-stencil buffer that is then
3455 used together with the swapchain's color buffers. Also used in combination
3456 with currentPixelSize() to detect size changes.
3457
3458 \sa currentPixelSize()
3459 */
3460
3461/*!
3462 \fn QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer()
3463
3464 \return a command buffer on which rendering commands can be recorded. Only
3465 valid within a QRhi::beginFrame() - QRhi::endFrame() block where
3466 beginFrame() was called with this swapchain.
3467
3468 \note the value must not be cached and reused between frames
3469*/
3470
3471/*!
3472 \fn QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget()
3473
3474 \return a render target that can used with beginPass() in order to render
3475 the the swapchain's current backbuffer. Only valid within a
3476 QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called
3477 with this swapchain.
3478
3479 \note the value must not be cached and reused between frames
3480 */
3481
3482/*!
3483 \fn bool QRhiSwapChain::buildOrResize()
3484
3485 Creates the swapchain if not already done and resizes the swapchain buffers
3486 to match the current size of the targeted surface. Call this whenever the
3487 size of the target surface is different than before.
3488
3489 \note call release() only when the swapchain needs to be released
3490 completely, typically upon
3491 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed. To perform resizing, just
3492 call buildOrResize().
3493
3494 \return \c true when successful, \c false when a graphics operation failed.
3495 Regardless of the return value, calling release() is always safe.
3496 */
3497
3498/*!
3499 \class QRhiComputePipeline
3500 \inmodule QtRhi
3501 \brief Compute pipeline state resource.
3502
3503 \note Setting the shader resource bindings is mandatory. The referenced
3504 QRhiShaderResourceBindings must already be built by the time build() is
3505 called.
3506
3507 \note Setting the shader is mandatory.
3508 */
3509
3510/*!
3511 \return the resource type.
3512 */
3513QRhiResource::Type QRhiComputePipeline::resourceType() const
3514{
3515 return ComputePipeline;
3516}
3517
3518/*!
3519 \internal
3520 */
3521QRhiComputePipeline::QRhiComputePipeline(QRhiImplementation *rhi)
3522 : QRhiResource(rhi)
3523{
3524}
3525
3526/*!
3527 \class QRhiCommandBuffer
3528 \inmodule QtRhi
3529 \brief Command buffer resource.
3530
3531 Not creatable by applications at the moment. The only ways to obtain a
3532 valid QRhiCommandBuffer are to get it from the targeted swapchain via
3533 QRhiSwapChain::currentFrameCommandBuffer(), or, in case of rendering
3534 completely offscreen, initializing one via QRhi::beginOffscreenFrame().
3535 */
3536
3537/*!
3538 \enum QRhiCommandBuffer::IndexFormat
3539 Specifies the index data type
3540
3541 \value IndexUInt16 Unsigned 16-bit (quint16)
3542 \value IndexUInt32 Unsigned 32-bit (quint32)
3543 */
3544
3545/*!
3546 \typedef QRhiCommandBuffer::DynamicOffset
3547
3548 Synonym for QPair<int, quint32>. The first entry is the binding, the second
3549 is the offset in the buffer.
3550*/
3551
3552/*!
3553 \typedef QRhiCommandBuffer::VertexInput
3554
3555 Synonym for QPair<QRhiBuffer *, quint32>. The second entry is an offset in
3556 the buffer specified by the first.
3557*/
3558
3559/*!
3560 \internal
3561 */
3562QRhiCommandBuffer::QRhiCommandBuffer(QRhiImplementation *rhi)
3563 : QRhiResource(rhi)
3564{
3565}
3566
3567/*!
3568 \return the resource type.
3569 */
3570QRhiResource::Type QRhiCommandBuffer::resourceType() const
3571{
3572 return CommandBuffer;
3573}
3574
3575QRhiImplementation::~QRhiImplementation()
3576{
3577 qDeleteAll(resUpdPool);
3578
3579 // Be nice and show something about leaked stuff. Though we may not get
3580 // this far with some backends where the allocator or the api may check
3581 // and freak out for unfreed graphics objects in the derived dtor already.
3582#ifndef QT_NO_DEBUG
3583 if (!resources.isEmpty()) {
3584 qWarning("QRhi %p going down with %d unreleased resources. This is not nice.",
3585 q, resources.count());
3586 for (QRhiResource *res : qAsConst(resources)) {
3587 qWarning(" Resource %p (%s)", res, res->m_objectName.constData());
3588 res->m_rhi = nullptr;
3589 }
3590 }
3591#endif
3592}
3593
3594bool QRhiImplementation::isCompressedFormat(QRhiTexture::Format format) const
3595{
3596 return (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
3597 || (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
3598 || (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12);
3599}
3600
3601void QRhiImplementation::compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
3602 quint32 *bpl, quint32 *byteSize,
3603 QSize *blockDim) const
3604{
3605 int xdim = 4;
3606 int ydim = 4;
3607 quint32 blockSize = 0;
3608
3609 switch (format) {
3610 case QRhiTexture::BC1:
3611 blockSize = 8;
3612 break;
3613 case QRhiTexture::BC2:
3614 blockSize = 16;
3615 break;
3616 case QRhiTexture::BC3:
3617 blockSize = 16;
3618 break;
3619 case QRhiTexture::BC4:
3620 blockSize = 8;
3621 break;
3622 case QRhiTexture::BC5:
3623 blockSize = 16;
3624 break;
3625 case QRhiTexture::BC6H:
3626 blockSize = 16;
3627 break;
3628 case QRhiTexture::BC7:
3629 blockSize = 16;
3630 break;
3631
3632 case QRhiTexture::ETC2_RGB8:
3633 blockSize = 8;
3634 break;
3635 case QRhiTexture::ETC2_RGB8A1:
3636 blockSize = 8;
3637 break;
3638 case QRhiTexture::ETC2_RGBA8:
3639 blockSize = 16;
3640 break;
3641
3642 case QRhiTexture::ASTC_4x4:
3643 blockSize = 16;
3644 break;
3645 case QRhiTexture::ASTC_5x4:
3646 blockSize = 16;
3647 xdim = 5;
3648 break;
3649 case QRhiTexture::ASTC_5x5:
3650 blockSize = 16;
3651 xdim = ydim = 5;
3652 break;
3653 case QRhiTexture::ASTC_6x5:
3654 blockSize = 16;
3655 xdim = 6;
3656 ydim = 5;
3657 break;
3658 case QRhiTexture::ASTC_6x6:
3659 blockSize = 16;
3660 xdim = ydim = 6;
3661 break;
3662 case QRhiTexture::ASTC_8x5:
3663 blockSize = 16;
3664 xdim = 8;
3665 ydim = 5;
3666 break;
3667 case QRhiTexture::ASTC_8x6:
3668 blockSize = 16;
3669 xdim = 8;
3670 ydim = 6;
3671 break;
3672 case QRhiTexture::ASTC_8x8:
3673 blockSize = 16;
3674 xdim = ydim = 8;
3675 break;
3676 case QRhiTexture::ASTC_10x5:
3677 blockSize = 16;
3678 xdim = 10;
3679 ydim = 5;
3680 break;
3681 case QRhiTexture::ASTC_10x6:
3682 blockSize = 16;
3683 xdim = 10;
3684 ydim = 6;
3685 break;
3686 case QRhiTexture::ASTC_10x8:
3687 blockSize = 16;
3688 xdim = 10;
3689 ydim = 8;
3690 break;
3691 case QRhiTexture::ASTC_10x10:
3692 blockSize = 16;
3693 xdim = ydim = 10;
3694 break;
3695 case QRhiTexture::ASTC_12x10:
3696 blockSize = 16;
3697 xdim = 12;
3698 ydim = 10;
3699 break;
3700 case QRhiTexture::ASTC_12x12:
3701 blockSize = 16;
3702 xdim = ydim = 12;
3703 break;
3704
3705 default:
3706 Q_UNREACHABLE();
3707 break;
3708 }
3709
3710 const quint32 wblocks = (size.width() + xdim - 1) / xdim;
3711 const quint32 hblocks = (size.height() + ydim - 1) / ydim;
3712
3713 if (bpl)
3714 *bpl = wblocks * blockSize;
3715 if (byteSize)
3716 *byteSize = wblocks * hblocks * blockSize;
3717 if (blockDim)
3718 *blockDim = QSize(xdim, ydim);
3719}
3720
3721void QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSize &size,
3722 quint32 *bpl, quint32 *byteSize) const
3723{
3724 if (isCompressedFormat(format)) {
3725 compressedFormatInfo(format, size, bpl, byteSize, nullptr);
3726 return;
3727 }
3728
3729 quint32 bpc = 0;
3730 switch (format) {
3731 case QRhiTexture::RGBA8:
3732 bpc = 4;
3733 break;
3734 case QRhiTexture::BGRA8:
3735 bpc = 4;
3736 break;
3737 case QRhiTexture::R8:
3738 bpc = 1;
3739 break;
3740 case QRhiTexture::R16:
3741 bpc = 2;
3742 break;
3743 case QRhiTexture::RED_OR_ALPHA8:
3744 bpc = 1;
3745 break;
3746
3747 case QRhiTexture::RGBA16F:
3748 bpc = 8;
3749 break;
3750 case QRhiTexture::RGBA32F:
3751 bpc = 16;
3752 break;
3753
3754 case QRhiTexture::D16:
3755 bpc = 2;
3756 break;
3757 case QRhiTexture::D32F:
3758 bpc = 4;
3759 break;
3760
3761 default:
3762 Q_UNREACHABLE();
3763 break;
3764 }
3765
3766 if (bpl)
3767 *bpl = size.width() * bpc;
3768 if (byteSize)
3769 *byteSize = size.width() * size.height() * bpc;
3770}
3771
3772// Approximate because it excludes subresource alignment or multisampling.
3773quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format, const QSize &baseSize,
3774 int mipCount, int layerCount)
3775{
3776 quint32 approxSize = 0;
3777 for (int level = 0; level < mipCount; ++level) {
3778 quint32 byteSize = 0;
3779 const QSize size(qFloor(float(qMax(1, baseSize.width() >> level))),
3780 qFloor(float(qMax(1, baseSize.height() >> level))));
3781 textureFormatInfo(format, size, nullptr, &byteSize);
3782 approxSize += byteSize;
3783 }
3784 approxSize *= layerCount;
3785 return approxSize;
3786}
3787
3788/*!
3789 \internal
3790 */
3791QRhi::QRhi()
3792{
3793}
3794
3795/*!
3796 Destructor. Destroys the backend and releases resources.
3797 */
3798QRhi::~QRhi()
3799{
3800 if (!d)
3801 return;
3802
3803 qDeleteAll(d->pendingReleaseAndDestroyResources);
3804 d->pendingReleaseAndDestroyResources.clear();
3805
3806 runCleanup();
3807
3808 d->destroy();
3809 delete d;
3810}
3811
3812/*!
3813 \return a new QRhi instance with a backend for the graphics API specified by \a impl.
3814
3815 \a params must point to an instance of one of the backend-specific
3816 subclasses of QRhiInitParams, such as, QRhiVulkanInitParams,
3817 QRhiMetalInitParams, QRhiD3D11InitParams, QRhiGles2InitParams. See these
3818 classes for examples on creating a QRhi.
3819
3820 \a flags is optional. It is used to enable profile and debug related
3821 features that are potentially expensive and should only be used during
3822 development.
3823 */
3824QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice)
3825{
3826 QScopedPointer<QRhi> r(new QRhi);
3827
3828 switch (impl) {
3829 case Null:
3830 r->d = new QRhiNull(static_cast<QRhiNullInitParams *>(params));
3831 break;
3832 case Vulkan:
3833#if QT_CONFIG(vulkan)
3834 r->d = new QRhiVulkan(static_cast<QRhiVulkanInitParams *>(params),
3835 static_cast<QRhiVulkanNativeHandles *>(importDevice));
3836 break;
3837#else
3838 Q_UNUSED(importDevice);
3839 qWarning("This build of Qt has no Vulkan support");
3840 break;
3841#endif
3842 case OpenGLES2:
3843#ifndef QT_NO_OPENGL
3844 r->d = new QRhiGles2(static_cast<QRhiGles2InitParams *>(params),
3845 static_cast<QRhiGles2NativeHandles *>(importDevice));
3846 break;
3847#else
3848 qWarning("This build of Qt has no OpenGL support");
3849 break;
3850#endif
3851 case D3D11:
3852#ifdef Q_OS_WIN
3853 r->d = new QRhiD3D11(static_cast<QRhiD3D11InitParams *>(params),
3854 static_cast<QRhiD3D11NativeHandles *>(importDevice));
3855 break;
3856#else
3857 qWarning("This platform has no Direct3D 11 support");
3858 break;
3859#endif
3860 case Metal:
3861//#ifdef Q_OS_DARWIN
3862#ifdef Q_OS_MACOS
3863 r->d = new QRhiMetal(static_cast<QRhiMetalInitParams *>(params),
3864 static_cast<QRhiMetalNativeHandles *>(importDevice));
3865 break;
3866#else
3867 qWarning("This platform has no Metal support");
3868 break;
3869#endif
3870 default:
3871 break;
3872 }
3873
3874 if (r->d) {
3875 r->d->q = r.data();
3876 if (flags.testFlag(EnableProfiling)) {
3877 QRhiProfilerPrivate *profD = QRhiProfilerPrivate::get(&r->d->profiler);
3878 profD->rhiDWhenEnabled = r->d;
3879 }
3880 r->d->debugMarkers = flags.testFlag(EnableDebugMarkers);
3881 if (r->d->create(flags)) {
3882 r->d->implType = impl;
3883 r->d->implThread = QThread::currentThread();
3884 return r.take();
3885 }
3886 }
3887
3888 return nullptr;
3889}
3890
3891/*!
3892 \return the backend type for this QRhi.
3893 */
3894QRhi::Implementation QRhi::backend() const
3895{
3896 return d->implType;
3897}
3898
3899/*!
3900 \return the thread on which the QRhi was \l{QRhi::create()}{initialized}.
3901 */
3902QThread *QRhi::thread() const
3903{
3904 return d->implThread;
3905}
3906
3907/*!
3908 Registers a \a callback that is invoked either when the QRhi is destroyed,
3909 or when runCleanup() is called.
3910
3911 The callback will run with the graphics resource still available, so this
3912 provides an opportunity for the application to cleanly release QRhiResource
3913 instances belonging to the QRhi. This is particularly useful for managing
3914 the lifetime of resources stored in \c cache type of objects, where the
3915 cache holds QRhiResources or objects containing QRhiResources.
3916
3917 \sa runCleanup(), ~QRhi()
3918 */
3919void QRhi::addCleanupCallback(const CleanupCallback &callback)
3920{
3921 d->addCleanupCallback(callback);
3922}
3923
3924/*!
3925 Invokes all registered cleanup functions. The list of cleanup callbacks it
3926 then cleared. Normally destroying the QRhi does this automatically, but
3927 sometimes it can be useful to trigger cleanup in order to release all
3928 cached, non-essential resources.
3929
3930 \sa addCleanupCallback()
3931 */
3932void QRhi::runCleanup()
3933{
3934 for (const CleanupCallback &f : qAsConst(d->cleanupCallbacks))
3935 f(this);
3936
3937 d->cleanupCallbacks.clear();
3938}
3939
3940/*!
3941 \class QRhiResourceUpdateBatch
3942 \inmodule QtRhi
3943 \brief Records upload and copy type of operations.
3944
3945 With QRhi it is no longer possible to perform copy type of operations at
3946 arbitrary times. Instead, all such operations are recorded into batches
3947 that are then passed, most commonly, to QRhiCommandBuffer::beginPass().
3948 What then happens under the hood is hidden from the application: the
3949 underlying implementations can defer and implement these operations in
3950 various different ways.
3951
3952 A resource update batch owns no graphics resources and does not perform any
3953 actual operations on its own. It should rather be viewed as a command
3954 buffer for update, upload, and copy type of commands.
3955
3956 To get an available, empty batch from the pool, call
3957 QRhi::nextResourceUpdateBatch().
3958 */
3959
3960/*!
3961 \internal
3962 */
3963QRhiResourceUpdateBatch::QRhiResourceUpdateBatch(QRhiImplementation *rhi)
3964 : d(new QRhiResourceUpdateBatchPrivate)
3965{
3966 d->q = this;
3967 d->rhi = rhi;
3968}
3969
3970QRhiResourceUpdateBatch::~QRhiResourceUpdateBatch()
3971{
3972 delete d;
3973}
3974
3975/*!
3976 \return the batch to the pool. This should only be used when the batch is
3977 not passed to one of QRhiCommandBuffer::beginPass(),
3978 QRhiCommandBuffer::endPass(), or QRhiCommandBuffer::resourceUpdate()
3979 because these implicitly call release().
3980
3981 \note QRhiResourceUpdateBatch instances must never by \c deleted by
3982 applications.
3983 */
3984void QRhiResourceUpdateBatch::release()
3985{
3986 d->free();
3987}
3988
3989/*!
3990 Copies all queued operations from the \a other batch into this one.
3991
3992 \note \a other is not changed in any way, typically it will still need a
3993 release()
3994
3995 This allows for a convenient pattern where resource updates that are
3996 already known during the initialization step are collected into a batch
3997 that is then merged into another when starting to first render pass later
3998 on:
3999
4000 \badcode
4001 void init()
4002 {
4003 ...
4004 initialUpdates = rhi->nextResourceUpdateBatch();
4005 initialUpdates->uploadStaticBuffer(vbuf, vertexData);
4006 initialUpdates->uploadStaticBuffer(ibuf, indexData);
4007 ...
4008 }
4009
4010 void render()
4011 {
4012 ...
4013 QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
4014 if (initialUpdates) {
4015 resUpdates->merge(initialUpdates);
4016 initialUpdates->release();
4017 initialUpdates = nullptr;
4018 }
4019 resUpdates->updateDynamicBuffer(...);
4020 ...
4021 cb->beginPass(rt, clearCol, clearDs, resUpdates);
4022 }
4023 \endcode
4024 */
4025void QRhiResourceUpdateBatch::merge(QRhiResourceUpdateBatch *other)
4026{
4027 d->merge(other->d);
4028}
4029
4030/*!
4031 Enqueues updating a region of a QRhiBuffer \a buf created with the type
4032 QRhiBuffer::Dynamic.
4033
4034 The region is specified \a offset and \a size. The actual bytes to write
4035 are specified by \a data which must have at least \a size bytes available.
4036 \a data can safely be destroyed or changed once this function returns.
4037
4038 \note If host writes are involved, which is the case with
4039 updateDynamicBuffer() typically as such buffers are backed by host visible
4040 memory with most backends, they may accumulate within a frame. Thus pass 1
4041 reading a region changed by a batch passed to pass 2 may see the changes
4042 specified in pass 2's update batch.
4043
4044 \note QRhi transparently manages double buffering in order to prevent
4045 stalling the graphics pipeline. The fact that a QRhiBuffer may have
4046 multiple native underneath can be safely ignored when using the QRhi and
4047 QRhiResourceUpdateBatch.
4048 */
4049void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, int offset, int size, const void *data)
4050{
4051 if (size > 0)
4052 d->dynamicBufferUpdates.append({ buf, offset, size, data });
4053}
4054
4055/*!
4056 Enqueues updating a region of a QRhiBuffer \a buf created with the type
4057 QRhiBuffer::Immutable or QRhiBuffer::Static.
4058
4059 The region is specified \a offset and \a size. The actual bytes to write
4060 are specified by \a data which must have at least \a size bytes available.
4061 \a data can safely be destroyed or changed once this function returns.
4062 */
4063void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, int offset, int size, const void *data)
4064{
4065 if (size > 0)
4066 d->staticBufferUploads.append({ buf, offset, size, data });
4067}
4068
4069/*!
4070 Enqueues updating the entire QRhiBuffer \a buf created with the type
4071 QRhiBuffer::Immutable or QRhiBuffer::Static.
4072 */
4073void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *data)
4074{
4075 if (buf->size() > 0)
4076 d->staticBufferUploads.append({ buf, 0, 0, data });
4077}
4078
4079/*!
4080 Enqueues uploading the image data for one or more mip levels in one or more
4081 layers of the texture \a tex.
4082
4083 The details of the copy (source QImage or compressed texture data, regions,
4084 target layers and levels) are described in \a desc.
4085 */
4086void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
4087{
4088 if (!desc.entries().isEmpty())
4089 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::textureUpload(tex, desc));
4090}
4091
4092/*!
4093 Enqueues uploading the image data for mip level 0 of layer 0 of the texture
4094 \a tex.
4095
4096 \a tex must have an uncompressed format. Its format must also be compatible
4097 with the QImage::format() of \a image. The source data is given in \a
4098 image.
4099 */
4100void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &image)
4101{
4102 uploadTexture(tex, QRhiTextureUploadEntry(0, 0, image));
4103}
4104
4105/*!
4106 Enqueues a texture-to-texture copy operation from \a src into \a dst as
4107 described by \a desc.
4108
4109 \note The source texture \a src must be created with
4110 QRhiTexture::UsedAsTransferSource.
4111 */
4112void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
4113{
4114 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::textureCopy(dst, src, desc));
4115}
4116
4117/*!
4118 Enqueues a texture-to-host copy operation as described by \a rb.
4119
4120 Normally \a rb will specify a QRhiTexture as the source. However, when the
4121 swapchain in the current frame was created with
4122 QRhiSwapChain::UsedAsTransferSource, it can also be the source of the
4123 readback. For this, leave the texture set to null in \a rb.
4124
4125 Unlike other operations, the results here need to be processed by the
4126 application. Therefore, \a result provides not just the data but also a
4127 callback as operations on the batch are asynchronous by nature:
4128
4129 \badcode
4130 beginFrame(sc);
4131 beginPass
4132 ...
4133 QRhiReadbackResult *rbResult = new QRhiReadbackResult;
4134 rbResult->completed = [rbResult] {
4135 {
4136 const QImage::Format fmt = QImage::Format_RGBA8888_Premultiplied; // fits QRhiTexture::RGBA8
4137 const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
4138 QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
4139 image.save("result.png");
4140 }
4141 delete rbResult;
4142 };
4143 u = nextResourceUpdateBatch();
4144 QRhiReadbackDescription rb; // no texture -> uses the current backbuffer of sc
4145 u->readBackTexture(rb, rbResult);
4146 endPass(u);
4147 endFrame(sc);
4148 \endcode
4149
4150 \note The texture must be created with QRhiTexture::UsedAsTransferSource.
4151
4152 \note Multisample textures cannot be read back.
4153
4154 \note The readback returns raw byte data, in order to allow the applications
4155 to interpret it in any way they see fit. Be aware of the blending settings
4156 of rendering code: if the blending is set up to rely on premultiplied alpha,
4157 the results of the readback must also be interpreted as Premultiplied.
4158
4159 \note When interpreting the resulting raw data, be aware that the readback
4160 happens with a byte ordered format. A \l{QRhiTexture::RGBA8}{RGBA8} texture
4161 maps therefore to byte ordered QImage formats, such as,
4162 QImage::Format_RGBA8888.
4163 */
4164void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
4165{
4166 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::textureRead(rb, result));
4167}
4168
4169/*!
4170 Enqueues a mipmap generation operation for the specified \a layer of texture
4171 \a tex.
4172
4173 \note The texture must be created with QRhiTexture::MipMapped and
4174 QRhiTexture::UsedWithGenerateMips.
4175 */
4176void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex, int layer)
4177{
4178 d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::textureMipGen(tex, layer));
4179}
4180
4181/*!
4182 \return an available, empty batch to which copy type of operations can be
4183 recorded.
4184
4185 \note the return value is not owned by the caller and must never be
4186 destroyed. Instead, the batch is returned the the pool for reuse by passing
4187 it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or
4188 QRhiCommandBuffer::resourceUpdate(), or by calling
4189 QRhiResourceUpdateBatch::release() on it.
4190
4191 \note Can be called outside beginFrame() - endFrame() as well since a batch
4192 instance just collects data on its own, it does not perform any operations.
4193 */
4194QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
4195{
4196 auto nextFreeBatch = [this]() -> QRhiResourceUpdateBatch * {
4197 for (int i = 0, ie = d->resUpdPoolMap.count(); i != ie; ++i) {
4198 if (!d->resUpdPoolMap.testBit(i)) {
4199 d->resUpdPoolMap.setBit(i);
4200 QRhiResourceUpdateBatch *u = d->resUpdPool[i];
4201 QRhiResourceUpdateBatchPrivate::get(u)->poolIndex = i;
4202 return u;
4203 }
4204 }
4205 return nullptr;
4206 };
4207
4208 QRhiResourceUpdateBatch *u = nextFreeBatch();
4209 if (!u) {
4210 const int oldSize = d->resUpdPool.count();
4211 const int newSize = oldSize + 4;
4212 d->resUpdPool.resize(newSize);
4213 d->resUpdPoolMap.resize(newSize);
4214 for (int i = oldSize; i < newSize; ++i)
4215 d->resUpdPool[i] = new QRhiResourceUpdateBatch(d);
4216 u = nextFreeBatch();
4217 Q_ASSERT(u);
4218 }
4219
4220 return u;
4221}
4222
4223void QRhiResourceUpdateBatchPrivate::free()
4224{
4225 Q_ASSERT(poolIndex >= 0 && rhi->resUpdPool[poolIndex] == q);
4226
4227 dynamicBufferUpdates.clear();
4228 staticBufferUploads.clear();
4229 textureOps.clear();
4230
4231 rhi->resUpdPoolMap.clearBit(poolIndex);
4232 poolIndex = -1;
4233}
4234
4235void QRhiResourceUpdateBatchPrivate::merge(QRhiResourceUpdateBatchPrivate *other)
4236{
4237 dynamicBufferUpdates += other->dynamicBufferUpdates;
4238 staticBufferUploads += other->staticBufferUploads;
4239 textureOps += other->textureOps;
4240}
4241
4242/*!
4243 Sometimes committing resource updates is necessary without starting a
4244 render pass. Not often needed, updates should typically be passed to
4245 beginPass (or endPass, in case of readbacks) instead.
4246
4247 \note Cannot be called inside a pass.
4248 */
4249void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
4250{
4251 if (resourceUpdates)
4252 m_rhi->resourceUpdate(this, resourceUpdates);
4253}
4254
4255/*!
4256 Records starting a new render pass targeting the render target \a rt.
4257
4258 \a resourceUpdates, when not null, specifies a resource update batch that
4259 is to be committed and then released.
4260
4261 The color and depth/stencil buffers of the render target are normally
4262 cleared. The clear values are specified in \a colorClearValue and \a
4263 depthStencilClearValue. The exception is when the render target was created
4264 with QRhiTextureRenderTarget::PreserveColorContents and/or
4265 QRhiTextureRenderTarget::PreserveDepthStencilContents. The clear values are
4266 ignored then.
4267
4268 \note Enabling preserved color or depth contents leads to decreased
4269 performance depending on the underlying hardware. Mobile GPUs with tiled
4270 architecture benefit from not having to reload the previous contents into
4271 the tile buffer. Similarly, a QRhiTextureRenderTarget with a QRhiTexture as
4272 the depth buffer is less efficient than a QRhiRenderBuffer since using a
4273 depth texture triggers requiring writing the data out to it, while with
4274 renderbuffers this is not needed (as the API does not allow sampling or
4275 reading from a renderbuffer).
4276
4277 \note Do not assume that any state or resource bindings persist between
4278 passes.
4279
4280 \note The QRhiCommandBuffer's \c set and \c draw functions can only be
4281 called inside a pass. Also, with the exception of setGraphicsPipeline(),
4282 they expect to have a pipeline set already on the command buffer.
4283 Unspecified issues may arise otherwise, depending on the backend.
4284 */
4285void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
4286 const QColor &colorClearValue,
4287 const QRhiDepthStencilClearValue &depthStencilClearValue,
4288 QRhiResourceUpdateBatch *resourceUpdates)
4289{
4290 m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates);
4291}
4292
4293/*!
4294 Records ending the current render pass.
4295
4296 \a resourceUpdates, when not null, specifies a resource update batch that
4297 is to be committed and then released.
4298 */
4299void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates)
4300{
4301 m_rhi->endPass(this, resourceUpdates);
4302}
4303
4304/*!
4305 Records setting a new graphics pipeline \a ps.
4306
4307 \note This function must be called before recording other \c set or \c draw
4308 commands on the command buffer.
4309
4310 \note QRhi will optimize out unnecessary invocations within a pass, so
4311 therefore overoptimizing to avoid calls to this function is not necessary
4312 on the applications' side.
4313
4314 \note This function can only be called inside a render pass, meaning
4315 between a beginPass() and endPass() call.
4316 */
4317void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)
4318{
4319 m_rhi->setGraphicsPipeline(this, ps);
4320}
4321
4322/*!
4323 Records binding a set of shader resources, such as, uniform buffers or
4324 textures, that are made visible to one or more shader stages.
4325
4326 \a srb can be null in which case the current graphics or compute pipeline's
4327 associated QRhiShaderResourceBindings is used. When \a srb is non-null, it
4328 must be
4329 \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible},
4330 meaning the layout (number of bindings, the type and binding number of each
4331 binding) must fully match the QRhiShaderResourceBindings that was
4332 associated with the pipeline at the time of calling the pipeline's build().
4333
4334 There are cases when a seemingly unnecessary setShaderResources() call is
4335 mandatory: when rebuilding a resource referenced from \a srb, for example
4336 changing the size of a QRhiBuffer followed by a QRhiBuffer::build(), this
4337 is the place where associated native objects (such as descriptor sets in
4338 case of Vulkan) are updated to refer to the current native resources that
4339 back the QRhiBuffer, QRhiTexture, QRhiSampler objects referenced from \a
4340 srb. In this case setShaderResources() must be called even if \a srb is
4341 the same as in the last call.
4342
4343 \a dynamicOffsets allows specifying buffer offsets for uniform buffers that
4344 were associated with \a srb via
4345 QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(). This is
4346 different from providing the offset in the \a srb itself: dynamic offsets
4347 do not require building a new QRhiShaderResourceBindings for every
4348 different offset, can avoid writing the underlying descriptors (with
4349 backends where applicable), and so they may be more efficient. Each element
4350 of \a dynamicOffsets is a \c binding - \c offset pair.
4351 \a dynamicOffsetCount specifies the number of elements in \a dynamicOffsets.
4352
4353 \note All offsets in \a dynamicOffsets must be byte aligned to the value
4354 returned from QRhi::ubufAlignment().
4355
4356 \note QRhi will optimize out unnecessary invocations within a pass (taking
4357 the conditions described above into account), so therefore overoptimizing
4358 to avoid calls to this function is not necessary on the applications' side.
4359
4360 \note This function can only be called inside a render or compute pass,
4361 meaning between a beginPass() and endPass(), or beginComputePass() and
4362 endComputePass().
4363 */
4364void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb,
4365 int dynamicOffsetCount,
4366 const DynamicOffset *dynamicOffsets)
4367{
4368 m_rhi->setShaderResources(this, srb, dynamicOffsetCount, dynamicOffsets);
4369}
4370
4371/*!
4372 Records vertex input bindings.
4373
4374 The index buffer used by subsequent drawIndexed() commands is specified by
4375 \a indexBuf, \a indexOffset, and \a indexFormat. \a indexBuf can be set to
4376 null when indexed drawing is not needed.
4377
4378 Vertex buffer bindings are batched. \a startBinding specifies the first
4379 binding number. The recorded command then binds each buffer from \a
4380 bindings to the binding point \c{startBinding + i} where \c i is the index
4381 in \a bindings. Each element in \a bindings specifies a QRhiBuffer and an
4382 offset.
4383
4384 Superfluous vertex input and index changes in the same pass are ignored
4385 automatically with most backends and therefore applications do not need to
4386 overoptimize to avoid calls to this function.
4387
4388 \note This function can only be called inside a render pass, meaning
4389 between a beginPass() and endPass() call.
4390
4391 As a simple example, take a vertex shader with two inputs:
4392
4393 \badcode
4394 layout(location = 0) in vec4 position;
4395 layout(location = 1) in vec3 color;
4396 \endcode
4397
4398 and assume we have the data available in interleaved format, using only 2
4399 floats for position (so 5 floats per vertex: x, y, r, g, b). A QRhiGraphicsPipeline for
4400 this shader can then be created using the input layout:
4401
4402 \badcode
4403 QRhiVertexInputLayout inputLayout;
4404 inputLayout.setBindings({
4405 { 5 * sizeof(float) }
4406 });
4407 inputLayout.setAttributes({
4408 { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
4409 { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
4410 });
4411 \endcode
4412
4413 Here there is one buffer binding (binding number 0), with two inputs
4414 referencing it. When recording the pass, once the pipeline is set, the
4415 vertex bindings can be specified simply like the following (using C++11
4416 initializer syntax), assuming vbuf is the QRhiBuffer with all the
4417 interleaved position+color data:
4418
4419 \badcode
4420 const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
4421 cb->setVertexInput(0, 1, &vbufBinding);
4422 \endcode
4423 */
4424void QRhiCommandBuffer::setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
4425 QRhiBuffer *indexBuf, quint32 indexOffset,
4426 IndexFormat indexFormat)
4427{
4428 m_rhi->setVertexInput(this, startBinding, bindingCount, bindings, indexBuf, indexOffset, indexFormat);
4429}
4430
4431/*!
4432 Records setting the active viewport rectangle specified in \a viewport.
4433
4434 With backends where the underlying graphics API has scissoring always
4435 enabled, this function also sets the scissor to match the viewport whenever
4436 the active QRhiGraphicsPipeline does not have
4437 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set.
4438
4439 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
4440 bottom-left.
4441
4442 \note This function can only be called inside a render pass, meaning
4443 between a beginPass() and endPass() call.
4444 */
4445void QRhiCommandBuffer::setViewport(const QRhiViewport &viewport)
4446{
4447 m_rhi->setViewport(this, viewport);
4448}
4449
4450/*!
4451 Records setting the active scissor rectangle specified in \a scissor.
4452
4453 This can only be called when the bound pipeline has
4454 \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set. When the flag is
4455 set on the active pipeline, this function must be called because scissor
4456 testing will get enabled and so a scissor rectangle must be provided.
4457
4458 \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
4459 bottom-left.
4460
4461 \note This function can only be called inside a render pass, meaning
4462 between a beginPass() and endPass() call.
4463 */
4464void QRhiCommandBuffer::setScissor(const QRhiScissor &scissor)
4465{
4466 m_rhi->setScissor(this, scissor);
4467}
4468
4469/*!
4470 Records setting the active blend constants to \a c.
4471
4472 This can only be called when the bound pipeline has
4473 QRhiGraphicsPipeline::UsesBlendConstants set.
4474
4475 \note This function can only be called inside a render pass, meaning
4476 between a beginPass() and endPass() call.
4477 */
4478void QRhiCommandBuffer::setBlendConstants(const QColor &c)
4479{
4480 m_rhi->setBlendConstants(this, c);
4481}
4482
4483/*!
4484 Records setting the active stencil reference value to \a refValue.
4485
4486 This can only be called when the bound pipeline has
4487 QRhiGraphicsPipeline::UsesStencilRef set.
4488
4489 \note This function can only be called inside a render pass, meaning between
4490 a beginPass() and endPass() call.
4491 */
4492void QRhiCommandBuffer::setStencilRef(quint32 refValue)
4493{
4494 m_rhi->setStencilRef(this, refValue);
4495}
4496
4497/*!
4498 Records a non-indexed draw.
4499
4500 The number of vertices is specified in \a vertexCount. For instanced
4501 drawing set \a instanceCount to a value other than 1. \a firstVertex is the
4502 index of the first vertex to draw. When drawing multiple instances, the
4503 first instance ID is specified by \a firstInstance.
4504
4505 \note \a firstInstance may not be supported, and is ignored when the
4506 QRhi::BaseInstance feature is reported as not supported. The first ID is
4507 always 0 in that case.
4508
4509 \note This function can only be called inside a render pass, meaning
4510 between a beginPass() and endPass() call.
4511 */
4512void QRhiCommandBuffer::draw(quint32 vertexCount,
4513 quint32 instanceCount,
4514 quint32 firstVertex,
4515 quint32 firstInstance)
4516{
4517 m_rhi->draw(this, vertexCount, instanceCount, firstVertex, firstInstance);
4518}
4519
4520/*!
4521 Records an indexed draw.
4522
4523 The number of vertices is specified in \a indexCount. \a firstIndex is the
4524 base index. The effective offset in the index buffer is given by
4525 \c{indexOffset + firstIndex * n} where \c n is 2 or 4 depending on the
4526 index element type. \c indexOffset is specified in setVertexInput().
4527
4528 \note The effective offset in the index buffer must be 4 byte aligned with
4529 some backends (for example, Metal). With these backends the
4530 \l{QRhi::NonFourAlignedEffectiveIndexBufferOffset}{NonFourAlignedEffectiveIndexBufferOffset}
4531 feature will be reported as not-supported.
4532
4533 For instanced drawing set \a instanceCount to a value other than 1. When
4534 drawing multiple instances, the first instance ID is specified by \a
4535 firstInstance.
4536
4537 \note \a firstInstance may not be supported, and is ignored when the
4538 QRhi::BaseInstance feature is reported as not supported. The first ID is
4539 always 0 in that case.
4540
4541 \a vertexOffset (also called \c{base vertex}) is a signed value that is
4542 added to the element index before indexing into the vertex buffer. Support
4543 for this is not always available, and the value is ignored when the feature
4544 QRhi::BaseVertex is reported as unsupported.
4545
4546 \note This function can only be called inside a render pass, meaning
4547 between a beginPass() and endPass() call.
4548 */
4549void QRhiCommandBuffer::drawIndexed(quint32 indexCount,
4550 quint32 instanceCount,
4551 quint32 firstIndex,
4552 qint32 vertexOffset,
4553 quint32 firstInstance)
4554{
4555 m_rhi->drawIndexed(this, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
4556}
4557
4558/*!
4559 Records a named debug group on the command buffer. This is shown in
4560 graphics debugging tools such as \l{https://renderdoc.org/}{RenderDoc} and
4561 \l{https://developer.apple.com/xcode/}{XCode}. The end of the grouping is
4562 indicated by debugMarkEnd().
4563
4564 \note Ignored when QRhi::DebugMarkers are not supported or
4565 QRhi::EnableDebugMarkers is not set.
4566
4567 \note Can be called anywhere within the frame, both inside and outside of passes.
4568 */
4569void QRhiCommandBuffer::debugMarkBegin(const QByteArray &name)
4570{
4571 m_rhi->debugMarkBegin(this, name);
4572}
4573
4574/*!
4575 Records the end of a debug group.
4576
4577 \note Ignored when QRhi::DebugMarkers are not supported or
4578 QRhi::EnableDebugMarkers is not set.
4579
4580 \note Can be called anywhere within the frame, both inside and outside of passes.
4581 */
4582void QRhiCommandBuffer::debugMarkEnd()
4583{
4584 m_rhi->debugMarkEnd(this);
4585}
4586
4587/*!
4588 Inserts a debug message \a msg into the command stream.
4589
4590 \note Ignored when QRhi::DebugMarkers are not supported or
4591 QRhi::EnableDebugMarkers is not set.
4592
4593 \note With some backends debugMarkMsg() is only supported inside a pass and
4594 is ignored when called outside a pass. With others it is recorded anywhere
4595 within the frame.
4596 */
4597void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)
4598{
4599 m_rhi->debugMarkMsg(this, msg);
4600}
4601
4602/*!
4603 Records starting a new compute pass.
4604
4605 \a resourceUpdates, when not null, specifies a resource update batch that
4606 is to be committed and then released.
4607
4608 \note Do not assume that any state or resource bindings persist between
4609 passes.
4610
4611 \note A compute pass can record setComputePipeline(), setShaderResources(),
4612 and dispatch() calls, not graphics ones. General functionality, such as,
4613 debug markers and beginExternal() is available both in render and compute
4614 passes.
4615
4616 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
4617 is reported as supported.
4618 */
4619void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates)
4620{
4621 m_rhi->beginComputePass(this, resourceUpdates);
4622}
4623
4624/*!
4625 Records ending the current compute pass.
4626
4627 \a resourceUpdates, when not null, specifies a resource update batch that
4628 is to be committed and then released.
4629 */
4630void QRhiCommandBuffer::endComputePass(QRhiResourceUpdateBatch *resourceUpdates)
4631{
4632 m_rhi->endComputePass(this, resourceUpdates);
4633}
4634
4635/*!
4636 Records setting a new compute pipeline \a ps.
4637
4638 \note This function must be called before recording setShaderResources() or
4639 dispatch() commands on the command buffer.
4640
4641 \note QRhi will optimize out unnecessary invocations within a pass, so
4642 therefore overoptimizing to avoid calls to this function is not necessary
4643 on the applications' side.
4644
4645 \note This function can only be called inside a compute pass, meaning
4646 between a beginComputePass() and endComputePass() call.
4647 */
4648void QRhiCommandBuffer::setComputePipeline(QRhiComputePipeline *ps)
4649{
4650 m_rhi->setComputePipeline(this, ps);
4651}
4652
4653/*!
4654 Records dispatching compute work items, with \a x, \a y, and \a z
4655 specifying the number of local workgroups in the corresponding dimension.
4656
4657 \note This function can only be called inside a compute pass, meaning
4658 between a beginComputePass() and endComputePass() call.
4659 */
4660void QRhiCommandBuffer::dispatch(int x, int y, int z)
4661{
4662 m_rhi->dispatch(this, x, y, z);
4663}
4664
4665/*!
4666 \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
4667 QRhiVulkanCommandBufferNativeHandles. The returned value is null when
4668 exposing the underlying native resources is not supported by, or not
4669 applicable to, the backend.
4670
4671 \sa QRhiVulkanCommandBufferNativeHandles,
4672 QRhiMetalCommandBufferNativeHandles, beginExternal(), endExternal()
4673 */
4674const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
4675{
4676 return m_rhi->nativeHandles(this);
4677}
4678
4679/*!
4680 To be called when the application before the application is about to
4681 enqueue commands to the current pass' command buffer by calling graphics
4682 API functions directly.
4683
4684 With Vulkan or Metal one can query the native command buffer or encoder
4685 objects via nativeHandles() and enqueue commands to them. With OpenGL or
4686 Direct3D 11 the (device) context can be retrieved from
4687 QRhi::nativeHandles(). However, this must never be done without ensuring
4688 the QRhiCommandBuffer's state stays up-to-date. Hence the requirement for
4689 wrapping any externally added command recording between beginExternal() and
4690 endExternal(). Conceptually this is the same as QPainter's
4691 \l{QPainter::beginNativePainting()}{beginNativePainting()} and
4692 \l{QPainter::endNativePainting()}{endNativePainting()} functions.
4693
4694 For OpenGL in particular, this function has an additional task: it makes
4695 sure the context is made current on the current thread.
4696
4697 \note Once beginExternal() is called, no other render pass specific
4698 functions (\c set* or \c draw*) must be called on the
4699 QRhiCommandBuffer until endExternal().
4700
4701 \sa endExternal(), nativeHandles()
4702 */
4703void QRhiCommandBuffer::beginExternal()
4704{
4705 m_rhi->beginExternal(this);
4706}
4707
4708/*!
4709 To be called once the externally added commands are recorded to the command
4710 buffer or context.
4711
4712 \note All QRhiCommandBuffer state must be assumed as invalid after calling
4713 this function. Pipelines, vertex and index buffers, and other state must be
4714 set again if more draw calls are recorded after the external commands.
4715
4716 \sa beginExternal(), nativeHandles()
4717 */
4718void QRhiCommandBuffer::endExternal()
4719{
4720 m_rhi->endExternal(this);
4721}
4722
4723/*!
4724 \return the value (typically an offset) \a v aligned to the uniform buffer
4725 alignment given by by ubufAlignment().
4726 */
4727int QRhi::ubufAligned(int v) const
4728{
4729 const int byteAlign = ubufAlignment();
4730 return (v + byteAlign - 1) & ~(byteAlign - 1);
4731}
4732
4733/*!
4734 \return the number of mip levels for a given \a size.
4735 */
4736int QRhi::mipLevelsForSize(const QSize &size) const
4737{
4738 return qFloor(std::log2(qMax(size.width(), size.height()))) + 1;
4739}
4740
4741/*!
4742 \return the texture image size for a given \a mipLevel, calculated based on
4743 the level 0 size given in \a baseLevelSize.
4744 */
4745QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize) const
4746{
4747 const int w = qMax(1, baseLevelSize.width() >> mipLevel);
4748 const int h = qMax(1, baseLevelSize.height() >> mipLevel);
4749 return QSize(w, h);
4750}
4751
4752/*!
4753 \return \c true if the underlying graphics API has the Y axis pointing up
4754 in framebuffers and images.
4755
4756 In practice this is \c true for OpenGL only.
4757 */
4758bool QRhi::isYUpInFramebuffer() const
4759{
4760 return d->isYUpInFramebuffer();
4761}
4762
4763/*!
4764 \return \c true if the underlying graphics API has the Y axis pointing up
4765 in its normalized device coordinate system.
4766
4767 In practice this is \c false for Vulkan only.
4768
4769 \note clipSpaceCorrMatrix() includes the corresponding adjustment (to make
4770 Y point up) in its returned matrix.
4771 */
4772bool QRhi::isYUpInNDC() const
4773{
4774 return d->isYUpInNDC();
4775}
4776
4777/*!
4778 \return \c true if the underlying graphics API uses depth 0 - 1 in clip
4779 space.
4780
4781 In practice this is \c false for OpenGL only.
4782
4783 \note clipSpaceCorrMatrix() includes the corresponding adjustment in its
4784 returned matrix.
4785 */
4786bool QRhi::isClipDepthZeroToOne() const
4787{
4788 return d->isClipDepthZeroToOne();
4789}
4790
4791/*!
4792 \return a matrix that can be used to allow applications keep using
4793 OpenGL-targeted vertex data and perspective projection matrices (such as,
4794 the ones generated by QMatrix4x4::perspective()), regardless of the
4795 backend. Once \c{this_matrix * mvp} is used instead of just \c mvp, vertex
4796 data with Y up and viewports with depth range 0 - 1 can be used without
4797 considering what backend and so graphics API is going to be used at run
4798 time.
4799
4800 See
4801 \l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this
4802 page} for a discussion of the topic from Vulkan perspective.
4803 */
4804QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
4805{
4806 return d->clipSpaceCorrMatrix();
4807}
4808
4809/*!
4810 \return \c true if the specified texture \a format modified by \a flags is
4811 supported.
4812
4813 The query is supported both for uncompressed and compressed formats.
4814 */
4815bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
4816{
4817 return d->isTextureFormatSupported(format, flags);
4818}
4819
4820/*!
4821 \return \c true if the specified \a feature is supported
4822 */
4823bool QRhi::isFeatureSupported(QRhi::Feature feature) const
4824{
4825 return d->isFeatureSupported(feature);
4826}
4827
4828/*!
4829 \return the value for the specified resource \a limit.
4830
4831 The values are expected to be queried by the backends upon initialization,
4832 meaning calling this function is a light operation.
4833 */
4834int QRhi::resourceLimit(ResourceLimit limit) const
4835{
4836 return d->resourceLimit(limit);
4837}
4838
4839/*!
4840 \return a pointer to the backend-specific collection of native objects
4841 for the device, context, and similar concepts used by the backend.
4842
4843 Cast to QRhiVulkanNativeHandles, QRhiD3D11NativeHandles,
4844 QRhiGles2NativeHandles, QRhiMetalNativeHandles as appropriate.
4845
4846 \note No ownership is transferred, neither for the returned pointer nor for
4847 any native objects.
4848 */
4849const QRhiNativeHandles *QRhi::nativeHandles()
4850{
4851 return d->nativeHandles();
4852}
4853
4854/*!
4855 With OpenGL this makes the OpenGL context current on the current thread.
4856 The function has no effect with other backends.
4857
4858 Calling this function is relevant typically in Qt framework code, when one
4859 has to ensure external OpenGL code provided by the application can still
4860 run like it did before with direct usage of OpenGL, as long as the QRhi is
4861 using the OpenGL backend.
4862 */
4863void QRhi::makeThreadLocalNativeContextCurrent()
4864{
4865 d->makeThreadLocalNativeContextCurrent();
4866}
4867
4868/*!
4869 \return the associated QRhiProfiler instance.
4870
4871 An instance is always available for each QRhi, but it is not very useful
4872 without EnableProfiling because no data is collected without setting the
4873 flag upon creation.
4874 */
4875QRhiProfiler *QRhi::profiler()
4876{
4877 return &d->profiler;
4878}
4879
4880/*!
4881 \return a new graphics pipeline resource.
4882
4883 \sa QRhiResource::release()
4884 */
4885QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
4886{
4887 return d->createGraphicsPipeline();
4888}
4889
4890/*!
4891 \return a new compute pipeline resource.
4892
4893 \note Compute is only available when the \l{QRhi::Compute}{Compute} feature
4894 is reported as supported.
4895
4896 \sa QRhiResource::release()
4897 */
4898QRhiComputePipeline *QRhi::newComputePipeline()
4899{
4900 return d->createComputePipeline();
4901}
4902
4903/*!
4904 \return a new shader resource binding collection resource.
4905
4906 \sa QRhiResource::release()
4907 */
4908QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
4909{
4910 return d->createShaderResourceBindings();
4911}
4912
4913/*!
4914 \return a new buffer with the specified \a type, \a usage, and \a size.
4915
4916 \note Some \a usage and \a type combinations may not be supported by all
4917 backends. See \l{QRhiBuffer::UsageFlag}{UsageFlags} and
4918 \l{QRhi::NonDynamicUniformBuffers}{the feature flags}.
4919
4920 \sa QRhiResource::release()
4921 */
4922QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type,
4923 QRhiBuffer::UsageFlags usage,
4924 int size)
4925{
4926 return d->createBuffer(type, usage, size);
4927}
4928
4929/*!
4930 \return a new renderbuffer with the specified \a type, \a pixelSize, \a
4931 sampleCount, and \a flags.
4932
4933 \sa QRhiResource::release()
4934 */
4935QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type,
4936 const QSize &pixelSize,
4937 int sampleCount,
4938 QRhiRenderBuffer::Flags flags)
4939{
4940 return d->createRenderBuffer(type, pixelSize, sampleCount, flags);
4941}
4942
4943/*!
4944 \return a new texture with the specified \a format, \a pixelSize, \a
4945 sampleCount, and \a flags.
4946
4947 \note \a format specifies the requested internal and external format,
4948 meaning the data to be uploaded to the texture will need to be in a
4949 compatible format, while the native texture may (but is not guaranteed to,
4950 in case of OpenGL at least) use this format internally.
4951
4952 \sa QRhiResource::release()
4953 */
4954QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
4955 const QSize &pixelSize,
4956 int sampleCount,
4957 QRhiTexture::Flags flags)
4958{
4959 return d->createTexture(format, pixelSize, sampleCount, flags);
4960}
4961
4962/*!
4963 \return a new sampler with the specified magnification filter \a magFilter,
4964 minification filter \a minFilter, mipmapping mode \a mipmapMpde, and S/T
4965 addressing modes \a u and \a v.
4966
4967 \sa QRhiResource::release()
4968 */
4969QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
4970 QRhiSampler::Filter mipmapMode,
4971 QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v)
4972{
4973 return d->createSampler(magFilter, minFilter, mipmapMode, u, v);
4974}
4975
4976/*!
4977 \return a new texture render target with color and depth/stencil
4978 attachments given in \a desc, and with the specified \a flags.
4979
4980 \sa QRhiResource::release()
4981 */
4982
4983QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
4984 QRhiTextureRenderTarget::Flags flags)
4985{
4986 return d->createTextureRenderTarget(desc, flags);
4987}
4988
4989/*!
4990 \return a new swapchain.
4991
4992 \sa QRhiResource::release(), QRhiSwapChain::buildOrResize()
4993 */
4994QRhiSwapChain *QRhi::newSwapChain()
4995{
4996 return d->createSwapChain();
4997}
4998
4999