qrhi_p.h 14.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt RHI module
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#ifndef QRHI_P_H
#define QRHI_P_H

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#include "qtrhiglobal_p.h"
#include "qrhi.h"
46
#include "qrhiprofiler_p.h"
47
#include <QBitArray>
48
#include <QAtomicInt>
Laszlo Agocs's avatar
Laszlo Agocs committed
49
#include <QAtomicInteger>
50 51 52 53

QT_BEGIN_NAMESPACE

#define QRHI_RES(t, x) static_cast<t *>(x)
Laszlo Agocs's avatar
Laszlo Agocs committed
54 55
#define QRHI_RES_RHI(t) t *rhiD = static_cast<t *>(m_rhi)
#define QRHI_PROF QRhiProfilerPrivate *rhiP = m_rhi->profilerPrivateOrNull()
56
#define QRHI_PROF_F(f) for (bool qrhip_enabled = rhiP != nullptr; qrhip_enabled; qrhip_enabled = false) rhiP->f
57 58 59 60 61 62

class QRhiImplementation
{
public:
    virtual ~QRhiImplementation();

63
    virtual bool create(QRhi::Flags flags) = 0;
64 65
    virtual void destroy() = 0;

66 67 68 69 70 71 72 73
    virtual QRhiGraphicsPipeline *createGraphicsPipeline() = 0;
    virtual QRhiShaderResourceBindings *createShaderResourceBindings() = 0;
    virtual QRhiBuffer *createBuffer(QRhiBuffer::Type type,
                                     QRhiBuffer::UsageFlags usage,
                                     int size) = 0;
    virtual QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
                                                 const QSize &pixelSize,
                                                 int sampleCount,
Laszlo Agocs's avatar
Laszlo Agocs committed
74
                                                 QRhiRenderBuffer::Flags flags) = 0;
75 76
    virtual QRhiTexture *createTexture(QRhiTexture::Format format,
                                       const QSize &pixelSize,
Laszlo Agocs's avatar
Laszlo Agocs committed
77
                                       int sampleCount,
78 79 80 81 82 83 84 85 86
                                       QRhiTexture::Flags flags) = 0;
    virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
                                       QRhiSampler::Filter mipmapMode,
                                       QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) = 0;

    virtual QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
                                                               QRhiTextureRenderTarget::Flags flags) = 0;

    virtual QRhiSwapChain *createSwapChain() = 0;
87 88
    virtual QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) = 0;
    virtual QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) = 0;
89
    virtual QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) = 0;
90 91
    virtual QRhi::FrameOpResult endOffscreenFrame() = 0;
    virtual QRhi::FrameOpResult finish() = 0;
92

93 94 95 96
    virtual void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;

    virtual void beginPass(QRhiCommandBuffer *cb,
                           QRhiRenderTarget *rt,
97 98 99
                           const QRhiColorClearValue &colorClearValue,
                           const QRhiDepthStencilClearValue &depthStencilClearValue,
                           QRhiResourceUpdateBatch *resourceUpdates) = 0;
100
    virtual void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
101 102

    virtual void setGraphicsPipeline(QRhiCommandBuffer *cb,
103 104 105 106 107
                                     QRhiGraphicsPipeline *ps) = 0;

    virtual void setShaderResources(QRhiCommandBuffer *cb,
                                    QRhiShaderResourceBindings *srb,
                                    const QVector<QRhiCommandBuffer::DynamicOffset> &dynamicOffsets) = 0;
108 109

    virtual void setVertexInput(QRhiCommandBuffer *cb,
110
                                int startBinding, const QVector<QRhiCommandBuffer::VertexInput> &bindings,
111
                                QRhiBuffer *indexBuf, quint32 indexOffset,
112
                                QRhiCommandBuffer::IndexFormat indexFormat) = 0;
113 114 115 116 117 118 119 120 121 122 123 124

    virtual void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) = 0;
    virtual void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) = 0;
    virtual void setBlendConstants(QRhiCommandBuffer *cb, const QVector4D &c) = 0;
    virtual void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) = 0;

    virtual void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
                      quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) = 0;
    virtual void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
                             quint32 instanceCount, quint32 firstIndex,
                             qint32 vertexOffset, quint32 firstInstance) = 0;

125 126 127 128
    virtual void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) = 0;
    virtual void debugMarkEnd(QRhiCommandBuffer *cb) = 0;
    virtual void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) = 0;

