qrhimetal_p.h 13.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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
/****************************************************************************
**
** 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 QRHIMETAL_P_H
#define QRHIMETAL_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 "qrhimetal.h"
#include "qrhi_p.h"
#include <QShaderDescription>
#include <QWindow>

QT_BEGIN_NAMESPACE

static const int QMTL_FRAMES_IN_FLIGHT = 2;

// have to hide the ObjC stuff, this header cannot contain MTL* at all
struct QMetalBufferData;

struct QMetalBuffer : public QRhiBuffer
{
    QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
    ~QMetalBuffer();
    void release() override;
    bool build() override;

    QMetalBufferData *d;
    uint generation = 0;
    int lastActiveFrameSlot = -1;
Laszlo Agocs's avatar
Laszlo Agocs committed
66
    friend class QRhiMetal;
67
    friend struct QMetalShaderResourceBindings;
68 69
};

70 71
struct QMetalRenderBufferData;

72 73 74
struct QMetalRenderBuffer : public QRhiRenderBuffer
{
    QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
Laszlo Agocs's avatar
Laszlo Agocs committed
75
                       int sampleCount, QRhiRenderBuffer::Flags flags);
76
    ~QMetalRenderBuffer();
77 78
    void release() override;
    bool build() override;
Laszlo Agocs's avatar
Laszlo Agocs committed
79
    QRhiTexture::Format backingFormat() const override;
Laszlo Agocs's avatar
Laszlo Agocs committed
80

81
    QMetalRenderBufferData *d;
82
    int samples = 1;
83 84
    uint generation = 0;
    int lastActiveFrameSlot = -1;
Laszlo Agocs's avatar
Laszlo Agocs committed
85
    friend class QRhiMetal;
86 87
};

Laszlo Agocs's avatar
Laszlo Agocs committed
88 89
struct QMetalTextureData;

90 91
struct QMetalTexture : public QRhiTexture
{
Laszlo Agocs's avatar
Laszlo Agocs committed
92 93
    QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
                  int sampleCount, Flags flags);
Laszlo Agocs's avatar
Laszlo Agocs committed
94
    ~QMetalTexture();
95 96
    void release() override;
    bool build() override;
97 98
    bool buildFrom(const QRhiNativeHandles *src) override;
    const QRhiNativeHandles *nativeHandles() override;
Laszlo Agocs's avatar
Laszlo Agocs committed
99 100

    bool prepareBuild(QSize *adjustedSize = nullptr);
101

Laszlo Agocs's avatar
Laszlo Agocs committed
102
    QMetalTextureData *d;
103
    QRhiMetalTextureNativeHandles nativeHandlesStruct;
Laszlo Agocs's avatar
Laszlo Agocs committed
104
    int mipLevelCount = 0;
105
    int samples = 1;
106 107
    uint generation = 0;
    int lastActiveFrameSlot = -1;
Laszlo Agocs's avatar
Laszlo Agocs committed
108
    friend class QRhiMetal;
109
    friend struct QMetalShaderResourceBindings;
110 111
};

Laszlo Agocs's avatar
Laszlo Agocs committed
112 113
struct QMetalSamplerData;

114 115 116 117
struct QMetalSampler : public QRhiSampler
{
    QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
                  AddressMode u, AddressMode v, AddressMode w);
Laszlo Agocs's avatar
Laszlo Agocs committed
118
    ~QMetalSampler();
119 120 121
    void release() override;
    bool build() override;

Laszlo Agocs's avatar
Laszlo Agocs committed
122
    QMetalSamplerData *d;
123 124
    uint generation = 0;
    int lastActiveFrameSlot = -1;
Laszlo Agocs's avatar
Laszlo Agocs committed
125
    friend class QRhiMetal;
126
    friend struct QMetalShaderResourceBindings;
127 128
};

Laszlo Agocs's avatar
Laszlo Agocs committed
129
struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor
130
{
Laszlo Agocs's avatar
Laszlo Agocs committed
131
    QMetalRenderPassDescriptor(QRhiImplementation *rhi);
132 133 134
    void release() override;

    // there is no MTLRenderPassDescriptor here as one will be created for each pass in beginPass()
135

136
    // but the things needed for the render pipeline descriptor have to be provided
Laszlo Agocs's avatar
Laszlo Agocs committed
137
    static const int MAX_COLOR_ATTACHMENTS = 8;
138
    int colorAttachmentCount = 0;
139
    bool hasDepthStencil = false;
Laszlo Agocs's avatar
Laszlo Agocs committed
140
    int colorFormat[MAX_COLOR_ATTACHMENTS];
141
    int dsFormat;
142 143
};

144
struct QMetalRenderTargetData;
145

146
struct QMetalReferenceRenderTarget : public QRhiRenderTarget
147 148
{
    QMetalReferenceRenderTarget(QRhiImplementation *rhi);
149
    ~QMetalReferenceRenderTarget();
150
    void release() override;
151

152 153
    Type type() const override;
    QSize sizeInPixels() const override;
Laszlo Agocs's avatar
Laszlo Agocs committed
154
    float devicePixelRatio() const override;
155
    int sampleCount() const override;
156

157
    QMetalRenderTargetData *d;
158 159 160 161 162
};

struct QMetalTextureRenderTarget : public QRhiTextureRenderTarget
{
    QMetalTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
163
    ~QMetalTextureRenderTarget();
164
    void release() override;
Laszlo Agocs's avatar
Laszlo Agocs committed
165

166 167
    Type type() const override;
    QSize sizeInPixels() const override;
Laszlo Agocs's avatar
Laszlo Agocs committed
168
    float devicePixelRatio() const override;
169
    int sampleCount() const override;
170

Laszlo Agocs's avatar
Laszlo Agocs committed
171
    QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
Laszlo Agocs's avatar
Laszlo Agocs committed
172 173
    bool build() override;

174
    QMetalRenderTargetData *d;
Laszlo Agocs's avatar
Laszlo Agocs committed
175
    friend class QRhiMetal;
176 177 178 179 180 181 182 183
};

struct QMetalShaderResourceBindings : public QRhiShaderResourceBindings
{
    QMetalShaderResourceBindings(QRhiImplementation *rhi);
    void release() override;
    bool build() override;

184
    QVector<QRhiShaderResourceBinding> sortedBindings;
185
    int maxBinding = -1;
186 187

    struct BoundUniformBufferData {
188
        quint64 id;
189 190 191
        uint generation;
    };
    struct BoundSampledTextureData {
192
        quint64 texId;
193
        uint texGeneration;
194
        quint64 samplerId;
195 196 197 198 199 200 201 202 203 204
        uint samplerGeneration;
    };
    struct BoundResourceData {
        union {
            BoundUniformBufferData ubuf;
            BoundSampledTextureData stex;
        };
    };
    QVector<BoundResourceData> boundResourceData;

205
    uint generation = 0;
Laszlo Agocs's avatar
Laszlo Agocs committed
206
    friend class QRhiMetal;
207 208 209 210 211 212 213 214 215 216 217 218 219 220
};

struct QMetalGraphicsPipelineData;

struct QMetalGraphicsPipeline : public QRhiGraphicsPipeline
{
    QMetalGraphicsPipeline(QRhiImplementation *rhi);
    ~QMetalGraphicsPipeline();
    void release() override;
    bool build() override;

    QMetalGraphicsPipelineData *d;
    uint generation = 0;
    int lastActiveFrameSlot = -1;
Laszlo Agocs's avatar
Laszlo Agocs committed
221
    friend class QRhiMetal;
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
};

struct QMetalCommandBufferData;
struct QMetalSwapChain;

struct QMetalCommandBuffer : public QRhiCommandBuffer
{
    QMetalCommandBuffer(QRhiImplementation *rhi);
    ~QMetalCommandBuffer();
    void release() override;

    QMetalCommandBufferData *d = nullptr;

    QRhiRenderTarget *currentTarget;
    QRhiGraphicsPipeline *currentPipeline;
    uint currentPipelineGeneration;
    QRhiShaderResourceBindings *currentSrb;
    uint currentSrbGeneration;
240
    int currentResSlot;
241 242 243
    QRhiBuffer *currentIndexBuffer;
    quint32 currentIndexOffset;
    QRhiCommandBuffer::IndexFormat currentIndexFormat;
244

245
    void resetState();
246
    void resetPerPassState();
247 248 249 250 251 252 253 254 255 256 257 258
};

struct QMetalSwapChainData;

struct QMetalSwapChain : public QRhiSwapChain
{
    QMetalSwapChain(QRhiImplementation *rhi);
    ~QMetalSwapChain();
    void release() override;

    QRhiCommandBuffer *currentFrameCommandBuffer() override;
    QRhiRenderTarget *currentFrameRenderTarget() override;
259
    QSize surfacePixelSize() override;
260

Laszlo Agocs's avatar
Laszlo Agocs committed
261
    QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
Laszlo Agocs's avatar
Laszlo Agocs committed
262

Laszlo Agocs's avatar
Laszlo Agocs committed
263
    bool buildOrResize() override;
264

265 266
    void chooseFormats();

267
    QWindow *window = nullptr;
Laszlo Agocs's avatar
Laszlo Agocs committed
268
    QSize pixelSize;
269 270
    int currentFrameSlot = 0; // 0..QMTL_FRAMES_IN_FLIGHT-1
    int frameCount = 0;
271
    int samples = 1;
272 273 274 275 276 277 278 279 280 281 282
    QMetalReferenceRenderTarget rtWrapper;
    QMetalCommandBuffer cbWrapper;
    QMetalRenderBuffer *ds = nullptr;
    QMetalSwapChainData *d = nullptr;
};

struct QRhiMetalData;

class QRhiMetal : public QRhiImplementation
{
public:
283
    QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *importDevice = nullptr);
284 285
    ~QRhiMetal();

286
    bool create(QRhi::Flags flags) override;
287 288
    void destroy() override;

289 290 291 292 293 294 295 296
    QRhiGraphicsPipeline *createGraphicsPipeline() override;
    QRhiShaderResourceBindings *createShaderResourceBindings() override;
    QRhiBuffer *createBuffer(QRhiBuffer::Type type,
                             QRhiBuffer::UsageFlags usage,
                             int size) override;
    QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
                                         const QSize &pixelSize,
                                         int sampleCount,
Laszlo Agocs's avatar
Laszlo Agocs committed
297
                                         QRhiRenderBuffer::Flags flags) override;
298 299
    QRhiTexture *createTexture(QRhiTexture::Format format,
                               const QSize &pixelSize,
Laszlo Agocs's avatar
Laszlo Agocs committed
300
                               int sampleCount,
301 302 303 304 305 306 307 308 309
                               QRhiTexture::Flags flags) override;
    QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
                               QRhiSampler::Filter mipmapMode,
                               QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) override;

    QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
                                                       QRhiTextureRenderTarget::Flags flags) override;

    QRhiSwapChain *createSwapChain() override;
310 311
    QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
    QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
312
    QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
313 314
    QRhi::FrameOpResult endOffscreenFrame() override;
    QRhi::FrameOpResult finish() override;
315

316 317 318 319
    void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;

    void beginPass(QRhiCommandBuffer *cb,
                   QRhiRenderTarget *rt,
320 321 322
                   const QRhiColorClearValue &colorClearValue,
                   const QRhiDepthStencilClearValue &depthStencilClearValue,
                   QRhiResourceUpdateBatch *resourceUpdates) override;
323
    void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
324 325

    void setGraphicsPipeline(QRhiCommandBuffer *cb,
326 327 328 329 330
                             QRhiGraphicsPipeline *ps) override;

    void setShaderResources(QRhiCommandBuffer *cb,
                            QRhiShaderResourceBindings *srb,
                            const QVector<QRhiCommandBuffer::DynamicOffset> &dynamicOffsets) override;
331 332

    void setVertexInput(QRhiCommandBuffer *cb,
333
                        int startBinding, const QVector<QRhiCommandBuffer::VertexInput> &bindings,
334
                        QRhiBuffer *indexBuf, quint32 indexOffset,
335
                        QRhiCommandBuffer::IndexFormat indexFormat) override;
336 337 338 339 340 341 342 343 344 345 346 347 348

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

    void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
              quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;

    void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
                     quint32 instanceCount, quint32 firstIndex,
                     qint32 vertexOffset, quint32 firstInstance) override;

349 350 351 352
    void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
    void debugMarkEnd(QRhiCommandBuffer *cb) override;
    void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;

353 354 355
    QVector<int> supportedSampleCounts() const override;
    int ubufAlignment() const override;
    bool isYUpInFramebuffer() const override;
Laszlo Agocs's avatar
Laszlo Agocs committed
356
    bool isYUpInNDC() const override;
357
    QMatrix4x4 clipSpaceCorrMatrix() const override;
358
    bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
359
    bool isFeatureSupported(QRhi::Feature feature) const override;
Laszlo Agocs's avatar
Laszlo Agocs committed
360
    int resourceLimit(QRhi::ResourceLimit limit) const override;
361
    const QRhiNativeHandles *nativeHandles() override;
362 363

    void executeDeferredReleases(bool forced = false);
364
    void finishActiveReadbacks(bool forced = false);
365
    void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
366
    void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);
367 368 369
    void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD, QMetalCommandBuffer *cbD,
                                       const QVector<QRhiCommandBuffer::DynamicOffset> &dynamicOffsets,
                                       bool offsetOnlyChange);
370
    int effectiveSampleCount(int sampleCount) const;
371 372

    bool importedDevice = false;
373
    bool importedCmdQueue = false;
374 375 376
    bool inFrame = false;
    int currentFrameSlot = 0;
    bool inPass = false;
377
    QMetalSwapChain *currentSwapChain = nullptr;
378
    QSet<QMetalSwapChain *> swapchains;
379
    QRhiMetalNativeHandles nativeHandlesStruct;
380

381 382 383 384
    struct {
        int maxTextureSize = 4096;
    } caps;

385 386 387 388 389 390
    QRhiMetalData *d = nullptr;
};

QT_END_NAMESPACE

#endif