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