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