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 virtual void drawIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer,
116 quint32 offset, quint32 drawCount, quint32 stride) = 0;
117 virtual void drawIndexedIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer,
118 quint32 offset, quint32 drawCount, quint32 stride) = 0;
119
120 virtual void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) = 0;
121 virtual void debugMarkEnd(QRhiCommandBuffer *cb) = 0;
122 virtual void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) = 0;
123
124 virtual void beginComputePass(QRhiCommandBuffer *cb,
125 QRhiResourceUpdateBatch *resourceUpdates,
126 QRhiCommandBuffer::BeginPassFlags flags) = 0;
127 virtual void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
128 virtual void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) = 0;
129 virtual void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) = 0;
130
131 virtual const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) = 0;
132 virtual void beginExternal(QRhiCommandBuffer *cb) = 0;
133 virtual void endExternal(QRhiCommandBuffer *cb) = 0;
134 virtual double lastCompletedGpuTime(QRhiCommandBuffer *cb) = 0;
135
136 virtual QList<int> supportedSampleCounts() const = 0;
137 virtual int ubufAlignment() const = 0;
138 virtual QList<QSize> supportedShadingRates(int sampleCount) const = 0;
139 virtual bool isYUpInFramebuffer() const = 0;
140 virtual bool isYUpInNDC() const = 0;
141 virtual bool isClipDepthZeroToOne() const = 0;
142 virtual QMatrix4x4 clipSpaceCorrMatrix() const = 0;
143 virtual bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const = 0;
144 virtual bool isFeatureSupported(QRhi::Feature feature) const = 0;
145 virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0;
146 virtual const QRhiNativeHandles *nativeHandles() = 0;
147 virtual QRhiDriverInfo driverInfo() const = 0;
148 virtual QRhiStats statistics() = 0;
149 virtual bool makeThreadLocalNativeContextCurrent() = 0;
150 virtual void setQueueSubmitParams(QRhiNativeHandles *params) = 0;
151 virtual void releaseCachedResources() = 0;
152 virtual bool isDeviceLost() const = 0;
153
154 virtual QByteArray pipelineCacheData() = 0;
155 virtual void setPipelineCacheData(const QByteArray &data) = 0;
156
157 static QRhiImplementation *newInstance(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *importDevice);
158 void prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags, QRhiAdapter *adapter);
159
160 bool isCompressedFormat(QRhiTexture::Format format) const;
161 void compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
162 quint32 *bpl, quint32 *byteSize,
163 QSize *blockDim) const;
164 void textureFormatInfo(QRhiTexture::Format format, const QSize &size,
165 quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const;
166 bool isStencilSupportingFormat(QRhiTexture::Format format) const;
167
168 void registerResource(QRhiResource *res, bool ownsNativeResources = true)
169 {
170 // The ownsNativeResources is relevant for the (graphics resource) leak
171 // check in ~QRhiImplementation; when false, the registration's sole
172 // purpose is to automatically null out the resource's m_rhi pointer in
173 // case the rhi goes away first. (which should not happen in
174 // well-written applications but we try to be graceful)
175 resources.insert(res, ownsNativeResources);
176 }
177
178 void unregisterResource(QRhiResource *res)
179 {
180 resources.remove(res);
181 }
182
183 void addDeleteLater(QRhiResource *res)
184 {
185 if (inFrame)
186 pendingDeleteResources.insert(res);
187 else
188 delete res;
189 }
190
191 void addCleanupCallback(const QRhi::CleanupCallback &callback)
192 {
193 cleanupCallbacks.append(callback);
194 }
195
196 void addCleanupCallback(const void *key, const QRhi::CleanupCallback &callback)
197 {
198 keyedCleanupCallbacks[key] = callback;
199 }
200
201 void removeCleanupCallback(const void *key)
202 {
203 keyedCleanupCallbacks.remove(key);
204 }
205
206 bool sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps);
207 bool sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb);
208 bool sanityCheckResourceOwnership(QRhiResource *maybeResource);
209 void updateLayoutDesc(QRhiShaderResourceBindings *srb);
210
211 quint32 pipelineCacheRhiId() const
212 {
213 const quint32 ver = (QT_VERSION_MAJOR << 16) | (QT_VERSION_MINOR << 8) | (QT_VERSION_PATCH);
214 return (quint32(implType) << 24) | ver;
215 }
216
217 void pipelineCreationStart()
218 {
219 pipelineCreationTimer.start();
220 }
221
222 void pipelineCreationEnd()
223 {
224 accumulatedPipelineCreationTime += pipelineCreationTimer.elapsed();
225 }
226
227 qint64 totalPipelineCreationTime() const
228 {
229 return accumulatedPipelineCreationTime;
230 }
231
232 QRhiVertexInputAttribute::Format shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const;
233 quint32 byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const;
234
235 static const QRhiShaderResourceBinding::Data *shaderResourceBindingData(const QRhiShaderResourceBinding &binding)
236 {
237 return &binding.d;
238 }
239
240 static QRhiShaderResourceBinding::Data *shaderResourceBindingData(QRhiShaderResourceBinding &binding)
241 {
242 return &binding.d;
243 }
244
245 static bool sortedBindingLessThan(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
246 {
247 return a.d.binding < b.d.binding;
248 }
249
250 int effectiveSampleCount(int sampleCount) const;
251 QSize clampedSubResourceUploadSize(QSize size, QPoint dstPos, int level, QSize textureSizeAtLevelZero, bool warn = true);
252
253 void runCleanup();
254
255 QRhi *q;
256
257 static const int MAX_SHADER_CACHE_ENTRIES = 128;
258
259 bool debugMarkers = false;
260 int currentFrameSlot = 0; // for vk, mtl, and similar. unused by gl and d3d11.
261 bool inFrame = false;
262
263 QRhiAdapter *requestedRhiAdapter = nullptr;
264
265private:
266 QRhi::Implementation implType;
267 QThread *implThread;
268 QVarLengthArray<QRhiResourceUpdateBatch *, 4> resUpdPool;
269 quint64 resUpdPoolMap = 0;
270 int lastResUpdIdx = -1;
271 QHash<QRhiResource *, bool> resources;
272 QSet<QRhiResource *> pendingDeleteResources;
273 QVarLengthArray<QRhi::CleanupCallback, 4> cleanupCallbacks;
274 QHash<const void *, QRhi::CleanupCallback> keyedCleanupCallbacks;
275 QElapsedTimer pipelineCreationTimer;
276 qint64 accumulatedPipelineCreationTime = 0;
277
278 friend class QRhi;
279 friend class QRhiResourceUpdateBatchPrivate;
280 friend class QRhiBufferData;
281};
282
288
289template<QRhiTargetRectBoundMode boundingMode, typename T, size_t N>
290bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T, N> &r,
291 T *x, T *y, T *w, T *h)
292{
293 // x,y are bottom-left in QRhiScissor and QRhiViewport but top-left in
294 // Vulkan/Metal/D3D. Our input is an OpenGL-style scissor rect where both
295 // negative x or y, and partly or completely out of bounds rects are
296 // allowed. The only thing the input here cannot have is a negative width
297 // or height. We must handle all other input gracefully, clamping to a zero
298 // width or height rect in the worst case, and ensuring the resulting rect
299 // is inside the rendertarget's bounds because some APIs' validation/debug
300 // layers are allergic to out of bounds scissor rects.
301
302 const T outputWidth = outputSize.width();
303 const T outputHeight = outputSize.height();
304 const T inputWidth = r[2];
305 const T inputHeight = r[3];
306
307 if (inputWidth < 0 || inputHeight < 0)
308 return false;
309
310 *x = r[0];
311 *y = outputHeight - (r[1] + inputHeight);
312 *w = inputWidth;
313 *h = inputHeight;
314
315 if (boundingMode == Bounded) {
316 const T widthOffset = *x < 0 ? -*x : 0;
317 const T heightOffset = *y < 0 ? -*y : 0;
318 *w = *x < outputWidth ? qMax<T>(0, inputWidth - widthOffset) : 0;
319 *h = *y < outputHeight ? qMax<T>(0, inputHeight - heightOffset) : 0;
320
321 if (outputWidth > 0)
322 *x = qBound<T>(0, *x, outputWidth - 1);
323 if (outputHeight > 0)
324 *y = qBound<T>(0, *y, outputHeight - 1);
325
326 if (*x + *w > outputWidth)
327 *w = qMax<T>(0, outputWidth - *x);
328 if (*y + *h > outputHeight)
329 *h = qMax<T>(0, outputHeight - *y);
330 }
331 return true;
332}
333
335{
337 QRhiBufferDataPrivate() { } // don't value-initialize smallData
338 int ref = 1;
341 static constexpr quint32 SMALL_DATA_SIZE = 1024;
342 char smallData[SMALL_DATA_SIZE];
343};
344
345// no detach-with-contents, no atomic refcount, no shrink
347{
348public:
349 QRhiBufferData() = default;
351 {
352 if (d && !--d->ref)
353 delete d;
354 }
356 : d(other.d)
357 {
358 if (d)
359 d->ref += 1;
360 }
362 {
363 if (d == other.d)
364 return *this;
365 if (other.d)
366 other.d->ref += 1;
367 if (d && !--d->ref)
368 delete d;
369 d = other.d;
370 return *this;
371 }
372 const char *constData() const
373 {
374 return d ? (d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE ? d->smallData : d->largeData.constData()) : nullptr;
375 }
376 quint32 size() const
377 {
378 return d ? d->size : 0;
379 }
381 {
382 return d ? d->largeData.size() : 0;
383 }
384 void assign(const char *s, quint32 size)
385 {
386 if (!d) {
387 d = new QRhiBufferDataPrivate;
388 } else if (d->ref != 1) {
389 if (QRHI_LOG_RUB().isDebugEnabled())
390 qDebug("[rub] QRhiBufferData %p/%p new backing due to no-copy detach, ref was %d", this, d, d->ref);
391 d->ref -= 1;
392 d = new QRhiBufferDataPrivate;
393 }
394 d->size = size;
395 if (size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) {
396 memcpy(d->smallData, s, size);
397 } else {
398 if (QRHI_LOG_RUB().isDebugEnabled() && largeAlloc() < size)
399 qDebug("[rub] QRhiBufferData %p/%p new large data allocation %u -> %u", this, d, largeAlloc(), size);
400 d->largeData.assign(QByteArrayView(s, size)); // keeps capacity
401 }
402 }
403 void assign(QByteArray data)
404 {
405 if (!d) {
406 d = new QRhiBufferDataPrivate;
407 } else if (d->ref != 1) {
408 if (QRHI_LOG_RUB().isDebugEnabled())
409 qDebug("[rub] QRhiBufferData %p/%p new backing due to no-copy detach, ref was %d", this, d, d->ref);
410 d->ref -= 1;
411 d = new QRhiBufferDataPrivate;
412 }
413 d->size = data.size();
414 if (d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) {
415 memcpy(d->smallData, data.constData(), data.size());
416 } else {
417 d->largeData = std::move(data);
418 }
419 }
420private:
421 QRhiBufferDataPrivate *d = nullptr;
422};
423
425
427{
428public:
429 struct BufferOp {
436 QRhiBuffer *buf;
441
442 static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
443 {
444 BufferOp op = {};
445 changeToDynamicUpdate(&op, buf, offset, size, data);
446 return op;
447 }
448
449 static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
450 {
452 op->buf = buf;
453 op->offset = offset;
454 const int effectiveSize = size ? size : buf->size();
455 op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
456 }
457
458 static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, QByteArray data)
459 {
460 BufferOp op = {};
461 changeToDynamicUpdate(&op, buf, offset, std::move(data));
462 return op;
463 }
464
465 static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
466 {
468 op->buf = buf;
469 op->offset = offset;
470 op->data.assign(std::move(data));
471 }
472
473 static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
474 {
475 BufferOp op = {};
476 changeToStaticUpload(&op, buf, offset, size, data);
477 return op;
478 }
479
480 static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
481 {
483 op->buf = buf;
484 op->offset = offset;
485 const int effectiveSize = size ? size : buf->size();
486 op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
487 }
488
489 static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, QByteArray data)
490 {
491 BufferOp op = {};
492 changeToStaticUpload(&op, buf, offset, std::move(data));
493 return op;
494 }
495
496 static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
497 {
499 op->buf = buf;
500 op->offset = offset;
501 op->data.assign(std::move(data));
502 }
503
504 static BufferOp read(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
505 {
506 BufferOp op = {};
507 op.type = Read;
508 op.buf = buf;
509 op.offset = offset;
510 op.readSize = size;
511 op.result = result;
512 return op;
513 }
514 };
515
516 struct TextureOp {
524 QRhiTexture *dst;
525 // Specifying multiple uploads for a subresource must be supported.
526 // In the backend this can then end up, where applicable, as a
527 // single, batched copy operation with only one set of barriers.
528 // This helps when doing for example glyph cache fills.
531 QRhiTexture *src;
535
536 static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
537 {
538 TextureOp op = {};
539 op.type = Upload;
540 op.dst = tex;
541 int maxLayer = -1;
542 for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it) {
543 if (it->layer() > maxLayer)
544 maxLayer = it->layer();
545 }
546 op.subresDesc.resize(maxLayer + 1);
547 for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it)
548 op.subresDesc[it->layer()][it->level()].append(it->description());
549 return op;
550 }
551
552 static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
553 {
554 TextureOp op = {};
555 op.type = Copy;
556 op.dst = dst;
557 op.src = src;
558 op.desc = desc;
559 return op;
560 }
561
562 static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
563 {
564 TextureOp op = {};
565 op.type = Read;
566 op.rb = rb;
567 op.result = result;
568 return op;
569 }
570
571 static TextureOp genMips(QRhiTexture *tex)
572 {
573 TextureOp op = {};
574 op.type = GenMips;
575 op.dst = tex;
576 return op;
577 }
578 };
579
580 int activeBufferOpCount = 0; // this is the real number of used elements in bufferOps, not bufferOps.count()
581 static const int BUFFER_OPS_STATIC_ALLOC = 64;
583
584 int activeTextureOpCount = 0; // this is the real number of used elements in textureOps, not textureOps.count()
585 static const int TEXTURE_OPS_STATIC_ALLOC = 32;
587
588 QRhiResourceUpdateBatch *q = nullptr;
589 QRhiImplementation *rhi = nullptr;
590 int poolIndex = -1;
591
592 void free();
594 bool hasOptimalCapacity() const;
595 void trimOpLists();
596
597 static QRhiResourceUpdateBatchPrivate *get(QRhiResourceUpdateBatch *b) { return b->d; }
598};
599
600template<typename T>
602{
603 void feed(int binding, T resource) { // binding must be strictly increasing
604 if (curBinding == -1 || binding > curBinding + 1) {
605 finish();
606 curBatch.startBinding = binding;
607 curBatch.resources.clear();
608 curBatch.resources.append(resource);
609 } else {
610 Q_ASSERT(binding == curBinding + 1);
611 curBatch.resources.append(resource);
612 }
613 curBinding = binding;
614 }
615
616 bool finish() {
617 if (!curBatch.resources.isEmpty())
618 batches.append(curBatch);
619 return !batches.isEmpty();
620 }
621
622 void clear() {
623 batches.clear();
624 curBatch.resources.clear();
625 curBinding = -1;
626 }
627
628 struct Batch {
631
632 bool operator==(const Batch &other) const
633 {
634 return startBinding == other.startBinding && resources == other.resources;
635 }
636
637 bool operator!=(const Batch &other) const
638 {
639 return !operator==(other);
640 }
641 };
642
643 // some backends make copies of QRhiBatchedBindings -> implicit sharing and
644 // not having a (possibly wasted) prealloc are beneficial -> use QVector
645 // instead of QVLA
646 QVector<Batch> batches; // sorted by startBinding
647
648 bool operator==(const QRhiBatchedBindings<T> &other) const
649 {
650 return batches == other.batches;
651 }
652
653 bool operator!=(const QRhiBatchedBindings<T> &other) const
654 {
655 return !operator==(other);
656 }
657
658private:
659 Batch curBatch;
660 int curBinding = -1;
661};
662
664{
665public:
666#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
667 using Type = quint64;
668#else
669 using Type = quint32;
670#endif
671 static Type newId();
672};
673
675{
676public:
677 bool isEmpty() const;
678 void reset();
679
680 struct UsageState {
683 int stage;
684 };
685
696
706
707 void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
708 const UsageState &state);
709
720
730
731 void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage,
732 const UsageState &state);
733
740
741 const QVarLengthFlatMap<QRhiBuffer *, Buffer, 12> &buffers() const { return m_buffers; }
742
748
749 const QVarLengthFlatMap<QRhiTexture *, Texture, 12> &textures() const { return m_textures; }
750
751 static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages);
752 static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages);
753
754private:
755 QVarLengthFlatMap<QRhiBuffer *, Buffer, 12> m_buffers;
756 QVarLengthFlatMap<QRhiTexture *, Texture, 12> m_textures;
757};
758
761
762template<typename T, int GROW = 1024>
764{
765public:
767 ~QRhiBackendCommandList() { delete[] v; }
768 inline void reset() { p = 0; }
769 inline bool isEmpty() const { return p == 0; }
770 inline T &get() {
771 if (p == a) {
772 a += GROW;
773 T *nv = new T[a];
774 if (v) {
775 memcpy(nv, v, p * sizeof(T));
776 delete[] v;
777 }
778 v = nv;
779 }
780 return v[p++];
781 }
782 inline void unget() { --p; }
783 inline T *cbegin() const { return v; }
784 inline T *cend() const { return v + p; }
785 inline T *begin() { return v; }
786 inline T *end() { return v + p; }
787private:
789 T *v = nullptr;
790 int a = 0;
791 int p = 0;
792};
793
795{
797 using ResIdList = QVarLengthArray<ResId, 8 * 2 + 1>; // color, resolve, ds
798
799 template<typename TexType, typename RenderBufferType>
800 static void updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst);
801
802 template<typename TexType, typename RenderBufferType>
803 static bool isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList);
804};
805
807{
808 return a.id == b.id && a.generation == b.generation;
809}
810
812{
813 return !(a == b);
814}
815
816template<typename TexType, typename RenderBufferType>
817void QRhiRenderTargetAttachmentTracker::updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst)
818{
819 const bool hasDepthStencil = desc.depthStencilBuffer() || desc.depthTexture();
820 dst->resize(desc.colorAttachmentCount() * 2 + (hasDepthStencil ? 1 : 0));
821 int n = 0;
822 for (auto it = desc.cbeginColorAttachments(), itEnd = desc.cendColorAttachments(); it != itEnd; ++it, ++n) {
823 const QRhiColorAttachment &colorAtt(*it);
824 if (colorAtt.texture()) {
825 TexType *texD = QRHI_RES(TexType, colorAtt.texture());
826 (*dst)[n] = { texD->globalResourceId(), texD->generation };
827 } else if (colorAtt.renderBuffer()) {
828 RenderBufferType *rbD = QRHI_RES(RenderBufferType, colorAtt.renderBuffer());
829 (*dst)[n] = { rbD->globalResourceId(), rbD->generation };
830 } else {
831 (*dst)[n] = { 0, 0 };
832 }
833 ++n;
834 if (colorAtt.resolveTexture()) {
835 TexType *texD = QRHI_RES(TexType, colorAtt.resolveTexture());
836 (*dst)[n] = { texD->globalResourceId(), texD->generation };
837 } else {
838 (*dst)[n] = { 0, 0 };
839 }
840 }
841 if (hasDepthStencil) {
842 if (desc.depthTexture()) {
843 TexType *depthTexD = QRHI_RES(TexType, desc.depthTexture());
844 (*dst)[n] = { depthTexD->globalResourceId(), depthTexD->generation };
845 } else if (desc.depthStencilBuffer()) {
846 RenderBufferType *depthRbD = QRHI_RES(RenderBufferType, desc.depthStencilBuffer());
847 (*dst)[n] = { depthRbD->globalResourceId(), depthRbD->generation };
848 } else {
849 (*dst)[n] = { 0, 0 };
850 }
851 }
852}
853
854template<typename TexType, typename RenderBufferType>
855bool QRhiRenderTargetAttachmentTracker::isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList)
856{
857 // Just as setShaderResources() recognizes if an srb's referenced
858 // resources have been rebuilt (got a create() since the srb's
859 // create()), we should do the same for the textures and renderbuffers
860 // referenced from the rendertarget. It is not uncommon that a texture
861 // or ds buffer gets resized due to following a window size in some
862 // form, which involves a create() on them. It is then nice if the
863 // render target auto-rebuilds in beginPass().
864
865 ResIdList resIdList;
866 updateResIdList<TexType, RenderBufferType>(desc, &resIdList);
867 return resIdList == currentResIdList;
868}
869
870template<typename T>
871inline T *qrhi_objectFromProxyData(QRhiSwapChainProxyData *pd, QWindow *window, QRhi::Implementation impl, uint objectIndex)
872{
873 Q_ASSERT(objectIndex < std::size(pd->reserved));
874 if (!pd->reserved[objectIndex]) // // was not set, no other choice, do it here, whatever thread this is
875 *pd = QRhi::updateSwapChainProxyData(impl, window);
876 return static_cast<T *>(pd->reserved[objectIndex]);
877}
878
879QT_END_NAMESPACE
880
881#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:803
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:814
QRhiBackendCommandList()=default
T * cend() const
Definition qrhi_p.h:784
T * cbegin() const
Definition qrhi_p.h:783
bool isEmpty() const
Definition qrhi_p.h:769
void assign(QByteArray data)
Definition qrhi_p.h:403
QRhiBufferData()=default
void assign(const char *s, quint32 size)
Definition qrhi_p.h:384
quint32 size() const
Definition qrhi_p.h:376
QRhiBufferData(const QRhiBufferData &other)
Definition qrhi_p.h:355
quint32 largeAlloc() const
Definition qrhi_p.h:380
QRhiBufferData & operator=(const QRhiBufferData &other)
Definition qrhi_p.h:361
const char * constData() const
Definition qrhi_p.h:372
static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
Definition qrhi.cpp:12089
const QVarLengthFlatMap< QRhiBuffer *, Buffer, 12 > & buffers() const
Definition qrhi_p.h:741
static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
Definition qrhi.cpp:12070
const QVarLengthFlatMap< QRhiTexture *, Texture, 12 > & textures() const
Definition qrhi_p.h:749
bool isEmpty() const
Definition qrhi.cpp:11979
void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage, const UsageState &state)
Definition qrhi.cpp:11996
void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage, const UsageState &state)
Definition qrhi.cpp:12036
QVarLengthArray< BufferOp, BUFFER_OPS_STATIC_ALLOC > bufferOps
Definition qrhi_p.h:582
QRhiImplementation * rhi
Definition qrhi_p.h:589
QVarLengthArray< TextureOp, TEXTURE_OPS_STATIC_ALLOC > textureOps
Definition qrhi_p.h:586
static const int BUFFER_OPS_STATIC_ALLOC
Definition qrhi_p.h:581
static QRhiResourceUpdateBatchPrivate * get(QRhiResourceUpdateBatch *b)
Definition qrhi_p.h:597
void merge(QRhiResourceUpdateBatchPrivate *other)
Definition qrhi.cpp:10139
QRhiResourceUpdateBatch * q
Definition qrhi_p.h:588
static const int TEXTURE_OPS_STATIC_ALLOC
Definition qrhi_p.h:585
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:8492
static QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a, QRhiPassResourceTracker::BufferStage b)
Definition qrhi.cpp:11990
QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
Definition qrhi.cpp:8239
static bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess access)
Definition qrhi.cpp:12029
static const char * deviceTypeStr(QRhiDriverInfo::DeviceType type)
\variable QRhiDriverInfo::deviceName
Definition qrhi.cpp:9429
static QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a, QRhiPassResourceTracker::TextureStage b)
Definition qrhi.cpp:12023
QRhiTargetRectBoundMode
Definition qrhi_p.h:284
@ UnBounded
Definition qrhi_p.h:285
@ Bounded
Definition qrhi_p.h:286
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:871
bool operator!=(const QRhiRenderTargetAttachmentTracker::ResId &a, const QRhiRenderTargetAttachmentTracker::ResId &b)
Definition qrhi_p.h:811
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:806
bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array< T, N > &r, T *x, T *y, T *w, T *h)
Definition qrhi_p.h:290
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:637
QVector< T > resources
Definition qrhi_p.h:630
bool operator==(const Batch &other) const
Definition qrhi_p.h:632
void feed(int binding, T resource)
Definition qrhi_p.h:603
QVector< Batch > batches
Definition qrhi_p.h:646
bool operator!=(const QRhiBatchedBindings< T > &other) const
Definition qrhi_p.h:653
bool operator==(const QRhiBatchedBindings< T > &other) const
Definition qrhi_p.h:648
char smallData[SMALL_DATA_SIZE]
Definition qrhi_p.h:342
QByteArray largeData
Definition qrhi_p.h:340
static constexpr quint32 SMALL_DATA_SIZE
Definition qrhi_p.h:341
static void updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst)
Definition qrhi_p.h:817
static bool isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList)
Definition qrhi_p.h:855
static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:465
static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:496
static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:480
static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:458
static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:489
static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:473
static BufferOp read(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
Definition qrhi_p.h:504
static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:442
static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:449
QRhiTextureCopyDescription desc
Definition qrhi_p.h:532
static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
Definition qrhi_p.h:552
QVarLengthArray< MipLevelUploadList, 6 > subresDesc
Definition qrhi_p.h:530
static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
Definition qrhi_p.h:536
static TextureOp genMips(QRhiTexture *tex)
Definition qrhi_p.h:571
static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
Definition qrhi_p.h:562
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1557
LimitsType limitsType
Definition qrhi.h:1568
float maxPotentialColorComponentValue
Definition qrhi.h:1576
LuminanceBehavior luminanceBehavior
Definition qrhi.h:1579
float maxColorComponentValue
Definition qrhi.h:1575
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1590
void * reserved[2]
Definition qrhi.h:1591