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/qset.h>
25#include <QtCore/qvarlengtharray.h>
26#include <QtCore/private/qflatmap_p.h>
27
29
30#define QRHI_RES(t, x) static_cast<t *>(x)
31#define QRHI_RES_RHI(t) t *rhiD = static_cast<t *>(m_rhi)
32
33Q_DECLARE_LOGGING_CATEGORY(QRHI_LOG_INFO)
34Q_DECLARE_LOGGING_CATEGORY(QRHI_LOG_RUB)
35
36class QRhiImplementation
37{
38public:
39 virtual ~QRhiImplementation();
40
41 virtual bool create(QRhi::Flags flags) = 0;
42 virtual void destroy() = 0;
43 virtual QRhi::AdapterList enumerateAdaptersBeforeCreate(QRhiNativeHandles *nativeHandles) const;
44
45 virtual QRhiGraphicsPipeline *createGraphicsPipeline() = 0;
46 virtual QRhiComputePipeline *createComputePipeline() = 0;
47 virtual QRhiShaderResourceBindings *createShaderResourceBindings() = 0;
48 virtual QRhiBuffer *createBuffer(QRhiBuffer::Type type,
49 QRhiBuffer::UsageFlags usage,
50 quint32 size) = 0;
51 virtual QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
52 const QSize &pixelSize,
53 int sampleCount,
54 QRhiRenderBuffer::Flags flags,
55 QRhiTexture::Format backingFormatHint) = 0;
56 virtual QRhiTexture *createTexture(QRhiTexture::Format format,
57 const QSize &pixelSize,
58 int depth,
59 int arraySize,
60 int sampleCount,
61 QRhiTexture::Flags flags) = 0;
62 virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
63 QRhiSampler::Filter minFilter,
64 QRhiSampler::Filter mipmapMode,
65 QRhiSampler:: AddressMode u,
66 QRhiSampler::AddressMode v,
67 QRhiSampler::AddressMode w) = 0;
68
69 virtual QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
70 QRhiTextureRenderTarget::Flags flags) = 0;
71
72 virtual QRhiShadingRateMap *createShadingRateMap() = 0;
73
74 virtual QRhiSwapChain *createSwapChain() = 0;
75 virtual QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) = 0;
76 virtual QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) = 0;
77 virtual QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) = 0;
78 virtual QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) = 0;
79 virtual QRhi::FrameOpResult finish() = 0;
80
81 virtual void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
82
83 virtual void beginPass(QRhiCommandBuffer *cb,
84 QRhiRenderTarget *rt,
85 const QColor &colorClearValue,
86 const QRhiDepthStencilClearValue &depthStencilClearValue,
87 QRhiResourceUpdateBatch *resourceUpdates,
88 QRhiCommandBuffer::BeginPassFlags flags) = 0;
89 virtual void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
90
91 virtual void setGraphicsPipeline(QRhiCommandBuffer *cb,
92 QRhiGraphicsPipeline *ps) = 0;
93
94 virtual void setShaderResources(QRhiCommandBuffer *cb,
95 QRhiShaderResourceBindings *srb,
96 int dynamicOffsetCount,
97 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) = 0;
98
99 virtual void setVertexInput(QRhiCommandBuffer *cb,
100 int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
101 QRhiBuffer *indexBuf, quint32 indexOffset,
102 QRhiCommandBuffer::IndexFormat indexFormat) = 0;
103
104 virtual void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) = 0;
105 virtual void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) = 0;
106 virtual void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) = 0;
107 virtual void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) = 0;
108 virtual void setShadingRate(QRhiCommandBuffer *cb, const QSize &coarsePixelSize) = 0;
109
110 virtual void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
111 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) = 0;
112 virtual void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
113 quint32 instanceCount, quint32 firstIndex,
114 qint32 vertexOffset, quint32 firstInstance) = 0;
115
116 virtual void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) = 0;
117 virtual void debugMarkEnd(QRhiCommandBuffer *cb) = 0;
118 virtual void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) = 0;
119
120 virtual void beginComputePass(QRhiCommandBuffer *cb,
121 QRhiResourceUpdateBatch *resourceUpdates,
122 QRhiCommandBuffer::BeginPassFlags flags) = 0;
123 virtual void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
124 virtual void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) = 0;
125 virtual void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) = 0;
126
127 virtual const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) = 0;
128 virtual void beginExternal(QRhiCommandBuffer *cb) = 0;
129 virtual void endExternal(QRhiCommandBuffer *cb) = 0;
130 virtual double lastCompletedGpuTime(QRhiCommandBuffer *cb) = 0;
131
132 virtual QList<int> supportedSampleCounts() const = 0;
133 virtual int ubufAlignment() const = 0;
134 virtual QList<QSize> supportedShadingRates(int sampleCount) const = 0;
135 virtual bool isYUpInFramebuffer() const = 0;
136 virtual bool isYUpInNDC() const = 0;
137 virtual bool isClipDepthZeroToOne() const = 0;
138 virtual QMatrix4x4 clipSpaceCorrMatrix() const = 0;
139 virtual bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const = 0;
140 virtual bool isFeatureSupported(QRhi::Feature feature) const = 0;
141 virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0;
142 virtual const QRhiNativeHandles *nativeHandles() = 0;
143 virtual QRhiDriverInfo driverInfo() const = 0;
144 virtual QRhiStats statistics() = 0;
145 virtual bool makeThreadLocalNativeContextCurrent() = 0;
146 virtual void setQueueSubmitParams(QRhiNativeHandles *params) = 0;
147 virtual void releaseCachedResources() = 0;
148 virtual bool isDeviceLost() const = 0;
149
150 virtual QByteArray pipelineCacheData() = 0;
151 virtual void setPipelineCacheData(const QByteArray &data) = 0;
152
153 static QRhiImplementation *newInstance(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *importDevice);
154 void prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags, QRhiAdapter *adapter);
155
156 bool isCompressedFormat(QRhiTexture::Format format) const;
157 void compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
158 quint32 *bpl, quint32 *byteSize,
159 QSize *blockDim) const;
160 void textureFormatInfo(QRhiTexture::Format format, const QSize &size,
161 quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const;
162 bool isStencilSupportingFormat(QRhiTexture::Format format) const;
163
164 void registerResource(QRhiResource *res, bool ownsNativeResources = true)
165 {
166 // The ownsNativeResources is relevant for the (graphics resource) leak
167 // check in ~QRhiImplementation; when false, the registration's sole
168 // purpose is to automatically null out the resource's m_rhi pointer in
169 // case the rhi goes away first. (which should not happen in
170 // well-written applications but we try to be graceful)
171 resources.insert(res, ownsNativeResources);
172 }
173
174 void unregisterResource(QRhiResource *res)
175 {
176 resources.remove(res);
177 }
178
179 void addDeleteLater(QRhiResource *res)
180 {
181 if (inFrame)
182 pendingDeleteResources.insert(res);
183 else
184 delete res;
185 }
186
187 void addCleanupCallback(const QRhi::CleanupCallback &callback)
188 {
189 cleanupCallbacks.append(callback);
190 }
191
192 void addCleanupCallback(const void *key, const QRhi::CleanupCallback &callback)
193 {
194 keyedCleanupCallbacks[key] = callback;
195 }
196
197 void removeCleanupCallback(const void *key)
198 {
199 keyedCleanupCallbacks.remove(key);
200 }
201
202 bool sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps);
203 bool sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb);
204 void updateLayoutDesc(QRhiShaderResourceBindings *srb);
205
206 quint32 pipelineCacheRhiId() const
207 {
208 const quint32 ver = (QT_VERSION_MAJOR << 16) | (QT_VERSION_MINOR << 8) | (QT_VERSION_PATCH);
209 return (quint32(implType) << 24) | ver;
210 }
211
212 void pipelineCreationStart()
213 {
214 pipelineCreationTimer.start();
215 }
216
217 void pipelineCreationEnd()
218 {
219 accumulatedPipelineCreationTime += pipelineCreationTimer.elapsed();
220 }
221
222 qint64 totalPipelineCreationTime() const
223 {
224 return accumulatedPipelineCreationTime;
225 }
226
227 QRhiVertexInputAttribute::Format shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const;
228 quint32 byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const;
229
230 static const QRhiShaderResourceBinding::Data *shaderResourceBindingData(const QRhiShaderResourceBinding &binding)
231 {
232 return &binding.d;
233 }
234
235 static QRhiShaderResourceBinding::Data *shaderResourceBindingData(QRhiShaderResourceBinding &binding)
236 {
237 return &binding.d;
238 }
239
240 static bool sortedBindingLessThan(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
241 {
242 return a.d.binding < b.d.binding;
243 }
244
245 int effectiveSampleCount(int sampleCount) const;
246 QSize clampedSubResourceUploadSize(QSize size, QPoint dstPos, int level, QSize textureSizeAtLevelZero, bool warn = true);
247
248 void runCleanup();
249
250 QRhi *q;
251
252 static const int MAX_SHADER_CACHE_ENTRIES = 128;
253
254 bool debugMarkers = false;
255 int currentFrameSlot = 0; // for vk, mtl, and similar. unused by gl and d3d11.
256 bool inFrame = false;
257
258 QRhiAdapter *requestedRhiAdapter = nullptr;
259
260private:
261 QRhi::Implementation implType;
262 QThread *implThread;
263 QVarLengthArray<QRhiResourceUpdateBatch *, 4> resUpdPool;
264 quint64 resUpdPoolMap = 0;
265 int lastResUpdIdx = -1;
266 QHash<QRhiResource *, bool> resources;
267 QSet<QRhiResource *> pendingDeleteResources;
268 QVarLengthArray<QRhi::CleanupCallback, 4> cleanupCallbacks;
269 QHash<const void *, QRhi::CleanupCallback> keyedCleanupCallbacks;
270 QElapsedTimer pipelineCreationTimer;
271 qint64 accumulatedPipelineCreationTime = 0;
272
273 friend class QRhi;
274 friend class QRhiResourceUpdateBatchPrivate;
275 friend class QRhiBufferData;
276};
277
283
284template<QRhiTargetRectBoundMode boundingMode, typename T, size_t N>
285bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T, N> &r,
286 T *x, T *y, T *w, T *h)
287{
288 // x,y are bottom-left in QRhiScissor and QRhiViewport but top-left in
289 // Vulkan/Metal/D3D. Our input is an OpenGL-style scissor rect where both
290 // negative x or y, and partly or completely out of bounds rects are
291 // allowed. The only thing the input here cannot have is a negative width
292 // or height. We must handle all other input gracefully, clamping to a zero
293 // width or height rect in the worst case, and ensuring the resulting rect
294 // is inside the rendertarget's bounds because some APIs' validation/debug
295 // layers are allergic to out of bounds scissor rects.
296
297 const T outputWidth = outputSize.width();
298 const T outputHeight = outputSize.height();
299 const T inputWidth = r[2];
300 const T inputHeight = r[3];
301
302 if (inputWidth < 0 || inputHeight < 0)
303 return false;
304
305 *x = r[0];
306 *y = outputHeight - (r[1] + inputHeight);
307 *w = inputWidth;
308 *h = inputHeight;
309
310 if (boundingMode == Bounded) {
311 const T widthOffset = *x < 0 ? -*x : 0;
312 const T heightOffset = *y < 0 ? -*y : 0;
313 *w = *x < outputWidth ? qMax<T>(0, inputWidth - widthOffset) : 0;
314 *h = *y < outputHeight ? qMax<T>(0, inputHeight - heightOffset) : 0;
315
316 if (outputWidth > 0)
317 *x = qBound<T>(0, *x, outputWidth - 1);
318 if (outputHeight > 0)
319 *y = qBound<T>(0, *y, outputHeight - 1);
320
321 if (*x + *w > outputWidth)
322 *w = qMax<T>(0, outputWidth - *x);
323 if (*y + *h > outputHeight)
324 *h = qMax<T>(0, outputHeight - *y);
325 }
326 return true;
327}
328
330{
332 QRhiBufferDataPrivate() { } // don't value-initialize smallData
333 int ref = 1;
336 static constexpr quint32 SMALL_DATA_SIZE = 1024;
337 char smallData[SMALL_DATA_SIZE];
338};
339
340// no detach-with-contents, no atomic refcount, no shrink
342{
343public:
344 QRhiBufferData() = default;
346 {
347 if (d && !--d->ref)
348 delete d;
349 }
351 : d(other.d)
352 {
353 if (d)
354 d->ref += 1;
355 }
357 {
358 if (d == other.d)
359 return *this;
360 if (other.d)
361 other.d->ref += 1;
362 if (d && !--d->ref)
363 delete d;
364 d = other.d;
365 return *this;
366 }
367 const char *constData() const
368 {
369 return d ? (d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE ? d->smallData : d->largeData.constData()) : nullptr;
370 }
371 quint32 size() const
372 {
373 return d ? d->size : 0;
374 }
376 {
377 return d ? d->largeData.size() : 0;
378 }
379 void assign(const char *s, quint32 size)
380 {
381 if (!d) {
382 d = new QRhiBufferDataPrivate;
383 } else if (d->ref != 1) {
384 if (QRHI_LOG_RUB().isDebugEnabled())
385 qDebug("[rub] QRhiBufferData %p/%p new backing due to no-copy detach, ref was %d", this, d, d->ref);
386 d->ref -= 1;
387 d = new QRhiBufferDataPrivate;
388 }
389 d->size = size;
390 if (size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) {
391 memcpy(d->smallData, s, size);
392 } else {
393 if (QRHI_LOG_RUB().isDebugEnabled() && largeAlloc() < size)
394 qDebug("[rub] QRhiBufferData %p/%p new large data allocation %u -> %u", this, d, largeAlloc(), size);
395 d->largeData.assign(QByteArrayView(s, size)); // keeps capacity
396 }
397 }
398 void assign(QByteArray data)
399 {
400 if (!d) {
401 d = new QRhiBufferDataPrivate;
402 } else if (d->ref != 1) {
403 if (QRHI_LOG_RUB().isDebugEnabled())
404 qDebug("[rub] QRhiBufferData %p/%p new backing due to no-copy detach, ref was %d", this, d, d->ref);
405 d->ref -= 1;
406 d = new QRhiBufferDataPrivate;
407 }
408 d->size = data.size();
409 if (d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) {
410 memcpy(d->smallData, data.constData(), data.size());
411 } else {
412 d->largeData = std::move(data);
413 }
414 }
415private:
416 QRhiBufferDataPrivate *d = nullptr;
417};
418
420
422{
423public:
424 struct BufferOp {
431 QRhiBuffer *buf;
436
437 static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
438 {
439 BufferOp op = {};
440 changeToDynamicUpdate(&op, buf, offset, size, data);
441 return op;
442 }
443
444 static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
445 {
447 op->buf = buf;
448 op->offset = offset;
449 const int effectiveSize = size ? size : buf->size();
450 op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
451 }
452
453 static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, QByteArray data)
454 {
455 BufferOp op = {};
456 changeToDynamicUpdate(&op, buf, offset, std::move(data));
457 return op;
458 }
459
460 static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
461 {
463 op->buf = buf;
464 op->offset = offset;
465 op->data.assign(std::move(data));
466 }
467
468 static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
469 {
470 BufferOp op = {};
471 changeToStaticUpload(&op, buf, offset, size, data);
472 return op;
473 }
474
475 static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
476 {
478 op->buf = buf;
479 op->offset = offset;
480 const int effectiveSize = size ? size : buf->size();
481 op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
482 }
483
484 static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, QByteArray data)
485 {
486 BufferOp op = {};
487 changeToStaticUpload(&op, buf, offset, std::move(data));
488 return op;
489 }
490
491 static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
492 {
494 op->buf = buf;
495 op->offset = offset;
496 op->data.assign(std::move(data));
497 }
498
499 static BufferOp read(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
500 {
501 BufferOp op = {};
502 op.type = Read;
503 op.buf = buf;
504 op.offset = offset;
505 op.readSize = size;
506 op.result = result;
507 return op;
508 }
509 };
510
511 struct TextureOp {
519 QRhiTexture *dst;
520 // Specifying multiple uploads for a subresource must be supported.
521 // In the backend this can then end up, where applicable, as a
522 // single, batched copy operation with only one set of barriers.
523 // This helps when doing for example glyph cache fills.
526 QRhiTexture *src;
530
531 static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
532 {
533 TextureOp op = {};
534 op.type = Upload;
535 op.dst = tex;
536 int maxLayer = -1;
537 for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it) {
538 if (it->layer() > maxLayer)
539 maxLayer = it->layer();
540 }
541 op.subresDesc.resize(maxLayer + 1);
542 for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it)
543 op.subresDesc[it->layer()][it->level()].append(it->description());
544 return op;
545 }
546
547 static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
548 {
549 TextureOp op = {};
550 op.type = Copy;
551 op.dst = dst;
552 op.src = src;
553 op.desc = desc;
554 return op;
555 }
556
557 static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
558 {
559 TextureOp op = {};
560 op.type = Read;
561 op.rb = rb;
562 op.result = result;
563 return op;
564 }
565
566 static TextureOp genMips(QRhiTexture *tex)
567 {
568 TextureOp op = {};
569 op.type = GenMips;
570 op.dst = tex;
571 return op;
572 }
573 };
574
575 int activeBufferOpCount = 0; // this is the real number of used elements in bufferOps, not bufferOps.count()
576 static const int BUFFER_OPS_STATIC_ALLOC = 64;
578
579 int activeTextureOpCount = 0; // this is the real number of used elements in textureOps, not textureOps.count()
580 static const int TEXTURE_OPS_STATIC_ALLOC = 32;
582
583 QRhiResourceUpdateBatch *q = nullptr;
584 QRhiImplementation *rhi = nullptr;
585 int poolIndex = -1;
586
587 void free();
589 bool hasOptimalCapacity() const;
590 void trimOpLists();
591
592 static QRhiResourceUpdateBatchPrivate *get(QRhiResourceUpdateBatch *b) { return b->d; }
593};
594
595template<typename T>
597{
598 void feed(int binding, T resource) { // binding must be strictly increasing
599 if (curBinding == -1 || binding > curBinding + 1) {
600 finish();
601 curBatch.startBinding = binding;
602 curBatch.resources.clear();
603 curBatch.resources.append(resource);
604 } else {
605 Q_ASSERT(binding == curBinding + 1);
606 curBatch.resources.append(resource);
607 }
608 curBinding = binding;
609 }
610
611 bool finish() {
612 if (!curBatch.resources.isEmpty())
613 batches.append(curBatch);
614 return !batches.isEmpty();
615 }
616
617 void clear() {
618 batches.clear();
619 curBatch.resources.clear();
620 curBinding = -1;
621 }
622
623 struct Batch {
626
627 bool operator==(const Batch &other) const
628 {
629 return startBinding == other.startBinding && resources == other.resources;
630 }
631
632 bool operator!=(const Batch &other) const
633 {
634 return !operator==(other);
635 }
636 };
637
638 // some backends make copies of QRhiBatchedBindings -> implicit sharing and
639 // not having a (possibly wasted) prealloc are beneficial -> use QVector
640 // instead of QVLA
641 QVector<Batch> batches; // sorted by startBinding
642
643 bool operator==(const QRhiBatchedBindings<T> &other) const
644 {
645 return batches == other.batches;
646 }
647
648 bool operator!=(const QRhiBatchedBindings<T> &other) const
649 {
650 return !operator==(other);
651 }
652
653private:
654 Batch curBatch;
655 int curBinding = -1;
656};
657
659{
660public:
661#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
662 using Type = quint64;
663#else
664 using Type = quint32;
665#endif
666 static Type newId();
667};
668
670{
671public:
672 bool isEmpty() const;
673 void reset();
674
675 struct UsageState {
678 int stage;
679 };
680
690
699
700 void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
701 const UsageState &state);
702
713
723
724 void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage,
725 const UsageState &state);
726
733
734 const QVarLengthFlatMap<QRhiBuffer *, Buffer, 12> &buffers() const { return m_buffers; }
735
741
742 const QVarLengthFlatMap<QRhiTexture *, Texture, 12> &textures() const { return m_textures; }
743
744 static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages);
745 static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages);
746
747private:
748 QVarLengthFlatMap<QRhiBuffer *, Buffer, 12> m_buffers;
749 QVarLengthFlatMap<QRhiTexture *, Texture, 12> m_textures;
750};
751
754
755template<typename T, int GROW = 1024>
757{
758public:
760 ~QRhiBackendCommandList() { delete[] v; }
761 inline void reset() { p = 0; }
762 inline bool isEmpty() const { return p == 0; }
763 inline T &get() {
764 if (p == a) {
765 a += GROW;
766 T *nv = new T[a];
767 if (v) {
768 memcpy(nv, v, p * sizeof(T));
769 delete[] v;
770 }
771 v = nv;
772 }
773 return v[p++];
774 }
775 inline void unget() { --p; }
776 inline T *cbegin() const { return v; }
777 inline T *cend() const { return v + p; }
778 inline T *begin() { return v; }
779 inline T *end() { return v + p; }
780private:
782 T *v = nullptr;
783 int a = 0;
784 int p = 0;
785};
786
788{
790 using ResIdList = QVarLengthArray<ResId, 8 * 2 + 1>; // color, resolve, ds
791
792 template<typename TexType, typename RenderBufferType>
793 static void updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst);
794
795 template<typename TexType, typename RenderBufferType>
796 static bool isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList);
797};
798
800{
801 return a.id == b.id && a.generation == b.generation;
802}
803
805{
806 return !(a == b);
807}
808
809template<typename TexType, typename RenderBufferType>
810void QRhiRenderTargetAttachmentTracker::updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst)
811{
812 const bool hasDepthStencil = desc.depthStencilBuffer() || desc.depthTexture();
813 dst->resize(desc.colorAttachmentCount() * 2 + (hasDepthStencil ? 1 : 0));
814 int n = 0;
815 for (auto it = desc.cbeginColorAttachments(), itEnd = desc.cendColorAttachments(); it != itEnd; ++it, ++n) {
816 const QRhiColorAttachment &colorAtt(*it);
817 if (colorAtt.texture()) {
818 TexType *texD = QRHI_RES(TexType, colorAtt.texture());
819 (*dst)[n] = { texD->globalResourceId(), texD->generation };
820 } else if (colorAtt.renderBuffer()) {
821 RenderBufferType *rbD = QRHI_RES(RenderBufferType, colorAtt.renderBuffer());
822 (*dst)[n] = { rbD->globalResourceId(), rbD->generation };
823 } else {
824 (*dst)[n] = { 0, 0 };
825 }
826 ++n;
827 if (colorAtt.resolveTexture()) {
828 TexType *texD = QRHI_RES(TexType, colorAtt.resolveTexture());
829 (*dst)[n] = { texD->globalResourceId(), texD->generation };
830 } else {
831 (*dst)[n] = { 0, 0 };
832 }
833 }
834 if (hasDepthStencil) {
835 if (desc.depthTexture()) {
836 TexType *depthTexD = QRHI_RES(TexType, desc.depthTexture());
837 (*dst)[n] = { depthTexD->globalResourceId(), depthTexD->generation };
838 } else if (desc.depthStencilBuffer()) {
839 RenderBufferType *depthRbD = QRHI_RES(RenderBufferType, desc.depthStencilBuffer());
840 (*dst)[n] = { depthRbD->globalResourceId(), depthRbD->generation };
841 } else {
842 (*dst)[n] = { 0, 0 };
843 }
844 }
845}
846
847template<typename TexType, typename RenderBufferType>
848bool QRhiRenderTargetAttachmentTracker::isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList)
849{
850 // Just as setShaderResources() recognizes if an srb's referenced
851 // resources have been rebuilt (got a create() since the srb's
852 // create()), we should do the same for the textures and renderbuffers
853 // referenced from the rendertarget. It is not uncommon that a texture
854 // or ds buffer gets resized due to following a window size in some
855 // form, which involves a create() on them. It is then nice if the
856 // render target auto-rebuilds in beginPass().
857
858 ResIdList resIdList;
859 updateResIdList<TexType, RenderBufferType>(desc, &resIdList);
860 return resIdList == currentResIdList;
861}
862
863template<typename T>
864inline T *qrhi_objectFromProxyData(QRhiSwapChainProxyData *pd, QWindow *window, QRhi::Implementation impl, uint objectIndex)
865{
866 Q_ASSERT(objectIndex < std::size(pd->reserved));
867 if (!pd->reserved[objectIndex]) // // was not set, no other choice, do it here, whatever thread this is
868 *pd = QRhi::updateSwapChainProxyData(impl, window);
869 return static_cast<T *>(pd->reserved[objectIndex]);
870}
871
872QT_END_NAMESPACE
873
874#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:807
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:818
QRhiBackendCommandList()=default
T * cend() const
Definition qrhi_p.h:777
T * cbegin() const
Definition qrhi_p.h:776
bool isEmpty() const
Definition qrhi_p.h:762
void assign(QByteArray data)
Definition qrhi_p.h:398
QRhiBufferData()=default
void assign(const char *s, quint32 size)
Definition qrhi_p.h:379
quint32 size() const
Definition qrhi_p.h:371
QRhiBufferData(const QRhiBufferData &other)
Definition qrhi_p.h:350
quint32 largeAlloc() const
Definition qrhi_p.h:375
QRhiBufferData & operator=(const QRhiBufferData &other)
Definition qrhi_p.h:356
const char * constData() const
Definition qrhi_p.h:367
static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
Definition qrhi.cpp:11895
const QVarLengthFlatMap< QRhiBuffer *, Buffer, 12 > & buffers() const
Definition qrhi_p.h:734
static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
Definition qrhi.cpp:11876
const QVarLengthFlatMap< QRhiTexture *, Texture, 12 > & textures() const
Definition qrhi_p.h:742
bool isEmpty() const
Definition qrhi.cpp:11785
void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage, const UsageState &state)
Definition qrhi.cpp:11802
void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage, const UsageState &state)
Definition qrhi.cpp:11842
QVarLengthArray< BufferOp, BUFFER_OPS_STATIC_ALLOC > bufferOps
Definition qrhi_p.h:577
QRhiImplementation * rhi
Definition qrhi_p.h:584
QVarLengthArray< TextureOp, TEXTURE_OPS_STATIC_ALLOC > textureOps
Definition qrhi_p.h:581
static const int BUFFER_OPS_STATIC_ALLOC
Definition qrhi_p.h:576
static QRhiResourceUpdateBatchPrivate * get(QRhiResourceUpdateBatch *b)
Definition qrhi_p.h:592
void merge(QRhiResourceUpdateBatchPrivate *other)
Definition qrhi.cpp:10030
QRhiResourceUpdateBatch * q
Definition qrhi_p.h:583
static const int TEXTURE_OPS_STATIC_ALLOC
Definition qrhi_p.h:580
Combined button and popup list for selecting options.
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
static const char * resourceTypeStr(const QRhiResource *res)
Definition qrhi.cpp:8401
static QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a, QRhiPassResourceTracker::BufferStage b)
Definition qrhi.cpp:11796
QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
Definition qrhi.cpp:8216
static bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess access)
Definition qrhi.cpp:11835
static const char * deviceTypeStr(QRhiDriverInfo::DeviceType type)
\variable QRhiDriverInfo::deviceName
Definition qrhi.cpp:9320
static QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a, QRhiPassResourceTracker::TextureStage b)
Definition qrhi.cpp:11829
QRhiTargetRectBoundMode
Definition qrhi_p.h:279
@ UnBounded
Definition qrhi_p.h:280
@ Bounded
Definition qrhi_p.h:281
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:864
bool operator!=(const QRhiRenderTargetAttachmentTracker::ResId &a, const QRhiRenderTargetAttachmentTracker::ResId &b)
Definition qrhi_p.h:804
Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Buffer, Q_RELOCATABLE_TYPE)
#define QRHI_RES(t, x)
Definition qrhi_p.h:30
bool operator==(const QRhiRenderTargetAttachmentTracker::ResId &a, const QRhiRenderTargetAttachmentTracker::ResId &b)
Definition qrhi_p.h:799
bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array< T, N > &r, T *x, T *y, T *w, T *h)
Definition qrhi_p.h:285
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:632
QVector< T > resources
Definition qrhi_p.h:625
bool operator==(const Batch &other) const
Definition qrhi_p.h:627
void feed(int binding, T resource)
Definition qrhi_p.h:598
QVector< Batch > batches
Definition qrhi_p.h:641
bool operator!=(const QRhiBatchedBindings< T > &other) const
Definition qrhi_p.h:648
bool operator==(const QRhiBatchedBindings< T > &other) const
Definition qrhi_p.h:643
char smallData[SMALL_DATA_SIZE]
Definition qrhi_p.h:337
QByteArray largeData
Definition qrhi_p.h:335
static constexpr quint32 SMALL_DATA_SIZE
Definition qrhi_p.h:336
static void updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst)
Definition qrhi_p.h:810
static bool isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList)
Definition qrhi_p.h:848
static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:460
static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:491
static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:475
static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:453
static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:484
static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:468
static BufferOp read(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
Definition qrhi_p.h:499
static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:437
static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:444
QRhiTextureCopyDescription desc
Definition qrhi_p.h:527
static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
Definition qrhi_p.h:547
QVarLengthArray< MipLevelUploadList, 6 > subresDesc
Definition qrhi_p.h:525
static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
Definition qrhi_p.h:531
static TextureOp genMips(QRhiTexture *tex)
Definition qrhi_p.h:566
static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
Definition qrhi_p.h:557
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1556
LimitsType limitsType
Definition qrhi.h:1567
float maxPotentialColorComponentValue
Definition qrhi.h:1575
LuminanceBehavior luminanceBehavior
Definition qrhi.h:1578
float maxColorComponentValue
Definition qrhi.h:1574
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1589
void * reserved[2]
Definition qrhi.h:1590