129 130 131
    virtual QVector<int> supportedSampleCounts() const = 0;
    virtual int ubufAlignment() const = 0;
    virtual bool isYUpInFramebuffer() const = 0;
Laszlo Agocs's avatar
Laszlo Agocs committed
132
    virtual bool isYUpInNDC() const = 0;
133
    virtual QMatrix4x4 clipSpaceCorrMatrix() const = 0;
134
    virtual bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const = 0;
135
    virtual bool isFeatureSupported(QRhi::Feature feature) const = 0;
Laszlo Agocs's avatar
Laszlo Agocs committed
136
    virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0;
137
    virtual const QRhiNativeHandles *nativeHandles() = 0;
138

139 140
    virtual void sendVMemStatsToProfiler();

141
    bool isCompressedFormat(QRhiTexture::Format format) const;
142
    void compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
143 144
                              quint32 *bpl, quint32 *byteSize,
                              QSize *blockDim) const;
145
    bool isFloatFormat(QRhiTexture::Format format) const;
146
    void textureFormatInfo(QRhiTexture::Format format, const QSize &size,
147
                           quint32 *bpl, quint32 *byteSize) const;
148 149
    quint32 approxByteSizeForTexture(QRhiTexture::Format format, const QSize &baseSize,
                                     int mipCount, int layerCount);
150

151 152
    QRhiProfilerPrivate *profilerPrivateOrNull()
    {
153
        // return null when QRhi::EnableProfiling was not set
154
        QRhiProfilerPrivate *p = QRhiProfilerPrivate::get(&profiler);
155
        return p->rhiDWhenEnabled ? p : nullptr;
156 157
    }

158
    // only really care about resources that own native graphics resources underneath
Laszlo Agocs's avatar
Laszlo Agocs committed
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
    void registerResource(QRhiResource *res)
    {
        resources.insert(res);
    }

    void unregisterResource(QRhiResource *res)
    {
        resources.remove(res);
    }

    QSet<QRhiResource *> activeResources() const
    {
        return resources;
    }

Laszlo Agocs's avatar
Laszlo Agocs committed
174 175 176 177 178 179 180 181
    void addReleaseAndDestroyLater(QRhiResource *res)
    {
        if (inFrame)
            pendingReleaseAndDestroyResources.insert(res);
        else
            res->releaseAndDestroy();
    }

182 183
    QRhi *q;

184
protected:
Laszlo Agocs's avatar
Laszlo Agocs committed
185 186 187
    bool debugMarkers = false;

private:
Laszlo Agocs's avatar
Laszlo Agocs committed
188 189
    QRhi::Implementation implType;
    QThread *implThread;
Laszlo Agocs's avatar
Laszlo Agocs committed
190
    QRhiProfiler profiler;
191 192
    QVector<QRhiResourceUpdateBatch *> resUpdPool;
    QBitArray resUpdPoolMap;
Laszlo Agocs's avatar
Laszlo Agocs committed
193
    QSet<QRhiResource *> resources;
Laszlo Agocs's avatar
Laszlo Agocs committed
194 195
    QSet<QRhiResource *> pendingReleaseAndDestroyResources;
    bool inFrame = false;
196 197

    friend class QRhi;
Laszlo Agocs's avatar
Laszlo Agocs committed
198
    friend class QRhiResourceUpdateBatchPrivate;
199 200
};

Laszlo Agocs's avatar
Laszlo Agocs committed
201
class QRhiResourceUpdateBatchPrivate
202
{
Laszlo Agocs's avatar
Laszlo Agocs committed
203
public:
204 205 206 207 208 209 210 211 212 213 214 215 216
    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;
        QByteArray data;
    };

    struct StaticBufferUpload {
        StaticBufferUpload() { }
Laszlo Agocs's avatar
Laszlo Agocs committed
217 218
        StaticBufferUpload(QRhiBuffer *buf_, int offset_, int size_, const void *data_)
            : buf(buf_), offset(offset_), data(reinterpret_cast<const char *>(data_), size_ ? size_ : buf_->size())
219 220 221
        { }

        QRhiBuffer *buf = nullptr;
Laszlo Agocs's avatar
Laszlo Agocs committed
222
        int offset = 0;
223 224 225
        QByteArray data;
    };

