summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi/qrhi_p_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/rhi/qrhi_p_p.h')
-rw-r--r--src/gui/rhi/qrhi_p_p.h241
1 files changed, 110 insertions, 131 deletions
diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h
index 0914cf268b..baffe28202 100644
--- a/src/gui/rhi/qrhi_p_p.h
+++ b/src/gui/rhi/qrhi_p_p.h
@@ -156,7 +156,9 @@ public:
virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0;
virtual const QRhiNativeHandles *nativeHandles() = 0;
virtual void sendVMemStatsToProfiler() = 0;
- virtual void makeThreadLocalNativeContextCurrent() = 0;
+ virtual bool makeThreadLocalNativeContextCurrent() = 0;
+ virtual void releaseCachedResources() = 0;
+ virtual bool isDeviceLost() const = 0;
bool isCompressedFormat(QRhiTexture::Format format) const;
void compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
@@ -203,8 +205,12 @@ public:
cleanupCallbacks.append(callback);
}
+ bool sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps);
+
QRhi *q;
+ static const int MAX_SHADER_CACHE_ENTRIES = 128;
+
protected:
bool debugMarkers = false;
int currentFrameSlot = 0; // for vk, mtl, and similar. unused by gl and d3d11.
@@ -214,7 +220,7 @@ private:
QRhi::Implementation implType;
QThread *implThread;
QRhiProfiler profiler;
- QVector<QRhiResourceUpdateBatch *> resUpdPool;
+ QVarLengthArray<QRhiResourceUpdateBatch *, 4> resUpdPool;
QBitArray resUpdPoolMap;
QSet<QRhiResource *> resources;
QSet<QRhiResource *> pendingReleaseAndDestroyResources;
@@ -229,27 +235,37 @@ bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T,
T *x, T *y, T *w, T *h)
{
// x,y are bottom-left in QRhiScissor and QRhiViewport but top-left in
- // Vulkan/Metal/D3D. We also need proper clamping since some
- // validation/debug layers are allergic to out of bounds scissor or
- // viewport rects.
+ // Vulkan/Metal/D3D. Our input is an OpenGL-style scissor rect where both
+ // negative x or y, and partly or completely out of bounds rects are
+ // allowed. The only thing the input here cannot have is a negative width
+ // or height. We must handle all other input gracefully, clamping to a zero
+ // width or height rect in the worst case, and ensuring the resulting rect
+ // is inside the rendertarget's bounds because some APIs' validation/debug
+ // layers are allergic to out of bounds scissor or viewport rects.
const T outputWidth = outputSize.width();
const T outputHeight = outputSize.height();
const T inputWidth = r[2];
const T inputHeight = r[3];
- *x = qMax<T>(0, r[0]);
- *y = qMax<T>(0, outputHeight - (r[1] + inputHeight));
- *w = inputWidth;
- *h = inputHeight;
-
- if (*x >= outputWidth || *y >= outputHeight)
+ if (inputWidth < 0 || inputHeight < 0)
return false;
+ *x = r[0];
+ *y = outputHeight - (r[1] + inputHeight);
+
+ const T widthOffset = *x < 0 ? -*x : 0;
+ const T heightOffset = *y < 0 ? -*y : 0;
+
+ *x = qBound<T>(0, *x, outputWidth - 1);
+ *y = qBound<T>(0, *y, outputHeight - 1);
+ *w = qMax<T>(0, inputWidth - widthOffset);
+ *h = qMax<T>(0, inputHeight - heightOffset);
+
if (*x + *w > outputWidth)
- *w = outputWidth - *x;
+ *w = qMax<T>(0, outputWidth - *x - 1);
if (*y + *h > outputHeight)
- *h = outputHeight - *y;
+ *h = qMax<T>(0, outputHeight - *y - 1);
return true;
}
@@ -257,26 +273,49 @@ bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T,
class QRhiResourceUpdateBatchPrivate
{
public:
- struct DynamicBufferUpdate {
- DynamicBufferUpdate() { }
- DynamicBufferUpdate(QRhiBuffer *buf_, int offset_, int size_, const void *data_)
- : buf(buf_), offset(offset_), data(reinterpret_cast<const char *>(data_), size_)
- { }
-
- QRhiBuffer *buf = nullptr;
- int offset = 0;
+ struct BufferOp {
+ enum Type {
+ DynamicUpdate,
+ StaticUpload,
+ Read
+ };
+ Type type;
+ QRhiBuffer *buf;
+ int offset;
QByteArray data;
- };
+ int readSize;
+ QRhiBufferReadbackResult *result;
- struct StaticBufferUpload {
- StaticBufferUpload() { }
- StaticBufferUpload(QRhiBuffer *buf_, int offset_, int size_, const void *data_)
- : buf(buf_), offset(offset_), data(reinterpret_cast<const char *>(data_), size_ ? size_ : buf_->size())
- { }
+ static BufferOp dynamicUpdate(QRhiBuffer *buf, int offset, int size, const void *data)
+ {
+ BufferOp op;
+ op.type = DynamicUpdate;
+ op.buf = buf;
+ op.offset = offset;
+ op.data = QByteArray(reinterpret_cast<const char *>(data), size ? size : buf->size());
+ return op;
+ }
- QRhiBuffer *buf = nullptr;
- int offset = 0;
- QByteArray data;
+ static BufferOp staticUpload(QRhiBuffer *buf, int offset, int size, const void *data)
+ {
+ BufferOp op;
+ op.type = StaticUpload;
+ op.buf = buf;
+ op.offset = offset;
+ op.data = QByteArray(reinterpret_cast<const char *>(data), size ? size : buf->size());
+ return op;
+ }
+
+ static BufferOp read(QRhiBuffer *buf, int offset, int size, QRhiBufferReadbackResult *result)
+ {
+ BufferOp op;
+ op.type = Read;
+ op.buf = buf;
+ op.offset = offset;
+ op.readSize = size;
+ op.result = result;
+ return op;
+ }
};
struct TextureOp {
@@ -284,74 +323,62 @@ public:
Upload,
Copy,
Read,
- MipGen
+ GenMips
};
Type type;
- struct SUpload {
- QRhiTexture *tex = nullptr;
- // Specifying multiple uploads for a subresource must be supported.
- // In the backend this can then end up, where applicable, as a
- // single, batched copy operation with only one set of barriers.
- // This helps when doing for example glyph cache fills.
- QVector<QRhiTextureSubresourceUploadDescription> subresDesc[QRhi::MAX_LAYERS][QRhi::MAX_LEVELS];
- } upload;
- struct SCopy {
- QRhiTexture *dst = nullptr;
- QRhiTexture *src = nullptr;
- QRhiTextureCopyDescription desc;
- } copy;
- struct SRead {
- QRhiReadbackDescription rb;
- QRhiReadbackResult *result;
- } read;
- struct SMipGen {
- QRhiTexture *tex = nullptr;
- int layer = 0;
- } mipgen;
-
- static TextureOp textureUpload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
+ QRhiTexture *dst;
+ // Specifying multiple uploads for a subresource must be supported.
+ // In the backend this can then end up, where applicable, as a
+ // single, batched copy operation with only one set of barriers.
+ // This helps when doing for example glyph cache fills.
+ QVector<QRhiTextureSubresourceUploadDescription> subresDesc[QRhi::MAX_LAYERS][QRhi::MAX_LEVELS];
+ QRhiTexture *src;
+ QRhiTextureCopyDescription desc;
+ QRhiReadbackDescription rb;
+ QRhiReadbackResult *result;
+ int layer;
+
+ static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
{
TextureOp op;
op.type = Upload;
- op.upload.tex = tex;
- const QVector<QRhiTextureUploadEntry> &entries(desc.entries());
- for (const QRhiTextureUploadEntry &entry : entries)
- op.upload.subresDesc[entry.layer()][entry.level()].append(entry.description());
+ op.dst = tex;
+ for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it)
+ op.subresDesc[it->layer()][it->level()].append(it->description());
return op;
}
- static TextureOp textureCopy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
+ static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
{
TextureOp op;
op.type = Copy;
- op.copy.dst = dst;
- op.copy.src = src;
- op.copy.desc = desc;
+ op.dst = dst;
+ op.src = src;
+ op.desc = desc;
return op;
}
- static TextureOp textureRead(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
+ static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
{
TextureOp op;
op.type = Read;
- op.read.rb = rb;
- op.read.result = result;
+ op.rb = rb;
+ op.result = result;
return op;
}
- static TextureOp textureMipGen(QRhiTexture *tex, int layer)
+ static TextureOp genMips(QRhiTexture *tex, int layer)
{
TextureOp op;
- op.type = MipGen;
- op.mipgen.tex = tex;
- op.mipgen.layer = layer;
+ op.type = GenMips;
+ op.dst = tex;
+ op.layer = layer;
return op;
}
};
- QVector<DynamicBufferUpdate> dynamicBufferUpdates;
- QVector<StaticBufferUpload> staticBufferUploads;
- QVector<TextureOp> textureOps;
+ QVarLengthArray<BufferOp, 1024> bufferOps;
+ QVarLengthArray<TextureOp, 256> textureOps;
QRhiResourceUpdateBatch *q = nullptr;
QRhiImplementation *rhi = nullptr;
@@ -363,61 +390,9 @@ public:
static QRhiResourceUpdateBatchPrivate *get(QRhiResourceUpdateBatch *b) { return b->d; }
};
-Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate, Q_MOVABLE_TYPE);
-Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::StaticBufferUpload, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::BufferOp, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::TextureOp, Q_MOVABLE_TYPE);
-class Q_GUI_EXPORT QRhiShaderResourceBindingPrivate
-{
-public:
- QRhiShaderResourceBindingPrivate()
- : ref(1)
- {
- }
-
- QRhiShaderResourceBindingPrivate(const QRhiShaderResourceBindingPrivate *other)
- : ref(1),
- binding(other->binding),
- stage(other->stage),
- type(other->type),
- u(other->u)
- {
- }
-
- static QRhiShaderResourceBindingPrivate *get(QRhiShaderResourceBinding *s) { return s->d; }
- static const QRhiShaderResourceBindingPrivate *get(const QRhiShaderResourceBinding *s) { return s->d; }
-
- QAtomicInt ref;
- int binding;
- QRhiShaderResourceBinding::StageFlags stage;
- QRhiShaderResourceBinding::Type type;
- struct UniformBufferData {
- QRhiBuffer *buf;
- int offset;
- int maybeSize;
- bool hasDynamicOffset;
- };
- struct SampledTextureData {
- QRhiTexture *tex;
- QRhiSampler *sampler;
- };
- struct StorageImageData {
- QRhiTexture *tex;
- int level;
- };
- struct StorageBufferData {
- QRhiBuffer *buf;
- int offset;
- int maybeSize;
- };
- union {
- UniformBufferData ubuf;
- SampledTextureData stex;
- StorageImageData simage;
- StorageBufferData sbuf;
- } u;
-};
-
template<typename T>
struct QRhiBatchedBindings
{
@@ -540,28 +515,32 @@ public:
const UsageState &state);
struct Buffer {
- QRhiBuffer *buf;
int slot;
BufferAccess access;
BufferStage stage;
UsageState stateAtPassBegin;
};
- const QVector<Buffer> *buffers() const { return &m_buffers; }
+
+ using BufferIterator = QHash<QRhiBuffer *, Buffer>::const_iterator;
+ BufferIterator cbeginBuffers() const { return m_buffers.cbegin(); }
+ BufferIterator cendBuffers() const { return m_buffers.cend(); }
struct Texture {
- QRhiTexture *tex;
TextureAccess access;
TextureStage stage;
UsageState stateAtPassBegin;
};
- const QVector<Texture> *textures() const { return &m_textures; }
+
+ using TextureIterator = QHash<QRhiTexture *, Texture>::const_iterator;
+ TextureIterator cbeginTextures() const { return m_textures.cbegin(); }
+ TextureIterator cendTextures() const { return m_textures.cend(); }
static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages);
static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages);
private:
- QVector<Buffer> m_buffers;
- QVector<Texture> m_textures;
+ QHash<QRhiBuffer *, Buffer> m_buffers;
+ QHash<QRhiTexture *, Texture> m_textures;
};
Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Buffer, Q_MOVABLE_TYPE);