qrhimetal_p.h 10.6 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 68
};

Laszlo Agocs's avatar
Laszlo Agocs committed
69 70
struct QMetalRenderBufferData;

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

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

Laszlo Agocs's avatar
Laszlo Agocs committed
85 86
struct QMetalTextureData;

87 88 89
struct QMetalTexture : public QRhiTexture
{
    QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, Flags flags);
Laszlo Agocs's avatar
Laszlo Agocs committed
90
    ~QMetalTexture();
91 92 93
    void release() override;
    bool build() override;

Laszlo Agocs's avatar
Laszlo Agocs committed
94
    QMetalTextureData *d;
Laszlo Agocs's avatar
Laszlo Agocs committed
95
    int mipLevelCount = 0;
96 97
    uint generation = 0;
    int lastActiveFrameSlot = -1;
Laszlo Agocs's avatar
Laszlo Agocs committed
98
    friend class QRhiMetal;
99 100
};

Laszlo Agocs's avatar
Laszlo Agocs committed
101 102
struct QMetalSamplerData;

103 104 105 106
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
107
    ~QMetalSampler();
108 109 110
    void release() override;
    bool build() override;

Laszlo Agocs's avatar
Laszlo Agocs committed
111
    QMetalSamplerData *d;
112 113
    uint generation = 0;
    int lastActiveFrameSlot = -1;
Laszlo Agocs's avatar
Laszlo Agocs committed
114
    friend class QRhiMetal;
115 116
};

Laszlo Agocs's avatar
Laszlo Agocs committed
117
struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor
118
{
Laszlo Agocs's avatar
Laszlo Agocs committed
119
    QMetalRenderPassDescriptor(QRhiImplementation *rhi);
120 121 122
    void release() override;

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

124
    // but the things needed for the render pipeline descriptor have to be provided
Laszlo Agocs's avatar
Laszlo Agocs committed
125
    static const int MAX_COLOR_ATTACHMENTS = 8;
Laszlo Agocs's avatar
Laszlo Agocs committed
126
    int colorAttachmentCount = 0;
127
    bool hasDepthStencil = false;
Laszlo Agocs's avatar
Laszlo Agocs committed
128
    int colorFormat[MAX_COLOR_ATTACHMENTS];
129
    int dsFormat;
130 131
};

132
struct QMetalRenderTargetData;
133 134 135 136

struct QMetalReferenceRenderTarget : public QRhiReferenceRenderTarget
{
    QMetalReferenceRenderTarget(QRhiImplementation *rhi);
137
    ~QMetalReferenceRenderTarget();
138
    void release() override;
139

140 141 142
    Type type() const override;
    QSize sizeInPixels() const override;

143
    QMetalRenderTargetData *d;
144 145 146 147 148
};

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

152 153 154
    Type type() const override;
    QSize sizeInPixels() const override;

Laszlo Agocs's avatar
Laszlo Agocs committed
155
    QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
Laszlo Agocs's avatar
Laszlo Agocs committed
156 157
    bool build() override;

158
    QMetalRenderTargetData *d;
Laszlo Agocs's avatar
Laszlo Agocs committed
159
    friend class QRhiMetal;
160 161 162 163 164 165 166 167
};

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

168
    QVector<QRhiShaderResourceBinding> sortedBindings;
169 170
    int maxBinding = -1;
    uint generation = 0;
Laszlo Agocs's avatar
Laszlo Agocs committed
171
    friend class QRhiMetal;
172 173 174 175 176 177 178 179 180 181 182 183 184 185
};

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
186
    friend class QRhiMetal;
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
};

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
205 206 207
    QRhiBuffer *currentIndexBuffer;
    quint32 currentIndexOffset;
    QRhi::IndexFormat currentIndexFormat;
208

209
    void resetState();
210 211 212 213 214 215 216 217 218 219 220 221
};

struct QMetalSwapChainData;

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

    QRhiCommandBuffer *currentFrameCommandBuffer() override;
    QRhiRenderTarget *currentFrameRenderTarget() override;
222
    QSize effectivePixelSize() const override;
223

Laszlo Agocs's avatar
Laszlo Agocs committed
224
    QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
Laszlo Agocs's avatar
Laszlo Agocs committed
225

Laszlo Agocs's avatar
Laszlo Agocs committed
226
    bool buildOrResize() override;
227

Laszlo Agocs's avatar
Laszlo Agocs committed
228
    QSize pixelSize;
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 259 260 261 262 263 264 265
    int currentFrame = 0; // 0..QMTL_FRAMES_IN_FLIGHT-1
    QMetalReferenceRenderTarget rtWrapper;
    QMetalCommandBuffer cbWrapper;
    QMetalRenderBuffer *ds = nullptr;
    QMetalSwapChainData *d = nullptr;
};

struct QRhiMetalData;

class QRhiMetal : public QRhiImplementation
{
public:
    QRhiMetal(QRhiInitParams *params);
    ~QRhiMetal();

    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,
                                         QRhiRenderBuffer::Hints hints) override;
    QRhiTexture *createTexture(QRhiTexture::Format format,
                               const QSize &pixelSize,
                               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;
266
    QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
267
    QRhi::FrameOpResult endOffscreenFrame() override;
268
    bool readback(QRhiCommandBuffer *cb, const QRhiReadbackDescription &rb, QRhiReadbackResult *result) override;
269
    QRhi::FrameOpResult finish() override;
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302

    void beginPass(QRhiRenderTarget *rt,
                   QRhiCommandBuffer *cb,
                   const QRhiColorClearValue &colorClearValue,
                   const QRhiDepthStencilClearValue &depthStencilClearValue,
                   QRhiResourceUpdateBatch *resourceUpdates) override;
    void endPass(QRhiCommandBuffer *cb) override;

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

    void setVertexInput(QRhiCommandBuffer *cb,
                        int startBinding, const QVector<QRhi::VertexInput> &bindings,
                        QRhiBuffer *indexBuf, quint32 indexOffset,
                        QRhi::IndexFormat indexFormat) override;

    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;

    QVector<int> supportedSampleCounts() const override;
    int ubufAlignment() const override;
    bool isYUpInFramebuffer() const override;
    QMatrix4x4 clipSpaceCorrMatrix() const override;
303
    bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
304 305 306 307

    void create();
    void destroy();
    void executeDeferredReleases(bool forced = false);
Laszlo Agocs's avatar
Laszlo Agocs committed
308
    void commitResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
309 310 311 312 313 314 315 316 317 318 319 320 321 322
    void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);

    bool importedDevice = false;
    bool inFrame = false;
    int currentFrameSlot = 0;
    int finishedFrameCount = 0;
    bool inPass = false;

    QRhiMetalData *d = nullptr;
};

QT_END_NAMESPACE

#endif