226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
    struct TextureOp {
        enum Type {
            TexUpload,
            TexCopy,
            TexRead,
            TexMipGen
        };
        Type type;
        struct Upload {
            QRhiTexture *tex = nullptr;
            QRhiTextureUploadDescription desc;
        } upload;
        struct Copy {
            QRhiTexture *dst = nullptr;
            QRhiTexture *src = nullptr;
            QRhiTextureCopyDescription desc;
        } copy;
        struct Read {
            QRhiReadbackDescription rb;
            QRhiReadbackResult *result;
        } read;
        struct MipGen {
            QRhiTexture *tex = nullptr;
        } mipgen;

        static TextureOp textureUpload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
        {
            TextureOp op;
            op.type = TexUpload;
            op.upload.tex = tex;
            op.upload.desc = desc;
            return op;
        }
259

260 261 262 263 264 265 266 267 268
        static TextureOp textureCopy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
        {
            TextureOp op;
            op.type = TexCopy;
            op.copy.dst = dst;
            op.copy.src = src;
            op.copy.desc = desc;
            return op;
        }
269

270 271 272 273 274 275 276 277
        static TextureOp textureRead(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
        {
            TextureOp op;
            op.type = TexRead;
            op.read.rb = rb;
            op.read.result = result;
            return op;
        }
278

279 280 281 282 283 284 285
        static TextureOp textureMipGen(QRhiTexture *tex)
        {
            TextureOp op;
            op.type = TexMipGen;
            op.mipgen.tex = tex;
            return op;
        }
Laszlo Agocs's avatar
Laszlo Agocs committed
286 287
    };

288 289
    QVector<DynamicBufferUpdate> dynamicBufferUpdates;
    QVector<StaticBufferUpload> staticBufferUploads;
290
    QVector<TextureOp> textureOps;
291 292 293 294 295 296

    QRhiResourceUpdateBatch *q = nullptr;
    QRhiImplementation *rhi = nullptr;
    int poolIndex = -1;

    void free();
297
    void merge(QRhiResourceUpdateBatchPrivate *other);
298 299 300 301 302 303

    static QRhiResourceUpdateBatchPrivate *get(QRhiResourceUpdateBatch *b) { return b->d; }
};

Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::StaticBufferUpload, Q_MOVABLE_TYPE);
304
Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::TextureOp, Q_MOVABLE_TYPE);
305

306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
class Q_RHI_PRIVATE_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;
334
        bool hasDynamicOffset;
335 336 337 338 339 340 341 342 343 344 345
    };
    struct SampledTextureData {
        QRhiTexture *tex;
        QRhiSampler *sampler;
    };
    union {
        UniformBufferData ubuf;
        SampledTextureData stex;
    } u;
};

346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
template<typename T>
struct QRhiBatchedBindings
{
    void feed(int binding, T resource) { // binding must be strictly increasing
        if (curBinding == -1 || binding > curBinding + 1) {
            finish();
            curBatch.startBinding = binding;
            curBatch.resources.clear();
            curBatch.resources.append(resource);
        } else {
            Q_ASSERT(binding == curBinding + 1);
            curBatch.resources.append(resource);
        }
        curBinding = binding;
    }

    void finish() {
        if (!curBatch.resources.isEmpty())
            batches.append(curBatch);
    }

    void clear() {
        batches.clear();
        curBatch.resources.clear();
        curBinding = -1;
    }

    struct Batch {
        uint startBinding;
        QVarLengthArray<T, 4> resources;
Laszlo Agocs's avatar
Laszlo Agocs committed
376 377 378 379 380

        bool operator==(const Batch &other) const
        {
            return startBinding == other.startBinding && resources == other.resources;
        }
381 382 383 384 385

        bool operator!=(const Batch &other) const
        {
            return !operator==(other);
        }
386 387 388 389
    };

    QVarLengthArray<Batch, 4> batches; // sorted by startBinding

Laszlo Agocs's avatar
Laszlo Agocs committed
390 391 392 393 394
    bool operator==(const QRhiBatchedBindings<T> &other) const
    {
        return batches == other.batches;
    }

395 396 397 398 399
    bool operator!=(const QRhiBatchedBindings<T> &other) const
    {
        return !operator==(other);
    }

400 401 402 403 404
private:
    Batch curBatch;
    int curBinding = -1;
};

Laszlo Agocs's avatar
Laszlo Agocs committed
405 406 407 408 409 410 411 412 413 414 415 416 417 418
class QRhiGlobalObjectIdGenerator
{
public:
#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
    using Type = quint64;
#else
    using Type = quint32;
#endif
    static Type newId();

private:
    QAtomicInteger<Type> counter;
};

419 420 421
QT_END_NAMESPACE

#endif