Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qrhi_p.h
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QRHI_P_H
6#define QRHI_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <rhi/qrhi.h>
20#include <QBitArray>
21#include <QAtomicInt>
22#include <QElapsedTimer>
23#include <QLoggingCategory>
24#include <QtCore/qhash.h>
25#include <QtCore/qset.h>
26#include <QtCore/qvarlengtharray.h>
27#include <algorithm>
28#include <utility>
29
30QT_BEGIN_NAMESPACE
31
32#define QRHI_RES(t, x) static_cast<t *>(x)
33#define QRHI_RES_RHI(t) t *rhiD = static_cast<t *>(m_rhi)
34
35Q_DECLARE_LOGGING_CATEGORY(QRHI_LOG_INFO)
36Q_DECLARE_LOGGING_CATEGORY(QRHI_LOG_RUB)
37
38class QRhiImplementation
39{
40public:
41 virtual ~QRhiImplementation();
42
43 virtual bool create(QRhi::Flags flags) = 0;
44 virtual void destroy() = 0;
45 virtual QRhi::AdapterList enumerateAdaptersBeforeCreate(QRhiNativeHandles *nativeHandles) const;
46
47 virtual QRhiGraphicsPipeline *createGraphicsPipeline() = 0;
48 virtual QRhiComputePipeline *createComputePipeline() = 0;
49 virtual QRhiShaderResourceBindings *createShaderResourceBindings() = 0;
50 virtual QRhiBuffer *createBuffer(QRhiBuffer::Type type,
51 QRhiBuffer::UsageFlags usage,
52 quint32 size) = 0;
53 virtual QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
54 const QSize &pixelSize,
55 int sampleCount,
56 QRhiRenderBuffer::Flags flags,
57 QRhiTexture::Format backingFormatHint) = 0;
58 virtual QRhiTexture *createTexture(QRhiTexture::Format format,
59 const QSize &pixelSize,
60 int depth,
61 int arraySize,
62 int sampleCount,
63 QRhiTexture::Flags flags) = 0;
64 virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
65 QRhiSampler::Filter minFilter,
66 QRhiSampler::Filter mipmapMode,
67 QRhiSampler:: AddressMode u,
68 QRhiSampler::AddressMode v,
69 QRhiSampler::AddressMode w) = 0;
70
71 virtual QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
72 QRhiTextureRenderTarget::Flags flags) = 0;
73
74 virtual QRhiShadingRateMap *createShadingRateMap() = 0;
75
76 virtual QRhiIndirectCommandBuffer *createIndirectCommandBuffer(QRhiIndirectCommandBuffer::Type type,
77 quint32 maxCommandCount);
78 virtual void buildIndirect(QRhiCommandBuffer *cb, QRhiIndirectCommandBuffer *icb,
79 const QRhiIndirectCommandBufferBuildInfo &info);
80 virtual void executeIndirect(QRhiCommandBuffer *cb, QRhiIndirectCommandBuffer *icb,
81 quint32 firstCommand, quint32 commandCount);
82 virtual void commitIndirectCommandBuffer(QRhiResourceUpdateBatch *u,
83 QRhiIndirectCommandBuffer *icb);
84
85 virtual QRhiSwapChain *createSwapChain() = 0;
86 virtual QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) = 0;
87 virtual QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) = 0;
88 virtual QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) = 0;
89 virtual QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) = 0;
90 virtual QRhi::FrameOpResult finish() = 0;
91
92 virtual void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
93
94 virtual void beginPass(QRhiCommandBuffer *cb,
95 QRhiRenderTarget *rt,
96 const QColor &colorClearValue,
97 const QRhiDepthStencilClearValue &depthStencilClearValue,
98 QRhiResourceUpdateBatch *resourceUpdates,
99 QRhiCommandBuffer::BeginPassFlags flags) = 0;
100 virtual void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
101
102 virtual void setGraphicsPipeline(QRhiCommandBuffer *cb,
103 QRhiGraphicsPipeline *ps) = 0;
104
105 virtual void setShaderResources(QRhiCommandBuffer *cb,
106 QRhiShaderResourceBindings *srb,
107 int dynamicOffsetCount,
108 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) = 0;
109
110 virtual void setVertexInput(QRhiCommandBuffer *cb,
111 int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
112 QRhiBuffer *indexBuf, quint32 indexOffset,
113 QRhiCommandBuffer::IndexFormat indexFormat) = 0;
114
115 virtual void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) = 0;
116 virtual void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) = 0;
117 virtual void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) = 0;
118 virtual void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) = 0;
119 virtual void setPushConstants(QRhiCommandBuffer *cb, quint32 offset, quint32 size, const void *data) = 0;
120 virtual void setShadingRate(QRhiCommandBuffer *cb, const QSize &coarsePixelSize) = 0;
121
122 virtual void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
123 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) = 0;
124 virtual void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
125 quint32 instanceCount, quint32 firstIndex,
126 qint32 vertexOffset, quint32 firstInstance) = 0;
127 virtual void drawIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer,
128 quint32 offset, quint32 drawCount, quint32 stride) = 0;
129 virtual void drawIndexedIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer,
130 quint32 offset, quint32 drawCount, quint32 stride) = 0;
131 virtual void drawIndirectCount(QRhiCommandBuffer *cb,
132 QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset,
133 QRhiBuffer *countBuffer, quint32 countBufferOffset,
134 quint32 maxDrawCount, quint32 stride) = 0;
135 virtual void drawIndexedIndirectCount(QRhiCommandBuffer *cb,
136 QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset,
137 QRhiBuffer *countBuffer, quint32 countBufferOffset,
138 quint32 maxDrawCount, quint32 stride) = 0;
139
140 virtual void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) = 0;
141 virtual void debugMarkEnd(QRhiCommandBuffer *cb) = 0;
142 virtual void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) = 0;
143
144 virtual void beginComputePass(QRhiCommandBuffer *cb,
145 QRhiResourceUpdateBatch *resourceUpdates,
146 QRhiCommandBuffer::BeginPassFlags flags) = 0;
147 virtual void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
148 virtual void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) = 0;
149 virtual void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) = 0;
150 virtual void dispatchIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer,
151 quint32 offset) = 0;
152
153 virtual const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) = 0;
154 virtual void beginExternal(QRhiCommandBuffer *cb) = 0;
155 virtual void endExternal(QRhiCommandBuffer *cb) = 0;
156 virtual double lastCompletedGpuTime(QRhiCommandBuffer *cb) = 0;
157
158 virtual QList<int> supportedSampleCounts() const = 0;
159 virtual int ubufAlignment() const = 0;
160 virtual QList<QSize> supportedShadingRates(int sampleCount) const = 0;
161 virtual bool isYUpInFramebuffer() const = 0;
162 virtual bool isYUpInNDC() const = 0;
163 virtual bool isClipDepthZeroToOne() const = 0;
164 virtual QMatrix4x4 clipSpaceCorrMatrix() const = 0;
165 virtual bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const = 0;
166 virtual bool isFeatureSupported(QRhi::Feature feature) const = 0;
167 virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0;
168 virtual const QRhiNativeHandles *nativeHandles() = 0;
169 virtual QRhiDriverInfo driverInfo() const = 0;
170 virtual QRhiStats statistics() = 0;
171 virtual bool makeThreadLocalNativeContextCurrent() = 0;
172 virtual void setQueueSubmitParams(QRhiNativeHandles *params) = 0;
173 virtual void releaseCachedResources() = 0;
174 virtual bool isDeviceLost() const = 0;
175
176 virtual QByteArray pipelineCacheData() = 0;
177 virtual void setPipelineCacheData(const QByteArray &data) = 0;
178
179 static QRhiImplementation *newInstance(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *importDevice);
180 void prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags, QRhiAdapter *adapter);
181
182 bool isCompressedFormat(QRhiTexture::Format format) const;
183 bool compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
184 quint32 *bpl, quint32 *byteSize,
185 QSize *blockDim) const;
186 bool textureFormatInfo(QRhiTexture::Format format, const QSize &size,
187 quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const;
188 bool isStencilSupportingFormat(QRhiTexture::Format format) const;
189
190 void registerResource(QRhiResource *res, bool ownsNativeResources = true)
191 {
192 // The ownsNativeResources is relevant for the (graphics resource) leak
193 // check in ~QRhiImplementation; when false, the registration's sole
194 // purpose is to automatically null out the resource's m_rhi pointer in
195 // case the rhi goes away first. (which should not happen in
196 // well-written applications but we try to be graceful)
197 resources.insert(res, ownsNativeResources);
198 }
199
200 void unregisterResource(QRhiResource *res)
201 {
202 resources.remove(res);
203 }
204
205 void addDeleteLater(QRhiResource *res)
206 {
207 if (inFrame)
208 pendingDeleteResources.insert(res);
209 else
210 delete res;
211 }
212
213 void addCleanupCallback(const QRhi::CleanupCallback &callback)
214 {
215 cleanupCallbacks.append(callback);
216 }
217
218 void addCleanupCallback(const void *key, const QRhi::CleanupCallback &callback)
219 {
220 keyedCleanupCallbacks[key] = callback;
221 }
222
223 void removeCleanupCallback(const void *key)
224 {
225 keyedCleanupCallbacks.remove(key);
226 }
227
228 bool sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps);
229 bool sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb);
230 bool sanityCheckResourceOwnership(QRhiResource *maybeResource);
231 void updateLayoutDesc(QRhiShaderResourceBindings *srb);
232
233 quint32 pipelineCacheRhiId() const
234 {
235 const quint32 ver = (QT_VERSION_MAJOR << 16) | (QT_VERSION_MINOR << 8) | (QT_VERSION_PATCH);
236 return (quint32(implType) << 24) | ver;
237 }
238
239 void pipelineCreationStart()
240 {
241 pipelineCreationTimer.start();
242 }
243
244 void pipelineCreationEnd()
245 {
246 accumulatedPipelineCreationTime += pipelineCreationTimer.elapsed();
247 }
248
249 qint64 totalPipelineCreationTime() const
250 {
251 return accumulatedPipelineCreationTime;
252 }
253
254 QRhiVertexInputAttribute::Format shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const;
255 quint32 byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const;
256
257 static const QRhiShaderResourceBinding::Data *shaderResourceBindingData(const QRhiShaderResourceBinding &binding)
258 {
259 return &binding.d;
260 }
261
262 static QRhiShaderResourceBinding::Data *shaderResourceBindingData(QRhiShaderResourceBinding &binding)
263 {
264 return &binding.d;
265 }
266
267 static bool sortedBindingLessThan(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
268 {
269 return a.d.binding < b.d.binding;
270 }
271
272 int effectiveSampleCount(int sampleCount) const;
273 QSize clampedSubResourceUploadSize(QSize size, QPoint dstPos, int level, QSize textureSizeAtLevelZero, bool warn = true);
274 QSize clampedSubResourceUploadSizeForSourceData(QSize size, quint32 bpl, quint32 bytesPerPixel,
275 qsizetype dataSize, bool warn = true);
276
277 void runCleanup();
278
279 QRhi *q;
280
281 static const int MAX_SHADER_CACHE_ENTRIES = 128;
282 static const quint32 MAX_BINARY_CACHE_BYTES = 16 * 1024 * 1024;
283
284 bool debugMarkers = false;
285 bool timestamps = false;
286 int currentFrameSlot = 0; // for vk, mtl, and similar. unused by gl and d3d11.
287 bool inFrame = false;
288 QRhiCommandBuffer *currentOffscreenCb = nullptr;
289 QRhiAdapter *requestedRhiAdapter = nullptr;
290 QHash<QRhiResource *, bool> resources;
291
292private:
293 QRhi::Implementation implType;
294 QThread *implThread;
295 QVarLengthArray<QRhiResourceUpdateBatch *, 4> resUpdPool;
296 quint64 resUpdPoolMap = 0;
297 int lastResUpdIdx = -1;
298 QSet<QRhiResource *> pendingDeleteResources;
299 QVarLengthArray<QRhi::CleanupCallback, 4> cleanupCallbacks;
300 QHash<const void *, QRhi::CleanupCallback> keyedCleanupCallbacks;
301 QElapsedTimer pipelineCreationTimer;
302 qint64 accumulatedPipelineCreationTime = 0;
303
304 friend class QRhi;
305 friend class QRhiResourceUpdateBatchPrivate;
306 friend class QRhiBufferData;
307};
308
309inline quint32 qrhiBinaryCacheEntryByteSize(const QByteArray &data)
310{
311 return quint32(data.size());
312}
313
314template <typename Key, typename Value,
315 quint32 MaxBytes = QRhiImplementation::MAX_BINARY_CACHE_BYTES>
317{
318 explicit QRhiBinaryCache(const char *name) : name(name) { }
319
322 const char *name;
323
324 void clear()
325 {
326 data.clear();
327 dataByteSize = 0;
328 }
329
330 void insertWithCapacityLimit(const Key &key, const Value &value)
331 {
332 const quint32 entrySize = qrhiBinaryCacheEntryByteSize(value);
333
334 // Replacing an entry must not make the running total drift. This does
335 // happen in practice: trySaveToPipelineCache() in the OpenGL backend
336 // replaces the existing entry when forced to.
337 auto it = data.find(key);
338 if (it != data.end()) {
339 dataByteSize -= qrhiBinaryCacheEntryByteSize(*it);
340 *it = value;
341 dataByteSize += entrySize;
342 return;
343 }
344
345 if (dataByteSize + entrySize > MaxBytes) {
346 // Use the simplest strategy: too much cached data -> drop it all.
347 // An entry larger than the entire budget is still inserted, so the
348 // cache can hold up to the budget plus one entry.
349 qCDebug(QRHI_LOG_INFO, "%s would exceed %u bytes, dropping all %d entries (%u bytes)",
350 name, MaxBytes, int(data.count()), dataByteSize);
351 clear();
352 }
353
354 data.insert(key, value);
355 dataByteSize += entrySize;
356 }
357};
358
360{
361 void (*frameEnd)(QRhiImplementation *d, QRhiSwapChain *swapChain, QRhiCommandBuffer *cb) = nullptr;
362 void (*rhiAboutToBeDestroyed)(QRhiImplementation *d) = nullptr;
363};
364
365Q_GUI_EXPORT extern QRhiDebugHooks qrhiDebugHooks;
366
368{
369public:
370 QRhiBufferBackedIndirectCommandBuffer(QRhiImplementation *rhi, Type type, quint32 maxCommandCount);
372
373 void destroy() override;
374 bool create() override;
375
376 // no-op if uploadedGeneration matches the current one, so safe to call regularly
377 void enqueueUpload(QRhiResourceUpdateBatch *u);
378
379 void execute(QRhiCommandBuffer *cb, quint32 firstCommand, quint32 commandCount);
380 void build(const QRhiIndirectCommandBufferBuildInfo &info);
381
382 bool valid = false;
383 QRhiBuffer *buffer = nullptr;
385 QRhiIndirectCommandBufferBuildInfo buildInfo;
386};
387
393
394template<QRhiTargetRectBoundMode boundingMode, typename T, size_t N>
395bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T, N> &r,
396 T *x, T *y, T *w, T *h)
397{
398 // x,y are bottom-left in QRhiScissor and QRhiViewport but top-left in
399 // Vulkan/Metal/D3D. Our input is an OpenGL-style scissor rect where both
400 // negative x or y, and partly or completely out of bounds rects are
401 // allowed. The only thing the input here cannot have is a negative width
402 // or height. We must handle all other input gracefully, clamping to a zero
403 // width or height rect in the worst case, and ensuring the resulting rect
404 // is inside the rendertarget's bounds because some APIs' validation/debug
405 // layers are allergic to out of bounds scissor rects.
406
407 const T outputWidth = outputSize.width();
408 const T outputHeight = outputSize.height();
409 const T inputWidth = r[2];
410 const T inputHeight = r[3];
411
412 if (inputWidth < 0 || inputHeight < 0)
413 return false;
414
415 *x = r[0];
416 *y = outputHeight - (r[1] + inputHeight);
417 *w = inputWidth;
418 *h = inputHeight;
419
420 if (boundingMode == Bounded) {
421 const T widthOffset = *x < 0 ? -*x : 0;
422 const T heightOffset = *y < 0 ? -*y : 0;
423 *w = *x < outputWidth ? qMax<T>(0, inputWidth - widthOffset) : 0;
424 *h = *y < outputHeight ? qMax<T>(0, inputHeight - heightOffset) : 0;
425
426 if (outputWidth > 0)
427 *x = qBound<T>(0, *x, outputWidth - 1);
428 if (outputHeight > 0)
429 *y = qBound<T>(0, *y, outputHeight - 1);
430
431 if (*x + *w > outputWidth)
432 *w = qMax<T>(0, outputWidth - *x);
433 if (*y + *h > outputHeight)
434 *h = qMax<T>(0, outputHeight - *y);
435 }
436 return true;
437}
438
440{
442 QRhiBufferDataPrivate() { } // don't value-initialize smallData
443 int ref = 1;
446 static constexpr quint32 SMALL_DATA_SIZE = 1024;
447 char smallData[SMALL_DATA_SIZE];
448};
449
450// no detach-with-contents, no atomic refcount, no shrink
452{
453public:
454 QRhiBufferData() = default;
456 {
457 if (d && !--d->ref)
458 delete d;
459 }
461 : d(other.d)
462 {
463 if (d)
464 d->ref += 1;
465 }
467 {
468 if (d == other.d)
469 return *this;
470 if (other.d)
471 other.d->ref += 1;
472 if (d && !--d->ref)
473 delete d;
474 d = other.d;
475 return *this;
476 }
477 const char *constData() const
478 {
479 return d ? (d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE ? d->smallData : d->largeData.constData()) : nullptr;
480 }
481 quint32 size() const
482 {
483 return d ? d->size : 0;
484 }
486 {
487 return d ? d->largeData.size() : 0;
488 }
489 void assign(const char *s, quint32 size)
490 {
491 if (!d) {
492 d = new QRhiBufferDataPrivate;
493 } else if (d->ref != 1) {
494 if (QRHI_LOG_RUB().isDebugEnabled())
495 qDebug("[rub] QRhiBufferData %p/%p new backing due to no-copy detach, ref was %d", this, d, d->ref);
496 d->ref -= 1;
497 d = new QRhiBufferDataPrivate;
498 }
499 d->size = size;
500 if (size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) {
501 memcpy(d->smallData, s, size);
502 } else {
503 if (QRHI_LOG_RUB().isDebugEnabled() && largeAlloc() < size)
504 qDebug("[rub] QRhiBufferData %p/%p new large data allocation %u -> %u", this, d, largeAlloc(), size);
505 d->largeData.assign(QByteArrayView(s, size)); // keeps capacity
506 }
507 }
508 void assign(QByteArray data)
509 {
510 if (!d) {
511 d = new QRhiBufferDataPrivate;
512 } else if (d->ref != 1) {
513 if (QRHI_LOG_RUB().isDebugEnabled())
514 qDebug("[rub] QRhiBufferData %p/%p new backing due to no-copy detach, ref was %d", this, d, d->ref);
515 d->ref -= 1;
516 d = new QRhiBufferDataPrivate;
517 }
518 d->size = data.size();
519 if (d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) {
520 memcpy(d->smallData, data.constData(), data.size());
521 } else {
522 d->largeData = std::move(data);
523 }
524 }
525private:
526 QRhiBufferDataPrivate *d = nullptr;
527};
528
530
532{
533public:
534 struct BufferOp {
543 QRhiBuffer *buf;
546 quint32 readSize; // also the number of bytes to copy with Copy, or to fill with Clear
548 QRhiBuffer *src;
551
552 static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
553 {
554 BufferOp op = {};
555 changeToDynamicUpdate(&op, buf, offset, size, data);
556 return op;
557 }
558
559 static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
560 {
562 op->buf = buf;
563 op->offset = offset;
564 const int effectiveSize = size ? size : buf->size();
565 op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
566 }
567
568 static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, QByteArray data)
569 {
570 BufferOp op = {};
571 changeToDynamicUpdate(&op, buf, offset, std::move(data));
572 return op;
573 }
574
575 static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
576 {
578 op->buf = buf;
579 op->offset = offset;
580 op->data.assign(std::move(data));
581 }
582
583 static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
584 {
585 BufferOp op = {};
586 changeToStaticUpload(&op, buf, offset, size, data);
587 return op;
588 }
589
590 static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
591 {
593 op->buf = buf;
594 op->offset = offset;
595 const int effectiveSize = size ? size : buf->size();
596 op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
597 }
598
599 static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, QByteArray data)
600 {
601 BufferOp op = {};
602 changeToStaticUpload(&op, buf, offset, std::move(data));
603 return op;
604 }
605
606 static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
607 {
609 op->buf = buf;
610 op->offset = offset;
611 op->data.assign(std::move(data));
612 }
613
614 static BufferOp read(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
615 {
616 BufferOp op = {};
617 op.type = Read;
618 op.buf = buf;
619 op.offset = offset;
620 op.readSize = size;
621 op.result = result;
622 return op;
623 }
624
625 static BufferOp copy(QRhiBuffer *dst, QRhiBuffer *src, quint32 dstOffset,
626 quint32 srcOffset, quint32 size)
627 {
628 BufferOp op = {};
629 op.type = Copy;
630 op.buf = dst;
631 op.offset = dstOffset;
632 op.readSize = size;
633 op.src = src;
634 op.srcOffset = srcOffset;
635 return op;
636 }
637
638 static BufferOp clear(QRhiBuffer *buf, quint32 offset, quint32 size, quint8 value)
639 {
640 BufferOp op = {};
641 op.type = Clear;
642 op.buf = buf;
643 op.offset = offset;
644 op.readSize = size;
645 op.fillValue = value;
646 return op;
647 }
648
649 // For the APIs that clear in units of 32 bits: fillValue repeated in
650 // all four bytes of the word, e.g. 0xAB becomes 0xABABABAB.
652 {
653 return quint32(fillValue) * 0x01010101u;
654 }
655 };
656
657 struct TextureOp {
665 QRhiTexture *dst;
666 // Specifying multiple uploads for a subresource must be supported.
667 // In the backend this can then end up, where applicable, as a
668 // single, batched copy operation with only one set of barriers.
669 // This helps when doing for example glyph cache fills.
670 //
671 // Stored as a flat list sorted by layer, then level, preserving the
672 // submission order within a subresource. (a dense layer x level grid
673 // of containers costs kilobytes per op even when empty, and there
674 // are dozens of ops preallocated in each batch)
681 QRhiTexture *src;
685
686 static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
687 {
688 TextureOp op = {};
689 op.type = Upload;
690 op.dst = tex;
691 for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it)
692 op.subresDesc.append({ it->layer(), it->level(), it->description() });
693 std::stable_sort(op.subresDesc.begin(), op.subresDesc.end(),
694 [](const SubresourceUpload &a, const SubresourceUpload &b) {
695 return a.layer != b.layer ? a.layer < b.layer : a.level < b.level;
696 });
697 return op;
698 }
699
700 static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
701 {
702 TextureOp op = {};
703 op.type = Copy;
704 op.dst = dst;
705 op.src = src;
706 op.desc = desc;
707 return op;
708 }
709
710 static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
711 {
712 TextureOp op = {};
713 op.type = Read;
714 op.rb = rb;
715 op.result = result;
716 return op;
717 }
718
719 static TextureOp genMips(QRhiTexture *tex)
720 {
721 TextureOp op = {};
722 op.type = GenMips;
723 op.dst = tex;
724 return op;
725 }
726 };
727
728 int activeBufferOpCount = 0; // this is the real number of used elements in bufferOps, not bufferOps.count()
729 static const int BUFFER_OPS_STATIC_ALLOC = 64;
731
732 int activeTextureOpCount = 0; // this is the real number of used elements in textureOps, not textureOps.count()
733 static const int TEXTURE_OPS_STATIC_ALLOC = 32;
735
736 QRhiResourceUpdateBatch *q = nullptr;
737 QRhiImplementation *rhi = nullptr;
738 int poolIndex = -1;
739
740 void free();
742 bool hasOptimalCapacity() const;
743 void trimOpLists();
744
745 static QRhiResourceUpdateBatchPrivate *get(QRhiResourceUpdateBatch *b) { return b->d; }
746};
747
748template<typename T>
750{
751 void feed(int binding, T resource) { // binding must be strictly increasing
752 if (curBinding == -1 || binding > curBinding + 1) {
753 finish();
754 curBatch.startBinding = binding;
755 curBatch.resources.clear();
756 curBatch.resources.append(resource);
757 } else {
758 Q_ASSERT(binding == curBinding + 1);
759 curBatch.resources.append(resource);
760 }
761 curBinding = binding;
762 }
763
764 bool finish() {
765 if (!curBatch.resources.isEmpty())
766 batches.append(curBatch);
767 return !batches.isEmpty();
768 }
769
770 void clear() {
771 batches.clear();
772 curBatch.resources.clear();
773 curBinding = -1;
774 }
775
776 struct Batch {
779
780 bool operator==(const Batch &other) const
781 {
782 return startBinding == other.startBinding && resources == other.resources;
783 }
784
785 bool operator!=(const Batch &other) const
786 {
787 return !operator==(other);
788 }
789 };
790
791 // some backends make copies of QRhiBatchedBindings -> implicit sharing and
792 // not having a (possibly wasted) prealloc are beneficial -> use QVector
793 // instead of QVLA
794 QVector<Batch> batches; // sorted by startBinding
795
796 bool operator==(const QRhiBatchedBindings<T> &other) const
797 {
798 return batches == other.batches;
799 }
800
801 bool operator!=(const QRhiBatchedBindings<T> &other) const
802 {
803 return !operator==(other);
804 }
805
806private:
807 Batch curBatch;
808 int curBinding = -1;
809};
810
812{
813public:
814#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
815 using Type = quint64;
816#else
817 using Type = quint32;
818#endif
819 static Type newId();
820};
821
822// The tracked resources of a pass, in the order the pass first used them.
823// Neither QHash nor QVarLengthFlatMap is suitable on its own. Most passes track
824// a handful of resources, which a QHash would allocate for. But a pass can also
825// track thousands, such as the vertex and index buffers of thousands of draw
826// calls, and a flat map keeps its keys sorted, so each insertion shifts half
827// the entries, which is quadratic in the number of resources. So the entries are
828// appended to a QVarLengthArray and searched linearly while there are few, and
829// indexed by a QHash once there are more.
830template <typename Key, typename T, qsizetype Prealloc>
832{
833public:
834 using value_type = std::pair<Key, T>;
836 using const_iterator = const value_type *;
837
838 iterator begin() { return m_entries.begin(); }
839 iterator end() { return m_entries.end(); }
840 const_iterator begin() const { return m_entries.cbegin(); }
841 const_iterator end() const { return m_entries.cend(); }
842 const_iterator cbegin() const { return m_entries.cbegin(); }
843 const_iterator cend() const { return m_entries.cend(); }
844
845 bool isEmpty() const { return m_entries.isEmpty(); }
846 qsizetype size() const { return m_entries.size(); }
847
848 void clear()
849 {
850 m_entries.clear();
851 m_index.clear();
852 }
853
854 const_iterator find(Key key) const
855 {
856 if (m_index.isEmpty()) {
857 return std::find_if(m_entries.cbegin(), m_entries.cend(),
858 [key](const value_type &entry) { return entry.first == key; });
859 }
860 const auto it = m_index.constFind(key);
861 return it == m_index.cend() ? m_entries.cend() : m_entries.cbegin() + it.value();
862 }
863
864 iterator find(Key key)
865 {
866 const const_iterator it = std::as_const(*this).find(key);
867 return m_entries.begin() + (it - m_entries.cbegin());
868 }
869
870 bool contains(Key key) const { return find(key) != cend(); }
871
872 // The key must not be in the map yet.
873 void append(Key key, const T &value)
874 {
875 m_entries.append({ key, value });
876 if (!m_index.isEmpty()) {
877 m_index.insert(key, m_entries.size() - 1);
878 } else if (m_entries.size() > LinearSearchLimit) {
879 m_index.reserve(m_entries.size() * 2);
880 for (qsizetype i = 0; i < m_entries.size(); ++i)
881 m_index.insert(m_entries[i].first, i);
882 }
883 }
884
885private:
886 static constexpr qsizetype LinearSearchLimit = 32;
887 QVarLengthArray<value_type, Prealloc> m_entries;
888 QHash<Key, qsizetype> m_index;
889};
890
892{
893public:
894 bool isEmpty() const;
895 void reset();
896
897 struct UsageState {
900 int stage;
901 };
902
913
923
924 void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
925 const UsageState &state);
926
937
948
949 void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage,
950 const UsageState &state);
951
958
959 const QRhiPassResourceMap<QRhiBuffer *, Buffer, 12> &buffers() const { return m_buffers; }
960
966
967 const QRhiPassResourceMap<QRhiTexture *, Texture, 12> &textures() const { return m_textures; }
968
969 static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages);
970 static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages);
971
972private:
973 QRhiPassResourceMap<QRhiBuffer *, Buffer, 12> m_buffers;
974 QRhiPassResourceMap<QRhiTexture *, Texture, 12> m_textures;
975};
976
979
980template<typename T, int GROW = 1024>
982{
983public:
985 ~QRhiBackendCommandList() { delete[] v; }
986 inline void reset() { p = 0; }
987 inline bool isEmpty() const { return p == 0; }
988 inline T &get() {
989 if (p == a) {
990 a += GROW;
991 T *nv = new T[a];
992 if (v) {
993 memcpy(nv, v, p * sizeof(T));
994 delete[] v;
995 }
996 v = nv;
997 }
998 return v[p++];
999 }
1000 inline void unget() { --p; }
1001 inline T *cbegin() const { return v; }
1002 inline T *cend() const { return v + p; }
1003 inline T *begin() { return v; }
1004 inline T *end() { return v + p; }
1005private:
1007 T *v = nullptr;
1008 int a = 0;
1009 int p = 0;
1010};
1011
1013{
1014 struct ResId { quint64 id; uint generation; };
1015 using ResIdList = QVarLengthArray<ResId, 8 * 2 + 1>; // color, resolve, ds
1016
1017 template<typename TexType, typename RenderBufferType>
1018 static void updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst);
1019
1020 template<typename TexType, typename RenderBufferType>
1021 static bool isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList);
1022};
1023
1025{
1026 return a.id == b.id && a.generation == b.generation;
1027}
1028
1030{
1031 return !(a == b);
1032}
1033
1034template<typename TexType, typename RenderBufferType>
1035void QRhiRenderTargetAttachmentTracker::updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst)
1036{
1037 const bool hasDepthStencil = desc.depthStencilBuffer() || desc.depthTexture();
1038 dst->resize(desc.colorAttachmentCount() * 2 + (hasDepthStencil ? 1 : 0));
1039 int n = 0;
1040 for (auto it = desc.cbeginColorAttachments(), itEnd = desc.cendColorAttachments(); it != itEnd; ++it, ++n) {
1041 const QRhiColorAttachment &colorAtt(*it);
1042 if (colorAtt.texture()) {
1043 TexType *texD = QRHI_RES(TexType, colorAtt.texture());
1044 (*dst)[n] = { texD->globalResourceId(), texD->generation };
1045 } else if (colorAtt.renderBuffer()) {
1046 RenderBufferType *rbD = QRHI_RES(RenderBufferType, colorAtt.renderBuffer());
1047 (*dst)[n] = { rbD->globalResourceId(), rbD->generation };
1048 } else {
1049 (*dst)[n] = { 0, 0 };
1050 }
1051 ++n;
1052 if (colorAtt.resolveTexture()) {
1053 TexType *texD = QRHI_RES(TexType, colorAtt.resolveTexture());
1054 (*dst)[n] = { texD->globalResourceId(), texD->generation };
1055 } else {
1056 (*dst)[n] = { 0, 0 };
1057 }
1058 }
1059 if (hasDepthStencil) {
1060 if (desc.depthTexture()) {
1061 TexType *depthTexD = QRHI_RES(TexType, desc.depthTexture());
1062 (*dst)[n] = { depthTexD->globalResourceId(), depthTexD->generation };
1063 } else if (desc.depthStencilBuffer()) {
1064 RenderBufferType *depthRbD = QRHI_RES(RenderBufferType, desc.depthStencilBuffer());
1065 (*dst)[n] = { depthRbD->globalResourceId(), depthRbD->generation };
1066 } else {
1067 (*dst)[n] = { 0, 0 };
1068 }
1069 }
1070}
1071
1072template<typename TexType, typename RenderBufferType>
1073bool QRhiRenderTargetAttachmentTracker::isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList)
1074{
1075 // Just as setShaderResources() recognizes if an srb's referenced
1076 // resources have been rebuilt (got a create() since the srb's
1077 // create()), we should do the same for the textures and renderbuffers
1078 // referenced from the rendertarget. It is not uncommon that a texture
1079 // or ds buffer gets resized due to following a window size in some
1080 // form, which involves a create() on them. It is then nice if the
1081 // render target auto-rebuilds in beginPass().
1082
1083 ResIdList resIdList;
1084 updateResIdList<TexType, RenderBufferType>(desc, &resIdList);
1085 return resIdList == currentResIdList;
1086}
1087
1088template<typename T>
1089inline T *qrhi_objectFromProxyData(QRhiSwapChainProxyData *pd, QWindow *window, QRhi::Implementation impl, uint objectIndex)
1090{
1091 Q_ASSERT(objectIndex < std::size(pd->reserved));
1092 if (!pd->reserved[objectIndex]) // // was not set, no other choice, do it here, whatever thread this is
1093 *pd = QRhi::updateSwapChainProxyData(impl, window);
1094 return static_cast<T *>(pd->reserved[objectIndex]);
1095}
1096
1098{
1099public:
1100 QRhiPipelineCacheDataReader(const char *data, quint32 size)
1101 : m_p(data), m_end(data + size)
1102 {
1103 }
1104
1105 bool readUInt32(quint32 *dst)
1106 {
1107 if (m_end - m_p < qptrdiff(sizeof(quint32)))
1108 return false;
1109 memcpy(dst, m_p, sizeof(quint32));
1110 m_p += sizeof(quint32);
1111 return true;
1112 }
1113
1114 // Reads a 32-bit length, followed by that many bytes.
1115 bool readByteArray(QByteArray *dst)
1116 {
1117 quint32 len = 0;
1118 if (!readUInt32(&len))
1119 return false;
1120 if (quint64(m_end - m_p) < len)
1121 return false;
1122 *dst = QByteArray(m_p, qsizetype(len));
1123 m_p += len;
1124 return true;
1125 }
1126
1127private:
1128 const char *m_p;
1129 const char *m_end;
1130};
1131
1132QT_END_NAMESPACE
1133
1134#endif
friend bool operator==(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
Returns true if lhs and rhs are equal, otherwise returns false.
Definition qbytearray.h:842
friend bool operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
Returns true if lhs and rhs are different, otherwise returns false.
Definition qbytearray.h:853
QRhiBackendCommandList()=default
T * cbegin() const
Definition qrhi_p.h:1001
bool isEmpty() const
Definition qrhi_p.h:987
void execute(QRhiCommandBuffer *cb, quint32 firstCommand, quint32 commandCount)
Definition qrhi.cpp:9337
QRhiBufferBackedIndirectCommandBuffer(QRhiImplementation *rhi, Type type, quint32 maxCommandCount)
\variable QRhiIndirectCommandBufferBuildInfo::topology
Definition qrhi.cpp:9247
void enqueueUpload(QRhiResourceUpdateBatch *u)
Definition qrhi.cpp:9301
QRhiIndirectCommandBufferBuildInfo buildInfo
Definition qrhi_p.h:385
void build(const QRhiIndirectCommandBufferBuildInfo &info)
Definition qrhi.cpp:9324
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
Definition qrhi.cpp:9259
bool create() override
Creates the corresponding native objects.
Definition qrhi.cpp:9282
void assign(QByteArray data)
Definition qrhi_p.h:508
QRhiBufferData()=default
void assign(const char *s, quint32 size)
Definition qrhi_p.h:489
quint32 size() const
Definition qrhi_p.h:481
QRhiBufferData(const QRhiBufferData &other)
Definition qrhi_p.h:460
quint32 largeAlloc() const
Definition qrhi_p.h:485
QRhiBufferData & operator=(const QRhiBufferData &other)
Definition qrhi_p.h:466
const char * constData() const
Definition qrhi_p.h:477
iterator end()
Definition qrhi_p.h:839
value_type * iterator
Definition qrhi_p.h:835
const value_type * const_iterator
Definition qrhi_p.h:836
bool isEmpty() const
Definition qrhi_p.h:845
iterator find(Key key)
Definition qrhi_p.h:864
const_iterator end() const
Definition qrhi_p.h:841
void append(Key key, const T &value)
Definition qrhi_p.h:873
const_iterator find(Key key) const
Definition qrhi_p.h:854
qsizetype size() const
Definition qrhi_p.h:846
std::pair< Key, T > value_type
Definition qrhi_p.h:834
const_iterator begin() const
Definition qrhi_p.h:840
bool contains(Key key) const
Definition qrhi_p.h:870
const_iterator cend() const
Definition qrhi_p.h:843
iterator begin()
Definition qrhi_p.h:838
const_iterator cbegin() const
Definition qrhi_p.h:842
static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
Definition qrhi.cpp:13744
static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
Definition qrhi.cpp:13725
bool isEmpty() const
Definition qrhi.cpp:13634
const QRhiPassResourceMap< QRhiTexture *, Texture, 12 > & textures() const
Definition qrhi_p.h:967
void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage, const UsageState &state)
Definition qrhi.cpp:13651
void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage, const UsageState &state)
Definition qrhi.cpp:13691
const QRhiPassResourceMap< QRhiBuffer *, Buffer, 12 > & buffers() const
Definition qrhi_p.h:959
QRhiPipelineCacheDataReader(const char *data, quint32 size)
Definition qrhi_p.h:1100
bool readByteArray(QByteArray *dst)
Definition qrhi_p.h:1115
bool readUInt32(quint32 *dst)
Definition qrhi_p.h:1105
QVarLengthArray< BufferOp, BUFFER_OPS_STATIC_ALLOC > bufferOps
Definition qrhi_p.h:730
QRhiImplementation * rhi
Definition qrhi_p.h:737
QVarLengthArray< TextureOp, TEXTURE_OPS_STATIC_ALLOC > textureOps
Definition qrhi_p.h:734
static const int BUFFER_OPS_STATIC_ALLOC
Definition qrhi_p.h:729
static QRhiResourceUpdateBatchPrivate * get(QRhiResourceUpdateBatch *b)
Definition qrhi_p.h:745
void merge(QRhiResourceUpdateBatchPrivate *other)
Definition qrhi.cpp:11408
QRhiResourceUpdateBatch * q
Definition qrhi_p.h:736
static const int TEXTURE_OPS_STATIC_ALLOC
Definition qrhi_p.h:733
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
static const char * resourceTypeStr(const QRhiResource *res)
Definition qrhi.cpp:9498
static QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a, QRhiPassResourceTracker::BufferStage b)
Definition qrhi.cpp:13645
QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
Definition qrhi.cpp:8550
static bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess access)
Definition qrhi.cpp:13684
static const char * deviceTypeStr(QRhiDriverInfo::DeviceType type)
\variable QRhiDriverInfo::deviceName
Definition qrhi.cpp:10481
static QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a, QRhiPassResourceTracker::TextureStage b)
Definition qrhi.cpp:13678
QRhiTargetRectBoundMode
Definition qrhi_p.h:389
@ UnBounded
Definition qrhi_p.h:390
@ Bounded
Definition qrhi_p.h:391
Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Texture, Q_RELOCATABLE_TYPE)
Q_DECLARE_TYPEINFO(QRhiBufferData, Q_RELOCATABLE_TYPE)
T * qrhi_objectFromProxyData(QRhiSwapChainProxyData *pd, QWindow *window, QRhi::Implementation impl, uint objectIndex)
Definition qrhi_p.h:1089
bool operator!=(const QRhiRenderTargetAttachmentTracker::ResId &a, const QRhiRenderTargetAttachmentTracker::ResId &b)
Definition qrhi_p.h:1029
Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Buffer, Q_RELOCATABLE_TYPE)
#define QRHI_RES(t, x)
Definition qrhi_p.h:32
bool operator==(const QRhiRenderTargetAttachmentTracker::ResId &a, const QRhiRenderTargetAttachmentTracker::ResId &b)
Definition qrhi_p.h:1024
quint32 qrhiBinaryCacheEntryByteSize(const QByteArray &data)
Definition qrhi_p.h:309
bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array< T, N > &r, T *x, T *y, T *w, T *h)
Definition qrhi_p.h:395
constexpr size_t qHash(const QSize &s, size_t seed=0) noexcept
Definition qsize.h:192
bool operator!=(const Batch &other) const
Definition qrhi_p.h:785
QVector< T > resources
Definition qrhi_p.h:778
bool operator==(const Batch &other) const
Definition qrhi_p.h:780
void feed(int binding, T resource)
Definition qrhi_p.h:751
QVector< Batch > batches
Definition qrhi_p.h:794
bool operator!=(const QRhiBatchedBindings< T > &other) const
Definition qrhi_p.h:801
bool operator==(const QRhiBatchedBindings< T > &other) const
Definition qrhi_p.h:796
void insertWithCapacityLimit(const Key &key, const Value &value)
Definition qrhi_p.h:330
quint32 dataByteSize
Definition qrhi_p.h:321
void clear()
Definition qrhi_p.h:324
const char * name
Definition qrhi_p.h:322
QHash< Key, Value > data
Definition qrhi_p.h:320
QRhiBinaryCache(const char *name)
Definition qrhi_p.h:318
char smallData[SMALL_DATA_SIZE]
Definition qrhi_p.h:447
QByteArray largeData
Definition qrhi_p.h:445
static constexpr quint32 SMALL_DATA_SIZE
Definition qrhi_p.h:446
void(* frameEnd)(QRhiImplementation *d, QRhiSwapChain *swapChain, QRhiCommandBuffer *cb)
Definition qrhi_p.h:361
void(* rhiAboutToBeDestroyed)(QRhiImplementation *d)
Definition qrhi_p.h:362
static void updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst)
Definition qrhi_p.h:1035
static bool isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList)
Definition qrhi_p.h:1073
static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:575
static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:606
static BufferOp clear(QRhiBuffer *buf, quint32 offset, quint32 size, quint8 value)
Definition qrhi_p.h:638
static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:590
static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:568
static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:599
static BufferOp copy(QRhiBuffer *dst, QRhiBuffer *src, quint32 dstOffset, quint32 srcOffset, quint32 size)
Definition qrhi_p.h:625
static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:583
static BufferOp read(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
Definition qrhi_p.h:614
static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:552
static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:559
QRhiTextureSubresourceUploadDescription desc
Definition qrhi_p.h:678
QRhiTextureCopyDescription desc
Definition qrhi_p.h:682
static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
Definition qrhi_p.h:700
QVarLengthArray< SubresourceUpload, 4 > subresDesc
Definition qrhi_p.h:680
static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
Definition qrhi_p.h:686
static TextureOp genMips(QRhiTexture *tex)
Definition qrhi_p.h:719
static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
Definition qrhi_p.h:710
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1588
LimitsType limitsType
Definition qrhi.h:1599
float maxPotentialColorComponentValue
Definition qrhi.h:1607
LuminanceBehavior luminanceBehavior
Definition qrhi.h:1610
float maxColorComponentValue
Definition qrhi.h:1606
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1621
void * reserved[2]
Definition qrhi.h:1622