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
246 void runCleanup();
247
248 QRhi *q;
249
250 static const int MAX_SHADER_CACHE_ENTRIES = 128;
251
252 bool debugMarkers = false;
253 int currentFrameSlot = 0; // for vk, mtl, and similar. unused by gl and d3d11.
254 bool inFrame = false;
255
256 QRhiAdapter *requestedRhiAdapter = nullptr;
257
258private:
259 QRhi::Implementation implType;
260 QThread *implThread;
261 QVarLengthArray<QRhiResourceUpdateBatch *, 4> resUpdPool;
262 quint64 resUpdPoolMap = 0;
263 int lastResUpdIdx = -1;
264 QHash<QRhiResource *, bool> resources;
265 QSet<QRhiResource *> pendingDeleteResources;
266 QVarLengthArray<QRhi::CleanupCallback, 4> cleanupCallbacks;
267 QHash<const void *, QRhi::CleanupCallback> keyedCleanupCallbacks;
268 QElapsedTimer pipelineCreationTimer;
269 qint64 accumulatedPipelineCreationTime = 0;
270
271 friend class QRhi;
272 friend class QRhiResourceUpdateBatchPrivate;
273 friend class QRhiBufferData;
274};
275
281
282template<QRhiTargetRectBoundMode boundingMode, typename T, size_t N>
283bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T, N> &r,
284 T *x, T *y, T *w, T *h)
285{
286 // x,y are bottom-left in QRhiScissor and QRhiViewport but top-left in
287 // Vulkan/Metal/D3D. Our input is an OpenGL-style scissor rect where both
288 // negative x or y, and partly or completely out of bounds rects are
289 // allowed. The only thing the input here cannot have is a negative width
290 // or height. We must handle all other input gracefully, clamping to a zero
291 // width or height rect in the worst case, and ensuring the resulting rect
292 // is inside the rendertarget's bounds because some APIs' validation/debug
293 // layers are allergic to out of bounds scissor rects.
294
295 const T outputWidth = outputSize.width();
296 const T outputHeight = outputSize.height();
297 const T inputWidth = r[2];
298 const T inputHeight = r[3];
299
300 if (inputWidth < 0 || inputHeight < 0)
301 return false;
302
303 *x = r[0];
304 *y = outputHeight - (r[1] + inputHeight);
305 *w = inputWidth;
306 *h = inputHeight;
307
308 if (boundingMode == Bounded) {
309 const T widthOffset = *x < 0 ? -*x : 0;
310 const T heightOffset = *y < 0 ? -*y : 0;
311 *w = *x < outputWidth ? qMax<T>(0, inputWidth - widthOffset) : 0;
312 *h = *y < outputHeight ? qMax<T>(0, inputHeight - heightOffset) : 0;
313
314 if (outputWidth > 0)
315 *x = qBound<T>(0, *x, outputWidth - 1);
316 if (outputHeight > 0)
317 *y = qBound<T>(0, *y, outputHeight - 1);
318
319 if (*x + *w > outputWidth)
320 *w = qMax<T>(0, outputWidth - *x);
321 if (*y + *h > outputHeight)
322 *h = qMax<T>(0, outputHeight - *y);
323 }
324 return true;
325}
326
328{
330 QRhiBufferDataPrivate() { } // don't value-initialize smallData
331 int ref = 1;
334 static constexpr quint32 SMALL_DATA_SIZE = 1024;
335 char smallData[SMALL_DATA_SIZE];
336};
337
338// no detach-with-contents, no atomic refcount, no shrink
340{
341public:
342 QRhiBufferData() = default;
344 {
345 if (d && !--d->ref)
346 delete d;
347 }
349 : d(other.d)
350 {
351 if (d)
352 d->ref += 1;
353 }
355 {
356 if (d == other.d)
357 return *this;
358 if (other.d)
359 other.d->ref += 1;
360 if (d && !--d->ref)
361 delete d;
362 d = other.d;
363 return *this;
364 }
365 const char *constData() const
366 {
367 return d ? (d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE ? d->smallData : d->largeData.constData()) : nullptr;
368 }
369 quint32 size() const
370 {
371 return d ? d->size : 0;
372 }
374 {
375 return d ? d->largeData.size() : 0;
376 }
377 void assign(const char *s, quint32 size)
378 {
379 if (!d) {
380 d = new QRhiBufferDataPrivate;
381 } else if (d->ref != 1) {
382 if (QRHI_LOG_RUB().isDebugEnabled())
383 qDebug("[rub] QRhiBufferData %p/%p new backing due to no-copy detach, ref was %d", this, d, d->ref);
384 d->ref -= 1;
385 d = new QRhiBufferDataPrivate;
386 }
387 d->size = size;
388 if (size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) {
389 memcpy(d->smallData, s, size);
390 } else {
391 if (QRHI_LOG_RUB().isDebugEnabled() && largeAlloc() < size)
392 qDebug("[rub] QRhiBufferData %p/%p new large data allocation %u -> %u", this, d, largeAlloc(), size);
393 d->largeData.assign(QByteArrayView(s, size)); // keeps capacity
394 }
395 }
396 void assign(QByteArray data)
397 {
398 if (!d) {
399 d = new QRhiBufferDataPrivate;
400 } else if (d->ref != 1) {
401 if (QRHI_LOG_RUB().isDebugEnabled())
402 qDebug("[rub] QRhiBufferData %p/%p new backing due to no-copy detach, ref was %d", this, d, d->ref);
403 d->ref -= 1;
404 d = new QRhiBufferDataPrivate;
405 }
406 d->size = data.size();
407 if (d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) {
408 memcpy(d->smallData, data.constData(), data.size());
409 } else {
410 d->largeData = std::move(data);
411 }
412 }
413private:
414 QRhiBufferDataPrivate *d = nullptr;
415};
416
418
420{
421public:
422 struct BufferOp {
429 QRhiBuffer *buf;
434
435 static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
436 {
437 BufferOp op = {};
438 changeToDynamicUpdate(&op, buf, offset, size, data);
439 return op;
440 }
441
442 static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
443 {
445 op->buf = buf;
446 op->offset = offset;
447 const int effectiveSize = size ? size : buf->size();
448 op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
449 }
450
451 static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, QByteArray data)
452 {
453 BufferOp op = {};
454 changeToDynamicUpdate(&op, buf, offset, std::move(data));
455 return op;
456 }
457
458 static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
459 {
461 op->buf = buf;
462 op->offset = offset;
463 op->data.assign(std::move(data));
464 }
465
466 static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
467 {
468 BufferOp op = {};
469 changeToStaticUpload(&op, buf, offset, size, data);
470 return op;
471 }
472
473 static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
474 {
476 op->buf = buf;
477 op->offset = offset;
478 const int effectiveSize = size ? size : buf->size();
479 op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
480 }
481
482 static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, QByteArray data)
483 {
484 BufferOp op = {};
485 changeToStaticUpload(&op, buf, offset, std::move(data));
486 return op;
487 }
488
489 static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
490 {
492 op->buf = buf;
493 op->offset = offset;
494 op->data.assign(std::move(data));
495 }
496
497 static BufferOp read(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
498 {
499 BufferOp op = {};
500 op.type = Read;
501 op.buf = buf;
502 op.offset = offset;
503 op.readSize = size;
504 op.result = result;
505 return op;
506 }
507 };
508
509 struct TextureOp {
517 QRhiTexture *dst;
518 // Specifying multiple uploads for a subresource must be supported.
519 // In the backend this can then end up, where applicable, as a
520 // single, batched copy operation with only one set of barriers.
521 // This helps when doing for example glyph cache fills.
524 QRhiTexture *src;
528
529 static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
530 {
531 TextureOp op = {};
532 op.type = Upload;
533 op.dst = tex;
534 int maxLayer = -1;
535 for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it) {
536 if (it->layer() > maxLayer)
537 maxLayer = it->layer();
538 }
539 op.subresDesc.resize(maxLayer + 1);
540 for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it)
541 op.subresDesc[it->layer()][it->level()].append(it->description());
542 return op;
543 }
544
545 static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
546 {
547 TextureOp op = {};
548 op.type = Copy;
549 op.dst = dst;
550 op.src = src;
551 op.desc = desc;
552 return op;
553 }
554
555 static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
556 {
557 TextureOp op = {};
558 op.type = Read;
559 op.rb = rb;
560 op.result = result;
561 return op;
562 }
563
564 static TextureOp genMips(QRhiTexture *tex)
565 {
566 TextureOp op = {};
567 op.type = GenMips;
568 op.dst = tex;
569 return op;
570 }
571 };
572
573 int activeBufferOpCount = 0; // this is the real number of used elements in bufferOps, not bufferOps.count()
574 static const int BUFFER_OPS_STATIC_ALLOC = 64;
576
577 int activeTextureOpCount = 0; // this is the real number of used elements in textureOps, not textureOps.count()
578 static const int TEXTURE_OPS_STATIC_ALLOC = 32;
580
581 QRhiResourceUpdateBatch *q = nullptr;
582 QRhiImplementation *rhi = nullptr;
583 int poolIndex = -1;
584
585 void free();
587 bool hasOptimalCapacity() const;
588 void trimOpLists();
589
590 static QRhiResourceUpdateBatchPrivate *get(QRhiResourceUpdateBatch *b) { return b->d; }
591};
592
593template<typename T>
595{
596 void feed(int binding, T resource) { // binding must be strictly increasing
597 if (curBinding == -1 || binding > curBinding + 1) {
598 finish();
599 curBatch.startBinding = binding;
600 curBatch.resources.clear();
601 curBatch.resources.append(resource);
602 } else {
603 Q_ASSERT(binding == curBinding + 1);
604 curBatch.resources.append(resource);
605 }
606 curBinding = binding;
607 }
608
609 bool finish() {
610 if (!curBatch.resources.isEmpty())
611 batches.append(curBatch);
612 return !batches.isEmpty();
613 }
614
615 void clear() {
616 batches.clear();
617 curBatch.resources.clear();
618 curBinding = -1;
619 }
620
621 struct Batch {
624
625 bool operator==(const Batch &other) const
626 {
627 return startBinding == other.startBinding && resources == other.resources;
628 }
629
630 bool operator!=(const Batch &other) const
631 {
632 return !operator==(other);
633 }
634 };
635
636 QVarLengthArray<Batch, 4> batches; // sorted by startBinding
637
638 bool operator==(const QRhiBatchedBindings<T> &other) const
639 {
640 return batches == other.batches;
641 }
642
643 bool operator!=(const QRhiBatchedBindings<T> &other) const
644 {
645 return !operator==(other);
646 }
647
648private:
649 Batch curBatch;
650 int curBinding = -1;
651};
652
654{
655public:
656#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
657 using Type = quint64;
658#else
659 using Type = quint32;
660#endif
661 static Type newId();
662};
663
665{
666public:
667 bool isEmpty() const;
668 void reset();
669
670 struct UsageState {
673 int stage;
674 };
675
685
694
695 void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
696 const UsageState &state);
697
708
718
719 void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage,
720 const UsageState &state);
721
728
729 const QVarLengthFlatMap<QRhiBuffer *, Buffer, 12> &buffers() const { return m_buffers; }
730
736
737 const QVarLengthFlatMap<QRhiTexture *, Texture, 12> &textures() const { return m_textures; }
738
739 static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages);
740 static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages);
741
742private:
743 QVarLengthFlatMap<QRhiBuffer *, Buffer, 12> m_buffers;
744 QVarLengthFlatMap<QRhiTexture *, Texture, 12> m_textures;
745};
746
749
750template<typename T, int GROW = 1024>
752{
753public:
755 ~QRhiBackendCommandList() { delete[] v; }
756 inline void reset() { p = 0; }
757 inline bool isEmpty() const { return p == 0; }
758 inline T &get() {
759 if (p == a) {
760 a += GROW;
761 T *nv = new T[a];
762 if (v) {
763 memcpy(nv, v, p * sizeof(T));
764 delete[] v;
765 }
766 v = nv;
767 }
768 return v[p++];
769 }
770 inline void unget() { --p; }
771 inline T *cbegin() const { return v; }
772 inline T *cend() const { return v + p; }
773 inline T *begin() { return v; }
774 inline T *end() { return v + p; }
775private:
777 T *v = nullptr;
778 int a = 0;
779 int p = 0;
780};
781
783{
785 using ResIdList = QVarLengthArray<ResId, 8 * 2 + 1>; // color, resolve, ds
786
787 template<typename TexType, typename RenderBufferType>
788 static void updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst);
789
790 template<typename TexType, typename RenderBufferType>
791 static bool isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList);
792};
793
795{
796 return a.id == b.id && a.generation == b.generation;
797}
798
800{
801 return !(a == b);
802}
803
804template<typename TexType, typename RenderBufferType>
805void QRhiRenderTargetAttachmentTracker::updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst)
806{
807 const bool hasDepthStencil = desc.depthStencilBuffer() || desc.depthTexture();
808 dst->resize(desc.colorAttachmentCount() * 2 + (hasDepthStencil ? 1 : 0));
809 int n = 0;
810 for (auto it = desc.cbeginColorAttachments(), itEnd = desc.cendColorAttachments(); it != itEnd; ++it, ++n) {
811 const QRhiColorAttachment &colorAtt(*it);
812 if (colorAtt.texture()) {
813 TexType *texD = QRHI_RES(TexType, colorAtt.texture());
814 (*dst)[n] = { texD->globalResourceId(), texD->generation };
815 } else if (colorAtt.renderBuffer()) {
816 RenderBufferType *rbD = QRHI_RES(RenderBufferType, colorAtt.renderBuffer());
817 (*dst)[n] = { rbD->globalResourceId(), rbD->generation };
818 } else {
819 (*dst)[n] = { 0, 0 };
820 }
821 ++n;
822 if (colorAtt.resolveTexture()) {
823 TexType *texD = QRHI_RES(TexType, colorAtt.resolveTexture());
824 (*dst)[n] = { texD->globalResourceId(), texD->generation };
825 } else {
826 (*dst)[n] = { 0, 0 };
827 }
828 }
829 if (hasDepthStencil) {
830 if (desc.depthTexture()) {
831 TexType *depthTexD = QRHI_RES(TexType, desc.depthTexture());
832 (*dst)[n] = { depthTexD->globalResourceId(), depthTexD->generation };
833 } else if (desc.depthStencilBuffer()) {
834 RenderBufferType *depthRbD = QRHI_RES(RenderBufferType, desc.depthStencilBuffer());
835 (*dst)[n] = { depthRbD->globalResourceId(), depthRbD->generation };
836 } else {
837 (*dst)[n] = { 0, 0 };
838 }
839 }
840}
841
842template<typename TexType, typename RenderBufferType>
843bool QRhiRenderTargetAttachmentTracker::isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList)
844{
845 // Just as setShaderResources() recognizes if an srb's referenced
846 // resources have been rebuilt (got a create() since the srb's
847 // create()), we should do the same for the textures and renderbuffers
848 // referenced from the rendertarget. It is not uncommon that a texture
849 // or ds buffer gets resized due to following a window size in some
850 // form, which involves a create() on them. It is then nice if the
851 // render target auto-rebuilds in beginPass().
852
853 ResIdList resIdList;
854 updateResIdList<TexType, RenderBufferType>(desc, &resIdList);
855 return resIdList == currentResIdList;
856}
857
858template<typename T>
859inline T *qrhi_objectFromProxyData(QRhiSwapChainProxyData *pd, QWindow *window, QRhi::Implementation impl, uint objectIndex)
860{
861 Q_ASSERT(objectIndex < std::size(pd->reserved));
862 if (!pd->reserved[objectIndex]) // // was not set, no other choice, do it here, whatever thread this is
863 *pd = QRhi::updateSwapChainProxyData(impl, window);
864 return static_cast<T *>(pd->reserved[objectIndex]);
865}
866
867QT_END_NAMESPACE
868
869#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:801
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:812
QRhiBackendCommandList()=default
T * cend() const
Definition qrhi_p.h:772
T * cbegin() const
Definition qrhi_p.h:771
bool isEmpty() const
Definition qrhi_p.h:757
void assign(QByteArray data)
Definition qrhi_p.h:396
QRhiBufferData()=default
void assign(const char *s, quint32 size)
Definition qrhi_p.h:377
quint32 size() const
Definition qrhi_p.h:369
QRhiBufferData(const QRhiBufferData &other)
Definition qrhi_p.h:348
quint32 largeAlloc() const
Definition qrhi_p.h:373
QRhiBufferData & operator=(const QRhiBufferData &other)
Definition qrhi_p.h:354
const char * constData() const
Definition qrhi_p.h:365
static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
Definition qrhi.cpp:11850
const QVarLengthFlatMap< QRhiBuffer *, Buffer, 12 > & buffers() const
Definition qrhi_p.h:729
static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
Definition qrhi.cpp:11831
const QVarLengthFlatMap< QRhiTexture *, Texture, 12 > & textures() const
Definition qrhi_p.h:737
bool isEmpty() const
Definition qrhi.cpp:11740
void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage, const UsageState &state)
Definition qrhi.cpp:11757
void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage, const UsageState &state)
Definition qrhi.cpp:11797
QVarLengthArray< BufferOp, BUFFER_OPS_STATIC_ALLOC > bufferOps
Definition qrhi_p.h:575
QRhiImplementation * rhi
Definition qrhi_p.h:582
QVarLengthArray< TextureOp, TEXTURE_OPS_STATIC_ALLOC > textureOps
Definition qrhi_p.h:579
static const int BUFFER_OPS_STATIC_ALLOC
Definition qrhi_p.h:574
static QRhiResourceUpdateBatchPrivate * get(QRhiResourceUpdateBatch *b)
Definition qrhi_p.h:590
void merge(QRhiResourceUpdateBatchPrivate *other)
Definition qrhi.cpp:9985
QRhiResourceUpdateBatch * q
Definition qrhi_p.h:581
static const int TEXTURE_OPS_STATIC_ALLOC
Definition qrhi_p.h:578
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
static const char * resourceTypeStr(const QRhiResource *res)
Definition qrhi.cpp:8356
static QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a, QRhiPassResourceTracker::BufferStage b)
Definition qrhi.cpp:11751
QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
Definition qrhi.cpp:8171
static bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess access)
Definition qrhi.cpp:11790
static const char * deviceTypeStr(QRhiDriverInfo::DeviceType type)
\variable QRhiDriverInfo::deviceName
Definition qrhi.cpp:9275
static QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a, QRhiPassResourceTracker::TextureStage b)
Definition qrhi.cpp:11784
QRhiTargetRectBoundMode
Definition qrhi_p.h:277
@ UnBounded
Definition qrhi_p.h:278
@ Bounded
Definition qrhi_p.h:279
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:859
bool operator!=(const QRhiRenderTargetAttachmentTracker::ResId &a, const QRhiRenderTargetAttachmentTracker::ResId &b)
Definition qrhi_p.h:799
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:794
bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array< T, N > &r, T *x, T *y, T *w, T *h)
Definition qrhi_p.h:283
constexpr size_t qHash(const QSize &s, size_t seed=0) noexcept
Definition qsize.h:191
bool operator!=(const Batch &other) const
Definition qrhi_p.h:630
bool operator==(const Batch &other) const
Definition qrhi_p.h:625
QVarLengthArray< T, 4 > resources
Definition qrhi_p.h:623
void feed(int binding, T resource)
Definition qrhi_p.h:596
QVarLengthArray< Batch, 4 > batches
Definition qrhi_p.h:636
bool operator!=(const QRhiBatchedBindings< T > &other) const
Definition qrhi_p.h:643
bool operator==(const QRhiBatchedBindings< T > &other) const
Definition qrhi_p.h:638
char smallData[SMALL_DATA_SIZE]
Definition qrhi_p.h:335
QByteArray largeData
Definition qrhi_p.h:333
static constexpr quint32 SMALL_DATA_SIZE
Definition qrhi_p.h:334
static void updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst)
Definition qrhi_p.h:805
static bool isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList)
Definition qrhi_p.h:843
static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:458
static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:489
static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:473
static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:451
static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, QByteArray data)
Definition qrhi_p.h:482
static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:466
static BufferOp read(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
Definition qrhi_p.h:497
static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:435
static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Definition qrhi_p.h:442
QRhiTextureCopyDescription desc
Definition qrhi_p.h:525
static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
Definition qrhi_p.h:545
QVarLengthArray< MipLevelUploadList, 6 > subresDesc
Definition qrhi_p.h:523
static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
Definition qrhi_p.h:529
static TextureOp genMips(QRhiTexture *tex)
Definition qrhi_p.h:564
static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
Definition qrhi_p.h:555
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1551
LimitsType limitsType
Definition qrhi.h:1562
float maxPotentialColorComponentValue
Definition qrhi.h:1570
LuminanceBehavior luminanceBehavior
Definition qrhi.h:1573
float maxColorComponentValue
Definition qrhi.h:1569
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1584
void * reserved[2]
Definition qrhi.h:1585