qrhimetal_p.h 12.7 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
/****************************************************************************
**
** 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();
60
    bool isShareable() const override;
61 62 63 64 65 66
    void release() override;
    bool build() override;

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

Laszlo Agocs's avatar
Laszlo Agocs committed
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);
Laszlo Agocs's avatar
Laszlo Agocs committed
76
    ~QMetalRenderBuffer();
77
    bool isShareable() const override;
78 79
    void release() override;
    bool build() override;
Laszlo Agocs's avatar
Laszlo Agocs committed
80
    QRhiTexture::Format backingFormat() const override;
Laszlo Agocs's avatar
Laszlo Agocs committed
81

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

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

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

    bool prepareBuild(QSize *adjustedSize = nullptr);
103

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

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

115 116 117 118
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
119
    ~QMetalSampler();
120
    bool isShareable() const override;
121 122 123
    void release() override;
    bool build() override;

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

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

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

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

145
struct QMetalRenderTargetData;
146 147 148 149

struct QMetalReferenceRenderTarget : public QRhiReferenceRenderTarget
{
    QMetalReferenceRenderTarget(QRhiImplementation *rhi);
150
    ~QMetalReferenceRenderTarget();
151
    void release() override;
152

153 154
    Type type() const override;
    QSize sizeInPixels() const override;
Laszlo Agocs's avatar
Laszlo Agocs committed
155
    float devicePixelRatio() 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

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

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

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

183
    QVector<QRhiShaderResourceBinding> sortedBindings;
184
    int maxBinding = -1;
Laszlo Agocs's avatar
Laszlo Agocs committed
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200

    struct BoundUniformBufferData {
        uint generation;
    };
    struct BoundSampledTextureData {
        uint texGeneration;
        uint samplerGeneration;
    };
    struct BoundResourceData {
        union {
            BoundUniformBufferData ubuf;
            BoundSampledTextureData stex;
        };
    };
    QVector<BoundResourceData> boundResourceData;

201
    uint generation = 0;
Laszlo Agocs's avatar
Laszlo Agocs committed
202
    friend class QRhiMetal;
203 204 205 206 207 208 209 210 211 212 213 214 215 216
};

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
217
    friend class QRhiMetal;
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
};

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;
Laszlo Agocs's avatar
Laszlo Agocs committed
236
    int currentResSlot;
237 238 239
    QRhiBuffer *currentIndexBuffer;
    quint32 currentIndexOffset;
    QRhiCommandBuffer::IndexFormat currentIndexFormat;
240

241
    void resetState();
242
    void resetPerPassState();
243 244 245 246 247 248 249 250 251 252 253 254
};

struct QMetalSwapChainData;

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

    QRhiCommandBuffer *currentFrameCommandBuffer() override;
    QRhiRenderTarget *currentFrameRenderTarget() override;
255
    QSize surfacePixelSize() override;
256

Laszlo Agocs's avatar
Laszlo Agocs committed
257
    QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
Laszlo Agocs's avatar
Laszlo Agocs committed
258

Laszlo Agocs's avatar
Laszlo Agocs committed
259
    bool buildOrResize() override;
260

261 262
    void chooseFormats();

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

struct QRhiMetalData;

class QRhiMetal : public QRhiImplementation
{
public:
279
    QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *importDevice = nullptr);
280 281
    ~QRhiMetal();

282
    bool create(QRhi::Flags flags) override;
283 284
    void destroy() override;

285 286 287 288 289 290 291 292
    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
293
                                         QRhiRenderBuffer::Flags flags) override;
294 295
    QRhiTexture *createTexture(QRhiTexture::Format format,
                               const QSize &pixelSize,
Laszlo Agocs's avatar
Laszlo Agocs committed
296
                               int sampleCount,
297 298 299 300 301 302 303 304 305 306 307
                               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;
    QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain) override;
    QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain) override;
308
    QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
309 310
    QRhi::FrameOpResult endOffscreenFrame() override;
    QRhi::FrameOpResult finish() override;
311

312 313 314 315
    void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;

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

    void setGraphicsPipeline(QRhiCommandBuffer *cb,
                             QRhiGraphicsPipeline *ps,
                             QRhiShaderResourceBindings *srb) override;

    void setVertexInput(QRhiCommandBuffer *cb,
326
                        int startBinding, const QVector<QRhiCommandBuffer::VertexInput> &bindings,
327
                        QRhiBuffer *indexBuf, quint32 indexOffset,
328
                        QRhiCommandBuffer::IndexFormat indexFormat) override;
329 330 331 332 333 334 335 336 337 338 339 340 341

    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;

342 343 344 345
    void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
    void debugMarkEnd(QRhiCommandBuffer *cb) override;
    void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;

346 347 348 349
    QVector<int> supportedSampleCounts() const override;
    int ubufAlignment() const override;
    bool isYUpInFramebuffer() const override;
    QMatrix4x4 clipSpaceCorrMatrix() const override;
350
    bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
Laszlo Agocs's avatar
Laszlo Agocs committed
351
    bool isFeatureSupported(QRhi::Feature feature) const override;
352
    int resourceSizeLimit(QRhi::ResourceSizeLimit limit) const override;
353
    const QRhiNativeHandles *nativeHandles() override;
354 355

    void executeDeferredReleases(bool forced = false);
356
    void finishActiveReadbacks(bool forced = false);
357
    void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
358
    void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);
Laszlo Agocs's avatar
Laszlo Agocs committed
359
    void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD, QMetalCommandBuffer *cbD);
360
    int effectiveSampleCount(int sampleCount) const;
361 362

    bool importedDevice = false;
363
    bool importedCmdQueue = false;
364 365 366
    bool inFrame = false;
    int currentFrameSlot = 0;
    bool inPass = false;
367
    QMetalSwapChain *currentSwapChain = nullptr;
Laszlo Agocs's avatar
Laszlo Agocs committed
368
    QSet<QMetalSwapChain *> swapchains;
369
    QRhiMetalNativeHandles nativeHandlesStruct;
370

371 372 373 374
    struct {
        int maxTextureSize = 4096;
    } caps;

375 376 377 378 379 380
    QRhiMetalData *d = nullptr;
};

QT_END_NAMESPACE

#endif